美文网首页
[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