1、Associated Type (关联类型)
Swift is a Protocol-Oriented Language, so we need to change our Object-Oriented mindset.
Swift是一种面向协议的语言,因此我们需要改变面向对象的思维方式。
??:
Associated Types (关联类型) 的作用?
- 在协议中使用范型。
定义一个协议时,有的时候声明一个或多个关联类型作为协议定义的一部分将会非常有用。关联类型为协议中的某个类型提供了一个占位名(或说别名),其代表的实际类型在协议被采纳时才会被指定。你可以通过 associatedtype
关键字来指定关联类型.
// Protocols with Associated Types 举例
struct Model {
let age: Int
}
//协议,使用关联类型
protocol TableViewCell {
associatedtype T
func updateCell(_ data: T)
}
//遵守TableViewCell
class MyTableViewCell: UITableViewCell, TableViewCell {
typealias T = Model
func updateCell(_ data: Model) {
// do something ...
}
}
2、Associated Values (关联值)
Associated Values 是Swift新增的强大的Enumeration特性。
You can define Swift enumerations to store associated values of any given type, and the value types can be different for each case of the enumeration if needed.
您可以定义Swift枚举来存储任何给定类型的关联值,如果需要,枚举的每种情况下的值类型都可以不同。
??:
写一个associated value 的枚举(enum)?
// 带有关联值的枚举
enum Barcode {
// 条形码 UPC :(number system digit,制造商代码,产品代码,校验位)
case upc(Int, Int, Int, Int)
case qrCode(String)
}
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = Barcode.qrCode("ABCDEFGHIJKLMNOP")
switch productBarcode {
case let .upc(numberSystem, manufacturer, product, check):
print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).")
case let .qrCode(productCode):
print("QR code: \(productCode).")
}
通过Associated Values,你可以定义包含更多信息的枚举,如图为了追踪商品,每一个商品可以有一个条形码或一个者二维码。相比传统的简单枚举,带有关联值的枚举拥有更多的信息。
// 简单枚举
enum Barcode {
case upc // 条形码
case qrCode // 二维码
}
3、Associated Object(关联对象)
所谓关联对象,其实就是我们在运行时对一个已存在的对象上面绑定一个对象,使两个对象变成动态的聚合关系。
??:
通过Category 给已有的类添加成员变量?
React Native 源码🌰
// React Native 源码的例子
@interface UIView (React) <RCTComponent>
@property (nonatomic, copy) NSString *nativeID;
@end
//================================================
@implementation UIView (React)
- (NSNumber *)nativeID
{
return objc_getAssociatedObject(self, _cmd); // 此处 _cmd == @selector(nativeID)
}
- (void)setNativeID:(NSNumber *)nativeID
{
objc_setAssociatedObject(self, @selector(nativeID), nativeID, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
// nativeID的类型 NSNumber* 和 NSString * 还不同,不知道算不算是bug?
文档API:
/**
* Sets an associated value for a given object using a given key and association policy.
*
* @param object The source object for the association.
* @param key The key for the association.
* @param value The value to associate with the key key for object. Pass nil to clear an existing association.
* @param policy The policy for the association. For possible values, see “Associative Object Behaviors.”
*
*/
OBJC_EXPORT void
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,
id _Nullable value, objc_AssociationPolicy policy)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0, 2.0);
OC的编译器在编译后会在每个方法中加两个隐藏的参数:
一个是_cmd
,当前方法的一个SEL指针。
一个是self
,指向当前对象的一个指针。