gpt4 book ai didi

iOS 向后兼容性 - 一个不存在的类的分配/初始化

转载 作者:行者123 更新时间:2023-11-28 22:34:14 25 4
gpt4 key购买 nike

背景:

假设我正在使用 iOS 6 SDK 开发应用程序。我将我的部署目标设置为 iOS 5。然后我可以使用 6 中的功能,但为了保持与 5 的兼容性,您必须在代码中进行一些检查:

// method only available from 6, class of someObj existed in 5
if (someObj respondToSelector:@selector(aMethod)) {
[someObj aMethod];
}

或者

// entire class only available from 6
if (NSStringFromClass([SKStoreProductViewController class]) != nil) {
SKStoreProductViewController *store = [[SKStoreProductViewController alloc] init];
}

到目前为止一切顺利。据我所知,这些是标准的做事方式。

但我今天发现对于新类示例,如果我只是尝试分配/初始化一个对象从那个类开始,没有任何检查,它不会在我期望的 iOS 5 上崩溃,而是返回 null。

// run this on an iOS 5 device
NSLog(@"%@", [UICollectionView alloc] init]);

为什么这不会导致 iOS 5 崩溃?我想这与链接器可以工作,但我预计会发生崩溃,因为该版本中不存在该符号。

第二个问题是:如果正常测试是使用 NSStringFromClass 方法,这意味着您可以将 +class 方法发送到一个不存在的类,它会返回 null - 为什么/如何工作?

最后,我注意到我可以创建一个 ViewController,它采用仅在 iOS 6 中定义的协议(protocol),并且在 iOS 5 上也不会出现任何问题。?

最佳答案

此行为是由于 NS_CLASS_AVAILABLE 宏造成的。这个宏已经在大多数(所有?)UIKit 类上实现,并且对于不可用的类将返回 nil。这允许您使用代码检查特定 iOS 版本上是否存在类:

if ([UICollectionView class]) {
// class exists, must be iOS6+
}

现在,您对 [[UICollectionView alloc] init] 的调用是对 nil 类的类方法调用,它将始终返回 nil。

要回答您的次要问题,检查类是否存在的正确方法是检查类是否为 nil,如上所述。不再需要 NSStringFromClass。

那么,关于问题 3。我也对这个问题感到惊讶,但协议(protocol)对象似乎直接编译到二进制文件中。当您使用最新的 SDK 进行编译时,代码编译良好,并且当在尚未引入协议(protocol)的 SDK 版本上运行时协议(protocol)将可用,因为不需要链接到丢失的类。这意味着 Protocol 对象将有效,并且该类将正确响应 conformsToProtocol:,无论您运行的是哪个 iOS 版本,都不会出现任何问题。在已编译的二进制文件上使用 otool -l 可以很容易地看到这一点,它将显示类及其方法所遵循的协议(protocol)。协议(protocol)本身似乎存在于名为 __objc_protolist 的部分中。符合 UICollectionViewDelegate 和 DataSource 的类的输出如下所示:

000050a4 0x5cf4
isa 0x5d08
superclass 0x0
cache 0x0
vtable 0x0
data 0x5b30 (struct class_ro_t *)
flags 0x80
instanceStart 156
instanceSize 156
ivarLayout 0x0
name 0x4a0f TTViewController
baseMethods 0x5b10 (struct method_list_t *)
entsize 12
count 2
name 0x3eb8 viewDidLoad
types 0x4955 v8@0:4
imp 0x2620
name 0x3ec4 didReceiveMemoryWarning
types 0x4955 v8@0:4
imp 0x2670
baseProtocols 0x5ad8
count 2
list[0] 0x5da0 (struct protocol_t *)
isa 0x0
name 0x4997 UICollectionViewDelegate
protocols 0x5304
instanceMethods 0x0 (struct method_list_t *)
classMethods 0x0 (struct method_list_t *)
optionalInstanceMethods 0x5310
optionalClassMethods 0x0
instanceProperties 0x0
list[1] 0x5dcc (struct protocol_t *)
isa 0x0
name 0x49ce UICollectionViewDataSource
protocols 0x53d8
instanceMethods 0x53e4 (struct method_list_t *)
entsize 12
count 2
name 0x394e collectionView:numberOfItemsInSection:
types 0x455d i16@0:4@8i12
imp 0x0
name 0x3975 collectionView:cellForItemAtIndexPath:
types 0x4589 @16@0:4@8@12
imp 0x0
classMethods 0x0 (struct method_list_t *)
optionalInstanceMethods 0x5404
optionalClassMethods 0x0
instanceProperties 0x0
ivars 0x0
weakIvarLayout 0x0
baseProperties 0x0

关于iOS 向后兼容性 - 一个不存在的类的分配/初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16561815/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com