此语法正确:
NSArray <__kindof id <MyProtocol>> *array = ...
也可以省略
__kindof
,并且仍然喜欢轻量级泛型。即使没有该关键字,它仍然会警告您添加错误类型的对象。这个
__有点
如果要将对象从该数组中拉出并将其指定给不带强制转换的子类型,则使用,否则不需要\uu kindof:
NSArray <id <MyProtocol>> *array = ...
如果将特定类型的对象添加到数组中,但该类型不符合
MyProtocol
。
这不会警告您的是,如果您尝试添加类型为的对象
id
它本身。因此,避免使用不合格的
id号
在代码中键入,您将享受轻量级泛型。
如果仍然没有看到警告,请确保已看到
-Wobjc-literal-conversion
警告已打开。因此,返回第一个项目的构建设置并搜索“literal”,您将看到该设置(称为“隐式Objective-C literal转换”)。
考虑以下示例:
@protocol MyProtocol
@end
@interface Foo: NSObject <MyProtocol>
@end
@interface Bar: Foo
@end
@interface Baz: NSObject
@end
然后考虑:
Foo *foo = [[Foo alloc] init];
Bar *bar = [[Bar alloc] init];
Baz *baz = [[Baz alloc] init];
id qux = [[Baz alloc] init];
NSArray <id <MyProtocol>> *array1;
array1 = @[foo, bar, baz, qux]; // warning: object of type 'Baz *' is not compatible with array element type 'Foo *'
注意,这警告我们
baz
,但不是
qux
。所以要小心使用
id号
类型。
id <MyProtocol> object1 = array1[0];
因此,这就是将该协议作为轻量级泛型使用,并按预期工作。
你添加的唯一原因
__有点
如果要避免此警告:
Foo *foo1 = array1[0]; // warning: initializing 'Foo *__strong' with an expression of incompatible type 'id<MyProtocol> _Nullable'
在这种情况下,您可以使用
__有点
:
NSArray <__kindof id <MyProtocol>> *array2;
array2 = @[foo, bar, baz]; // again, warning: object of type 'Baz *' is not compatible with array element type 'Foo *'
id <MyProtocol> object2 = array2[0]; // no warning, great
Foo *foo2 = array2[0]; // no warning, great