__kindof之间的区别与不在Objective-C中使用它

Dar*_*kas 9 objective-c nsarray ios

我已经阅读了有关iOS中Objective-C的一些新功能的文章.但是,我无法得到这两种方式的主要区别:

@property (strong, nonatomic, nonnull) NSArray<UIView *> *someViews;
Run Code Online (Sandbox Code Playgroud)

@property (strong, nonatomic, nonnull) NSArray<__kindof UIView *> *someViews;
Run Code Online (Sandbox Code Playgroud)

对我来说,它们看起来很相似.有什么区别,什么时候我应该使用另一个?

luk*_*302 14

为了看到__kindof我的全部效果,我建议只使用它并看看不同的结果:

NSMutableArray<UIView *> *views;
NSMutableArray<__kindof UIView *> *subviews;

views = [NSMutableArray new];
subviews = [NSMutableArray new];

UIView *someView = [UIView new];

[subviews addObject:someView];
[views addObject:someView];

UIButton *someSubview = [UIButton new];

[subviews addObject:someSubview];
[views addObject:someSubview];
Run Code Online (Sandbox Code Playgroud)

到目前为止,插入到不同的通用数组中.编译和运行都很好.没有警告,没有崩溃.

然而有趣的部分是从数组读取 - 请记住,在两个数组的第一个插槽中是实际的UIView*,在第二个插槽中是UIButton*

UIView *extView00 = views[0];
UIView *extView01 = subviews[0];
UIView *extView10 = views[1];
UIView *extView11 = subviews[1];

UIButton *extButton00 = views[0]; <-- warning
UIButton *extButton01 = subviews[0];
UIButton *extButton10 = views[1]; <-- warning
UIButton *extButton11 = subviews[1];
Run Code Online (Sandbox Code Playgroud)

这将运行正常,但为标记的行提供两个编译器警告:

不兼容的指针类型使用"UIView*"类型的表达式初始化"UIButton*"

其他两行按预期工作.当然还没有崩溃.但是我们遇到了一些问题:extButton01包含UIView*但看起来像是一个UIButton*.

因此添加以下内容

NSLog(@"%@", extButton00.titleLabel);
NSLog(@"%@", extButton01.titleLabel);
NSLog(@"%@", extButton10.titleLabel);
NSLog(@"%@", extButton11.titleLabel);
Run Code Online (Sandbox Code Playgroud)

在第一行和第二行按预期崩溃.如果我们删除整个视图数组,我们最终将获得无警告但崩溃的代码.而且我不喜欢崩溃但是没有警告的代码.当然,无警告并不保证没有崩溃,但为方便起见删除警告不是一个好主意恕我直言.

结论

是的,该功能可以很好地删除演员阵容.它也删除了不匹配类型可能有用的警告.如果您100%确定索引X处的对象是T类型,那么您可以选择使用subviews方法__kindof.

我个人将会/现在不会使用它 - 直到我遇到一个我看不到的非常非常好的用例.


Cy-*_*4AH 4

一切都很简单。在第一种情况下,您需要编写:

UILabel* titleLabel = (typeof(titleLabel))someViews[0];
Run Code Online (Sandbox Code Playgroud)

在第二个你可以写:

UILabel* titleLabel = someViews[0];
Run Code Online (Sandbox Code Playgroud)

您应该选择您喜欢的方式:隐式或显式类型转换。

  • @luk2302 在 Objective-C 中,我们通常*根本*不指定数组包含的对象类型。数组可以同时包含字符串和数字以及视图和视图控制器。将字符串和视图放在同一个数组中通常不太有用,因此大多数时候您可以获得有关对象类型的更多信息。但在同一个集合中拥有几种不同类型的视图通常很有用。告诉编译器它可以期望组中的每个对象都是“某种”视图,可以提高安全性,而不会使代码变得笨拙。 (2认同)