Search code examples
iosobjective-csingletonsigabrtclass-extensions

SIGABR exception when try to assign a property in a Singleton


I've got a SIGABRT when I assign value to the property "myLocal" of the class CMRequestManager in a Singleton Init. What's wrong?

 @interface CMRequestManager (private)
        @property (nonatomic,strong)  NSString* myLocal;
 @end

 @implementation CMRequestManager
        #pragma mark Singleton Methods
        + (id)Manager {
            static CMRequestManager *sharedMyManager = nil;
            static dispatch_once_t onceToken;
            dispatch_once(&onceToken, ^{
                sharedMyManager = [[self alloc] init];
                sharedMyManager.myLocal = @"test test"; //SIGABRT !!!!
            });
            return sharedMyManager;
        }

        - (id)init {
            if (self = [super init]) {

            }
            return self;
        }
 @end

EDIT:

Ok, I've found a solution: move property "myLocal" in the header file outside the class extension:

 @interface CMRequestManager 
 @property (nonatomic,strong)  NSString* myLocal;
 @end

This work, but I don't understand why. So the question remain: What's wrong in my previous code?


Solution

  • @interface CMRequestManager (private)
    

    This is your problem. What you meant was:

    @interface CMRequestManager ()
    

    These appear very similar, but they're actually quite different. The first is a category. You're just promising that such a property exists, but no backing ivar is going to be allocated and no getters and setters are going to be synthesized. You'd need an @implementation block somewhere that actually provided these.

    If you looked at your logs, you would probably see something like "CMRequestManager not key-value compliant for myLocal" or "CMRequestManager does not respond to selector -myLocal" or something like that. Always check the log output; the answer is very often in there.

    The second form, with (), is an extension. An extension is a continuation of the class definition. Properties defined there will automatically receive storage and synthesized getters and setters.

    The difference between these two is highly historical. The category form has existed since the early days of ObjC, long before properties were added to the language (it was originally a way to split up the interfaces for large, complicated objects, and later became primarily a way of creating "protected" or "friend" methods). The extension form is a more recent addition, and is made to look like the categories we were used to, while providing some extra features that came with ObjC 2 (like properties and synthesized methods).

    This works when you moved the property because you made it part of the actual interface, which is the same thing that putting it in an extension would do.

    See Programming with Objective-C for more discussion on categories and extensions.