In the AppDelegate, I'm alloc'ing an instance defined in a static library. This instance has an NSString property set a "copy". When I access the string property on this instance, the app crashes with 'unrecognized selector sent to instance'. Xcode provides a code hint for the property, which means it is known in the calling app. The particular class is compiled into the static library target. What am I missing?
Adding some code.
//static library
//ClassA.h
@interface ClassA : NSObject {
...
NSString *downloadUrl;
}
@property(nonatomic, copy) NSString *downloadUrl;
//ClassA.m
@synthesize downloadUrl;
In the calling app's 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/";
...}
Other classes in the app will get a reference to the delegate and call classA.downloadUrl.
Set flag -ObjC in Other linker Flag in your Project setting... (Not in the static library project but the project you that is using static library...) And make sure that in Project setting Configuration is set to All Configuration
You should note that this is not necessarily the best design pattern. From the looks of it, you are essentially using your App Delegate to store what amounts to a global variable.
Matt Gallagher covered the issue of globals well in his Cocoa with Love article at http://cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html. In all likelyhood, your ClassA should be a singleton rather than a global in the AppDelegate, although its possible you intent ClassA to be more general purpose and not simply a singleton. In that case, you'd probably be better off with either a class method to return a pre-configured instance of Class A, something like:
Or alternatively (since that would add application specific stuff to what is possibly a general purpose class), create a new class whose sole purpose is to contain that class method.
The point is that application globals do not need to be part of the AppDelegate. Just because the AppDelegate is a known singleton, does not mean every other app global should be mixed in with it even if they have nothing conceptually to do with handling the NSApplication delegate methods.
For me, what caused this error was that I accidentally had the same message being sent twice to the same class member. When I right clicked on the button in the gui, I could see the method name twice, and I just deleted one. Newbie mistake in my case for sure, but wanted to get it out there for other newbies to consider.
1) Is the synthesize within
@implementation
block?2) Should you refer to
self.classA = [[ClassA alloc] init];
andself.classA.downloadUrl = @"..."
instead of plainclassA
?3) In your
myApp.m
file you need to importClassA.h
, when it's missing it will default to a number, or pointer? (in C variables default to int if not found by compiler):#import "ClassA.h"
.In the code you posted, you're sending the
setDownloadURL:
setter toClassA
— that is, the class itself. You want to set the property of an instance.How are you importing ClassA into your AppDelegate Class? Did you include the .h file in the main project? I had this problem for a while because I didn't copy the header file into the main project as well as the normal #include "ClassA.h."
Copying, or creating the .h solved it for me.