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

时间:2014-06-10 23:32:20

标签: objective-c

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

AppDelegate.h:

@interface AppDelegate : NSObject <NSApplicationDelegate>
{
   NSMutableString *myString;
}
@property (assign) NSMutableString *myString;

ViewController.h:

-(void)doStuff
{
  AppDelegate *del = (AppDelegate *)[[NSApplication sharedApplication] delegate];
  [del.myString setString:@"This is a test"];
}

这是我在调用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

为什么在其他视图控制器中抛出错误?

2 个答案:

答案 0 :(得分:2)

因为在某些时候你已经重置了app委托,所以 是一个ViewController2。这发生在你没有展示的代码中,所以我不知道你是怎么做的。但重点是,您的消息myString永远不会到达AppDelegate。它到达了ViewController2。

换句话说,你说的是

(AppDelegate *)[[NSApplication sharedApplication] delegate]

但实际上该对象已经以某种方式在ViewController2中被重新命名。因此,即使您正在转换为AppDelegate,它根本不是AppDelegate。编译器允许您对此对象说myString,因为您(错误地)说它是AppDelegate,但是当myString消息到达ViewController2对象时,实际情况会导致运行时崩溃。

在重新命名应用代表时,查找代表setDelegate:.delegate = ...的代码。

答案 1 :(得分:0)

一些事情:

1)错误&#34;无法识别的选择器&#34;意味着你试图在一个不包含具有该名称的公共方法的对象上调用某个函数(&#34; doStuff&#34;或&#34; setMyString&#34;)。它崩溃了,因为它不知道如何回应。当你忘记正确连接故事板,在方法调用中输入错误,或者向错误的对象发送消息时,大多数情况下你都会看到这个。

2)你试图在AppDelegate上访问myString,但它实际上是在ViewController2上调用的。该错误是因为ViewController2没有名为myString的@property。如上所述,请仔细检查您实际分配appDelegate的方式。

3)您正在声明实例变量myString和@property myString。这是多余的,并且确实过时(&lt; iOS4)实践。相反,删除花括号中的{NSMutableString * myString}部分&amp;仅使用@property (nonatomic, strong) NSMutableString *myString;

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

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

致电[del setMyString:@"whatever value"];del.myString = @"whatever value";

5)在Obj-C中,通常首先询问对象是否会响应,从而避免这种崩溃:

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

}

6)这种错误是Apple的新语言Swift偏离上述模式的一个很好的理由。斯威夫特不鼓励询问选择器和放大器。而是需要更多特定/可选数据类型,因此您不太可能遇到此问题。