美文网首页
[Swift] OC 泛型参数为协议的集合到 Swift 的桥接

[Swift] OC 泛型参数为协议的集合到 Swift 的桥接

作者: BudSwift | 来源:发表于2020-06-25 16:56 被阅读0次

0x0 背景

目前 OC 的泛型使用已经逐渐被 Apple Developer 所接受,可以阅读早期的介绍文章,使用泛型可以更好地保证集合操作的安全性,在类型不符时编译器可以提出警告,而泛型一般在系统框架的集合类型中使用,比如 NSArray,NSDictionary 等。
比如声明带有泛型参数的集合类型变量:

NSArray <NSString *> *names = ...;
NSMutableDictionary <NSNumber *, NSNumber *> *sectionStatus = ...;

又比如,使用 block 的方式遍历带有泛型参数的集合类型时 Xcode 会自动生成内部对象的类型信息:

[array enumerateObjectsUsingBlock:^(SomeClass * _Nonnull obj,
                                    NSUInteger idx,
                                    BOOL * _Nonnull stop) {
    // enumerate the array using block
}];

在实际的使用中,有时候会用到将不明确具体类型而是遵循某种特定协议的对象,以 array 为例,可能有如下声明方式

 NSArray <SomeProtocol> *array1 = ...;
 NSArray <id<SomeProtocol>> *array2 = ...;
 NSArray <SomeClass<SomeProtocol> *> *array3 = ...;

那么分析讨论下如何去理解和使用泛型参数为协议的集合。

0x1 分析

  • 写法 1: NSArray <SomeProtocol> *array1 认真地看,其实这不是泛型数组,而是遵循了 SomeProtocol 的数组对象。
  • 写法 2:NSArray <id<SomeProtocol>> * 这种写法完全正确,编译器会有很好的泛型支持,可以联想类比 UITableView 的 delegate 声明,所表达的含义是任意遵循 SomeProtocol 的 OC 对象
// objc.h
typedef struct objc_object *id
  • 写法 3:NSArray <SomeClass<SomeProtocol> *> * 也符合要求,与写法 2 的区别在于,这次泛型参数要求对象遵循协议的同时还要继承自某个类(在这里是继承自 SomeClass)。

根据上述分析,不难得出如上三种写法桥接到 Swift 的结果:

let array1: [Any] = ...;
let array2: [SomeProtocol] = ...;
let array3: [SomeClass & SomeProtocol] = ...;

也就是说写法 1 的对应到 Swift 为 Any Array 类型,这是 OC 数组因为桥接后没有了协议信息,如果是普通对象则不会,例如:

- (void)funcWithObject:(SomeClass<SomeProtocol> *)object;

桥接到 Swift 则是这样:

func func(withObject object: SomeClass & SomeProtocol)

而后面两种则符合预期的表现,实际开发中应避免看似简便实际无效的写法 1,根据场景使用写法 2 或者写法 3。

~~~ 加个V,交个友 😆

V🌊@席萍萍Brook
V❤️:↓↓

微信|

EOF

相关文章

网友评论

      本文标题:[Swift] OC 泛型参数为协议的集合到 Swift 的桥接

      本文链接:https://www.haomeiwen.com/subject/icisfktx.html