Objective-C 与 泛型

2021-02-01 11:13:39 浏览数 (1)

Objective-C 与 泛型

从 Xcode 7 开始,为了更简单和高效的与 Swift 交互, Objective-C 支持了引入了 3 个高级特性:轻量泛型Nullability annotationKindOf

本文希望对 轻量泛型 做一个简单的介绍。更多信息,请参考 llvm 或者 与 Objective-C API 交互[1]

轻量泛型 是什么?

轻量泛型 可以让开发者执行集合类的类型信息,并且支持与 Swift 的泛型系统进行相互转化。

为什么使用 轻量泛型?

通常情况下,我们使用下面的语法声明数组:

代码语言:javascript复制
NSArray *dates;

通过在类型后面添加 <NSDate *>,我们可以告诉编译器:这个数组只接受 NSDate 类型的实例

代码语言:javascript复制
NSArray<NSDate *> *dates;

下面,我们通过实例验证一下它的作用:

代码语言:javascript复制
NSArray<NSDate *> *dates;
NSString *str = dates[2];

当我们编译上述代码时,clang 在语法校验时会自动提示 ⚠️ 信息:NSDateNSString 不兼容

image-20210105220623395

解决该 ⚠️ 的方案也很简单,把 NSString 换成 NSDate 即可。

代码语言:javascript复制
NSDate *date = dates[2];

如何让自己的类支持 轻量泛型?

1、如下所示,声明类型时,开发者需要在 类名 后面新增一些typedef-names[2]

代码语言:javascript复制
@interface NSCovariant1<T>
@interface NSCovariant1<T, U : NSObject *>

2、在实例方法或者类方法中,使用 T 代替普通的类型声明

代码语言:javascript复制
- (void)setObject:(U)obj forKeyedSubscript:(T)key;

验证

下面,我们写一个完整的 Demo 对上面的功能进行验证:

代码语言:javascript复制
// main.m

@import Foundation;

@interface KKMutableDictionary<KeyType, ObjectType> : NSObject

- (void)setObject:(nullable ObjectType)obj forKeyedSubscript:(KeyType <NSCopying>)key;

@end

@implementation KKMutableDictionary

- (void)setObject:(nullable id)obj forKeyedSubscript:(id <NSCopying>)key {

}

@end

int main() {
    KKMutableDictionary<NSString *, NSDate *> *dic = [KKMutableDictionary new];
    dic[@"today"] = @"2021-01-01";
    dic[@"today"] = [NSDate date];
    dic[@"today"] = nil;
    NSLog(@"%@", dic);
}

进行语法检测并打印语法树:

代码语言:javascript复制
xcrun clang -fmodules -fsyntax-only -Xclang -ast-dump main.m

1、语法检测会提示 dic[@"today"] = @"2021-01-01"; 存在类型兼容问题

image-20210105223501712

2、源码的第 5 行的语法树如下:

image-20210105223959567

我们简单对上面的语法树进行讲解:

  • ObjCInterfaceDecl 代表类的声明,本例中是 KKMutableDictionary
  • 随后,是父类 NSObject
  • 最后是两个 ObjCTypeParamDecl : KeyTypeObjectTYpe

总结

本文分享了轻量泛型的用法,并通过 clang 命令将对应的语法树进行了介绍。

参考资料

[1]

与 Objective-C API 交互: https://github.com/949478479/Using-Swift-with-Cocoa-and-Objective-C-in-Chinese/blob/master/02-Interoperability/01-Interacting with Objective-C APIs.md#lightweight_generics

[2]

typedef-names: https://clang.llvm.org/doxygen/DeclObjC_8h_source.html#l00567

0 人点赞