40

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.

stefanB
  • 77,323
  • 27
  • 116
  • 141
4thSpace
  • 43,672
  • 97
  • 296
  • 475

9 Answers9

28

1) Is the synthesize within @implementation block?

2) Should you refer to self.classA = [[ClassA alloc] init]; and self.classA.downloadUrl = @"..." instead of plain classA?

3) In your myApp.m file you need to import ClassA.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".

stefanB
  • 77,323
  • 27
  • 116
  • 141
  • 1
    Have already tried that. Still get exception. I have several other similar classes in the same library. None of them are having this issue. – 4thSpace May 14 '09 at 06:23
  • ... Of course the 'www' was shortened to web link in previous comment – stefanB May 14 '09 at 06:26
  • Yes - same outcome with unrecognized selector. – 4thSpace May 14 '09 at 06:34
  • I have some NSInteger properties in ClassA that are all declared the same way. I can set only one of them. The others throw the same type of exception. – 4thSpace May 14 '09 at 06:36
  • Is the synthesize within @implementation block? should you refer to self.classA = [[ClassA alloc] init]; and self.classA.downloadUrl = @"..." ? – stefanB May 14 '09 at 06:41
  • I've added a test string property to another class in the static library. I get the same results. Somewhere, the linking up must have changed. – 4thSpace May 14 '09 at 06:48
  • Yes - but still same exception. Yes to #1 above. For #3, I put imports in the PCH file so each classes doesn't have to keep importing. – 4thSpace May 14 '09 at 07:00
  • If I open the ClassA.o file in the calling app's build folder, I see getter and setter methods for downloadUrl. – 4thSpace May 14 '09 at 14:03
  • 3
    Finally I have resolved it. I removed ClassA.h from the .h file in the library which references all .h files. I then dragged ClassA.h into the app project and added the imports. I was trying to follow the technique mentioned here github.com/joehewitt/three20/tree/master with his common.h. The weird thing is I still have lots of classes referenced through my common.h, which still work in the app project. I didn't have to drag their header files over – 4thSpace May 14 '09 at 14:33
  • @stefanB Thanks for the answer! In my case the problem was that I was not referencing self. , but I'm curious, if that's so important, why doesn't swift throw a compiler error? – Jubei Sep 11 '15 at 07:49
20

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

Mihir Mehta
  • 13,743
  • 3
  • 64
  • 88
  • I just created a static library with a unittest target in Xcode4.2. I had to add "-ObjC" to "Other Linker Flags". Now the unittest runs. – neoneye Jan 30 '12 at 16:16
15

A lot of people have given some very technical answers for this and similar questions, but I think it's simpler than that. Sometimes if you're not paying attention a selector that you don't intend to use can be attached to something in the interface. You might be getting this error because the selector's there but you haven't written any code for it.

The easiest way to double-check that this is not the case is to control-click the item so you can see all of the selectors that are associated with it. If there's anything in there that you don't want to be, get rid of it! Hope this helps...

Raydot
  • 1,458
  • 1
  • 23
  • 38
1

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.

Rich
  • 926
  • 8
  • 17
1

Mine was something simple/stupid. Newbie mistake, for anyone that has converted their NSManagedObject to a normal NSObject.

I had:

@dynamic order_id;

when i should have had:

@synthesize order_id;
Dan Power
  • 1,141
  • 1
  • 12
  • 18
1

In the code you posted, you're sending the setDownloadURL: setter to ClassA — that is, the class itself. You want to set the property of an instance.

Chuck
  • 234,037
  • 30
  • 302
  • 389
  • In the static class I have @property(nonatomic, copy) NSString *theString and theString is @synthesize. Is there something else? – 4thSpace May 14 '09 at 05:14
  • I do notice when I mouse over theString on the caller side, its type is NSCFNumber. Should be NSString. – 4thSpace May 14 '09 at 05:16
1

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.

Heat Miser
  • 19,438
  • 7
  • 35
  • 38
  • In the library, I have a .h that references all the other .h files. So, the calling app only needs to reference that particular .h file to get a reference to everything in the library. I can drag the ClassA header file into the app project and reference it from the .m file. Still get the same exception though. – 4thSpace May 14 '09 at 06:03
  • Another thing you may want to try is doing self.classA.downloadUrl. That error is usually what you get when a variable is initialized to nothing, such as NSString *m. It gets set to some seemingly random int. You might try overriding the init method in the class and setting it to nil in there. – Heat Miser May 14 '09 at 06:11
  • I've tried overriding init but my breakpoint in there is never hit. However, if I Jump to Definition on ClassA where the alloc is, it goes to the correct file and I see my custom init. – 4thSpace May 14 '09 at 06:22
  • I see below that you solved it. I think there is something strange about the linker with Objective-C classes vs normal C++ classes. Typically even though they are compiled in, I like to keep the header files in the main project, whenever I don't I seem to have problems like this. I'm glad you solved it! – Heat Miser May 14 '09 at 15:50
0

Very weird, but. You have to declare the class for your application instance as myApplication: UIApplication instead of myApplication: NSObject . It seems that the UIApplicationDelegate protocol doesn't implement the +registerForSystemEvents message. Crazy Apple APIs, again.

H2CO3
  • 23
  • 1
  • 2
0

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:

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

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.

Peter N Lewis
  • 17,664
  • 2
  • 43
  • 56