使用 NSBundle -classNamed 按字符串检索 Class:在 iOS10 中失败
Retrieving a Class by String using NSBundle -classNamed: fails in iOS10
我在 iOS 10 上发现了问题,其中未加载具有字符串生成类名的 viewcontroller。该问题发生在 iPad Air 2 上,当用户第二次启动该应用程序时(在用力关闭后)。
在带有 Xcode 8 的模拟器中,错误是可重现的。似乎无法实例化 viewcontroller 并且此代码不再有效。这样对吗?
Class controllerClass = [[NSBundle mainBundle] classNamed:className];
解决方案是使用简单的开关盒结构来创建控制器。它需要更多的代码行,但它是更安全的代码。
我找到了一个使用底层 Objective-C 函数 objc_getClass() 并忽略现在(自 iOS10?)错误的解决方法NSBundle 的方法。由于此函数与 [MyClass class] 的功能相同,因此它应该不会失败。
我的应用程序的旧版本(iOS8 和更早版本)使用此代码似乎也无法在新硬件上运行。看起来设备越快,该方法就越有可能失败。对我来说,iOS 模拟器的失败率约为 50%。
id objc_getClass(const char *name); // define the function signature without importing it
Class cls = objc_getClass([s cStringUsingEncoding:NSASCIIStringEncoding]);
NSAssert(cls != nil, @"classNamed: %@ returned nil!", s);
参考资料
- https://forums.developer.apple.com/message/200857
- NSClassFromString() vs classNamed:(NSString *)
- Objective C class problem
我在 iOS 10 上发现了问题,其中未加载具有字符串生成类名的 viewcontroller。该问题发生在 iPad Air 2 上,当用户第二次启动该应用程序时(在用力关闭后)。
在带有 Xcode 8 的模拟器中,错误是可重现的。似乎无法实例化 viewcontroller 并且此代码不再有效。这样对吗?
Class controllerClass = [[NSBundle mainBundle] classNamed:className];
解决方案是使用简单的开关盒结构来创建控制器。它需要更多的代码行,但它是更安全的代码。
我找到了一个使用底层 Objective-C 函数 objc_getClass() 并忽略现在(自 iOS10?)错误的解决方法NSBundle 的方法。由于此函数与 [MyClass class] 的功能相同,因此它应该不会失败。
我的应用程序的旧版本(iOS8 和更早版本)使用此代码似乎也无法在新硬件上运行。看起来设备越快,该方法就越有可能失败。对我来说,iOS 模拟器的失败率约为 50%。
id objc_getClass(const char *name); // define the function signature without importing it
Class cls = objc_getClass([s cStringUsingEncoding:NSASCIIStringEncoding]);
NSAssert(cls != nil, @"classNamed: %@ returned nil!", s);
参考资料
- https://forums.developer.apple.com/message/200857
- NSClassFromString() vs classNamed:(NSString *)
- Objective C class problem