如何解决“发送到实例的无法识别的选择器”?

Posted

技术标签:

【中文标题】如何解决“发送到实例的无法识别的选择器”?【英文标题】:How to resolve 'unrecognized selector sent to instance'? 【发布时间】:2010-10-26 02:05:00 【问题描述】:

在 AppDelegate 中,我正在分配一个在静态库中定义的实例。这个实例有一个 NSString 属性设置了一个“副本”。当我访问此实例上的字符串属性时,应用程序因“发送到实例的无法识别的选择器”而崩溃。 Xcode 为该属性提供了代码提示,这意味着它在调用应用程序中是已知的。特定类被编译到静态库目标中。我错过了什么?

添加一些代码。

//static library 
//ClassA.h
@interface ClassA : NSObject 
...
NSString *downloadUrl;

@property(nonatomic, copy) NSString *downloadUrl;

//ClassA.m
@synthesize downloadUrl;

在调用应用的 appDelegate 中。

//app delegate header file
@interface myApp : NSObject <UIApplicationDelegate> 
ClassA *classA;

@property (nonatomic, retain) ClassA *classA;

//app delegate .m file
@synthesize classA;

- (void)applicationDidFinishLaunching:(UIApplication *)application 
classA = [[ClassA alloc] init];
//exception occurs here.  downloadUrl is of type NSCFNumber
classA.downloadUrl = @"http://www.abc.com/";
...

应用程序中的其他类将获得对委托的引用并调用 classA.downloadUrl。

【问题讨论】:

我认为您需要发布代码 sn-ps 和完整的错误消息才能在这里获得更多帮助。 【参考方案1】:

在您发布的代码中,您将setDownloadURL: 设置器发送到ClassA — 即类本身。你想设置一个实例的属性。

【讨论】:

在静态类中我有@property(nonatomic, copy) NSString *theString 并且theString 是@synthesize。还有别的吗? 我注意到当我将鼠标悬停在调用方的字符串上时,它的类型是 NSCFNumber。应该是 NSString。【参考方案2】:

您如何将 ClassA 导入您的 AppDelegate 类?您是否在主项目中包含了 .h 文件?我有一段时间遇到这个问题,因为我没有将头文件复制到主项目以及正常的#include“ClassA.h”中。

复制或创建 .h 为我解决了这个问题。

【讨论】:

在库中,我有一个引用所有其他 .h 文件的 .h 。因此,调用应用程序只需要引用该特定的 .h 文件即可获得对库中所有内容的引用。我可以将 ClassA 头文件拖到应用程序项目中并从 .m 文件中引用它。尽管如此,仍然会遇到同样的异常。 您可能想尝试的另一件事是执行 self.classA.downloadUrl。当变量初始化为空时,通常会出现该错误,例如 NSString *m。它被设置为一些看似随机的 int。您可以尝试覆盖类中的 init 方法并将其设置为 nil。 我尝试过覆盖 init 但我的断点从未被命中。但是,如果我跳转到 alloc 所在的 ClassA 上的定义,它会转到正确的文件,并且我会看到我的自定义 init。 我在下面看到你解决了它。我认为带有 Objective-C 类与普通 C++ 类的链接器有些奇怪。通常,即使它们被编译,我也喜欢将头文件保留在主项目中,只要我不这样做,我似乎就会遇到这样的问题。我很高兴你解决了它!【参考方案3】:

1) 合成是否在@implementation 块内?

2) 你应该引用self.classA = [[ClassA alloc] init];self.classA.downloadUrl = @"..." 而不是普通的classA

3) 在您的myApp.m 文件中,您需要导入ClassA.h,当它丢失时,它会默认为数字还是指针? (在 C 变量中,如果编译器找不到,则默认为 int):

#import "ClassA.h".

【讨论】:

已经试过了。仍然得到异常。我在同一个库中有几个其他类似的类。他们都没有这个问题。 ... 当然,“www”在之前的评论中被缩短为网络链接 是 - 与无法识别的选择器相同的结果。 我在 ClassA 中有一些 NSInteger 属性,它们都以相同的方式声明。我只能设置其中一个。其他的抛出相同类型的异常。 终于解决了。我从引用所有 .h 文件的库中的 .h 文件中删除了 ClassA.h。然后我将 ClassA.h 拖到应用程序项目中并添加了导入。我试图用他的 common.h 来遵循这里提到的技术 github.com/joehewitt/three20/tree/master。奇怪的是我仍然有很多通过我的 common.h 引用的类,它们仍然在应用程序项目中工作。我不必将他们的头文件拖过来【参考方案4】:

