Objective c 无法识别的选择器已发送到实例(多个视图控制器)

Objective c 无法识别的选择器已发送到实例(多个视图控制器),objective-c,Objective C,我使用NSTabView访问两个视图控制器:ViewController1和ViewController2。在我的AppDelegate中,我有一个变量希望在这两个变量之间共享: AppDelegate.h: @interface AppDelegate : NSObject <NSApplicationDelegate> { NSMutableString *myString; } @property (assign) NSMutableString *myString;

我使用NSTabView访问两个视图控制器:
ViewController1
ViewController2
。在我的AppDelegate中,我有一个变量希望在这两个变量之间共享:

AppDelegate.h:

@interface AppDelegate : NSObject <NSApplicationDelegate>
{
   NSMutableString *myString;
}
@property (assign) NSMutableString *myString;
这是调用
doStuff()
时出现的错误:

2014-06-10 16:29:09.240 MyApp[32297:303] -[ViewController2 myString]:
                        unrecognized selector sent to instance 0x6100001a7700
2014-06-10 16:29:09.240 MyApp[32297:303] An uncaught exception was raised
2014-06-10 16:29:09.240 MyApp[32297:303] -[ViewController2 myString]:
                        unrecognized selector sent to instance 0x6100001a7700
2014-06-10 16:29:09.241 MyApp[32297:303] (
0   CoreFoundation        0x00007fff8d52d25c __exceptionPreprocess + 172
1   libobjc.A.dylib       0x00007fff93f16e75 objc_exception_throw + 43
2   CoreFoundation        0x00007fff8d53012d -[NSObject(NSObject)
                                              doesNotRecognizeSelector:] + 205
3   CoreFoundation        0x00007fff8d48b322 ___forwarding___ + 1010
4   CoreFoundation        0x00007fff8d48aea8 _CF_forwarding_prep_0 + 120
5   Recorder              0x0000000100006b55 -[ViewController1 doStuff:] + 549

为什么在另一个视图控制器中抛出错误?

因为在某个点上,您已重置应用程序委托,使其成为ViewController2。这发生在您尚未显示的代码中,所以我不知道您是如何以及何时做到的。但关键是,您的消息
myString
永远不会到达AppDelegate。它将到达ViewController2

换句话说,你是在说

(AppDelegate *)[[NSApplication sharedApplication] delegate]
但事实上,该对象以某种方式被重新绘制在ViewController2上。因此,即使您正在强制转换为AppDelegate,它也根本不是AppDelegate。编译器允许您对此对象说
myString
,因为您(错误地)说它是AppDelegate,但当
myString
消息到达ViewController2对象时,实际情况会导致运行时崩溃

在你说
setDelegate:
.delegate=…
的地方寻找代码,以确定你何时重新输入应用程序委托。

有几件事:

1) 错误“unrecognized selector”表示您试图对不包含该名称的公共方法的对象调用某个函数(“doStuff”或“setMyString”)。它崩溃是因为它不知道如何响应。大多数情况下,当您忘记正确连接故事板、方法调用中出现输入错误或向错误对象发送消息时,您会看到这种情况

2) 您试图在AppDelegate上访问myString,但实际上它在ViewController2上被调用。错误是因为ViewController2没有名为myString的@property。正如上面的响应所述,再次检查您实际上是如何分配appDelegate的

3) 您同时声明了实例变量myString和@property myString。这是多余的,而且确实是过时的(@property(非原子,强)NSMutableString*myString

4) 除非您在AppDelegate.m中专门创建了
setString
方法,否则访问名为“myString”的@property的默认方式可能是
[del setMyString]
del.myString=…

调用[del.myString setString]也是点语法和括号的冗余混合。修复第一个错误后,它可能会抛出一个单独的错误。让@property处理创建getter/setter方法

调用
[del setMyString:@“任意值”]
del.myString=@“任意值”

5) 在Obj-C中,通常通过首先询问对象是否会响应来避免此类崩溃:

if ([someObject respondsToSelector:@selector(doStuff:)] {//then do something
}

6) 这种错误是苹果新语言Swift偏离上述模式的一个很好的原因。Swift不鼓励询问选择器&相反,它需要更具体/可选的数据类型,因此您不太可能遇到此问题

if ([someObject respondsToSelector:@selector(doStuff:)] {//then do something