为什么某些类对象不能作为 Objective-C 中的返回值传递?



考虑以下尝试使用非NSObject类对象__NSMessageBuilder的代码:

- (Class)getTestClass {
    Class class = objc_getClass("__NSMessageBuilder");
    return class;
}
- (void)testNonNSObjectClass {
    // case 1
    Class class1 = objc_getClass("__NSMessageBuilder");
    const char *name1 = class_getName(class1);
    // case 2
    Class class2 = [self getTestClass];
    const char *name2 = class_getName(class2);
}

第一种情况按预期工作,name1 包含类的正确名称。但是,在情况 2 中,执行在 [self getTestClass] 上崩溃,并显示以下看似无关的日志输出:

NSForwarding: warning: object 0x7fff76f18dc0 of class '__NSMessageBuilder' does not 
implement doesNotRecognizeSelector: -- abort
Message from debugger: Terminated due to signal 9

这对我来说没有任何意义。这是怎么回事,我该如何解决?问题不仅限于__NSMessageBuilder,这也发生在其他特殊类(如__ARCLite__等)上。

很可能

是因为您使用的是 ARC。编译器正在向代码添加保留/释放消息,并且由于根类不继承自 NSObject,因此尚未实现保留和释放方法,因此会出现错误"类'__NSMessageBuilder'未实现 doesNotRecognizeSelector: -- abort"。

我刚刚使用以下代码进行了测试:

#import <Foundation/Foundation.h>
// RootClass.h
NS_ROOT_CLASS
@interface RootClass
@end
// RootClass.m
#import "RootClass.h"
@implementation RootClass
@end
// AppDelegate.m
#import "RootClass.h"
#import <objc/runtime.h>
@interface AppDelegate ()
@property (retain) IBOutlet NSWindow *window; // retain is important here because you will not use ARC in one of the tests
@end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    [self testNonNSObjectClass];
}
- (Class)getTestClass {
    Class class = objc_getClass("RootClass");
    return class;
}
- (void)testNonNSObjectClass {
    // case 1
    Class class1 = objc_getClass("RootClass");
    const char *name1 = class_getName(class1);
    // case 2
    Class class2 = [self getTestClass];
    const char *name2 = class_getName(class2);
}

如果我使用 ARC 运行它,它会像您发现的那样轰炸,但是如果您在没有 ARC 的情况下运行此代码(转到构建阶段并将编译器标志 -fno-objc-arc 添加到 AppDelegate.m),您将不会轰炸。

最新更新