您应该注意,这不一定是最好的设计模式。从外观上看,您实际上是在使用您的 App Delegate 来存储相当于全局变量的内容。

Matt Gallagher 在http://cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html 的 Cocoa with Love 文章中很好地介绍了全局变量的问题。在所有可能的情况下,您的 ClassA 应该是单例而不是 AppDelegate 中的全局,尽管您可能希望 ClassA 更通用,而不仅仅是单例。在这种情况下,您可能最好使用类方法来返回 A 类的预配置实例,例如:

+ (ClassA*) applicationClassA

    static ClassA* appClassA = nil;
    if ( !appClassA ) 
        appClassA = [[ClassA alloc] init];
        appClassA.downloadURL = @"http://www.abc.com/";
    
    return appClassA;

或者(因为这会将特定于应用程序的东西添加到可能是通用类的内容中),创建一个新类,其唯一目的是包含该类方法。

关键是应用程序全局变量不需要是 AppDelegate 的一部分。仅仅因为 AppDelegate 是一个已知的单例,并不意味着所有其他应用程序全局都应该混入其中,即使它们在概念上与处理 NSApplication 委托方法无关。

【讨论】:

【参考方案5】:

在您的项目设置中的其他链接器标志中设置标志 -ObjC...(不在静态库项目中,而是在您使用静态库的项目中...)并确保在项目设置配置设置为所有配置

【讨论】:

我刚刚在 Xcode4.2 中创建了一个带有 unittest 目标的静态库。我不得不将“-ObjC”添加到“其他链接器标志”中。现在单元测试运行。【参考方案6】:

很奇怪,但是。您必须将应用程序实例的类声明为 myApplication: UIApplication 而不是 myApplication: NSObject 。似乎 UIApplicationDelegate 协议没有实现 +registerForSystemEvents 消息。又是疯狂的 Apple API。

【讨论】:

【参考方案7】:

对于这个和类似的问题,很多人给出了一些非常技术性的答案,但我认为它比这更简单。有时,如果您不注意,您不打算使用的选择器可以附加到界面中的某些内容上。您可能会收到此错误,因为选择器在那里,但您还没有为它编写任何代码。

仔细检查情况是否如此的最简单方法是按住控件单击该项目,这样您就可以看到与其关联的所有选择器。如果那里有任何你不想成为的东西,那就摆脱它!希望这会有所帮助...

【讨论】:

结束了漫长的一天,这正是我需要看到的。感谢您保持简单。 刚刚在我的第一个 ios 项目中使用了这个。我的视图控制器中有一个死“链接”到一个动作实现。删除它,它工作。谢谢! 宾果游戏——正是我所需要的!谢谢! 没错,在我的例子中,.h 和 .m 中的大小写不同,在 .h 中是 methodName(),在 .m 中是 MethodName() 在看到这个答案之前就想出来了,但值得一试。我为UIImageView 设置了 2 个网点。【参考方案8】:

对我来说,导致此错误的原因是我不小心将同一条消息发送给同一个班级成员两次。当我右键单击 gui 中的按钮时,我可以看到两次方法名称,我只是删除了一个。在我的情况下肯定是新手错误,但想把它拿出来供其他新手考虑。

【讨论】:

【参考方案9】:

我的想法很简单/愚蠢。新手错误,对于任何将他们的 NSManagedObject 转换为普通 NSObject 的人。

我有:

@dynamic order_id;

我应该有的时候:

@synthesize order_id;

【讨论】:

以上是关于如何解决“发送到实例的无法识别的选择器”?的主要内容,如果未能解决你的问题,请参考以下文章

NSInvalidArgumentException,使用 performSegueWithIdentifier 时发送到实例的无法识别的选择器

快速代码崩溃:“发送到实例的无法识别的选择器”

AppDelegate - 发送到实例的无法识别的选择器[关闭]

UISwipeGesture '发送到实例的无法识别的选择器'

ARC 和 UIAlertView:发送到实例的无法识别的选择器

[UICollectionViewCell imageView]:无法识别的选择器发送到实例