Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is "self" weak within a method in ARC?

I have a method that occasionally crashes.

-(void)foo{
    [self doSomething];
    [self.delegate didFinish];
    [self doSomethingElse];
}

-doSomething works correctly, then I call to a delegate -didFinish. Within -didFinish, the reference to this object might be set to nil, releasing it under ARC. When the method crashes, it does so on -doSomethingElse. My assumption was that self would be strong within a method, allowing the function to complete. Is self weak or strong? Is there documentation on this? What would the reasoning be for it being strong or weak?

Edit

Upon being inspired by some of the answers below, I did some investigation. The actual cause of the crash in my case was that the NSNotificationCenter does not retain the observer in any case. Mike Weller indicates below that callers of methods should retain the object while it is being called in order to prevent the case that I described above, however it appears that NSNotificationCenter ignores this issue, and always maintains a weak reference to the observer. In other words:

-(void)setupNotification{
    //observer is weakly referenced when added to NSNotificationCenter
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleNotification:)
                                                 name:SomeNotification object:nil];
}

//handle the notification
-(void)handleNotification:(id)notification{
    //owner has reference so this is fine
    [self doSomething];
    //call back to the owner/delegate, owner sets reference to nil
    [self.delegate didFinish];
    //object has been dealloc'ed, crash
    [self doSomethingElse];
}
like image 276
Saltymule Avatar asked Aug 01 '13 14:08

Saltymule


People also ask

What is weak in Objective C?

Pointers that are not retained are often referred to as “weak” in Objective-C documentation that predates the garbage collector. These are references that are allowed to persist beyond the lifetime of the object. Unfortunately, there is no automatic way of telling whether they are still valid.

How do you declare a weak self in Objective C?

The simplest way to create such scope is to declare another block: void(^intermediateBlock)(__typeof(self) __weak self) = ^(__typeof(self) __weak self) { // self is weak in this scope ^{ // self is weak here too [self doSomeWork]; }; };


2 Answers

self would be strong within a method, allowing the function to complete. Is self weak or strong?

self is neither strong nor weak in ARC. It is assumed that the caller holds a reference, and self is unsafe unretained.

It's also true that self can be -dealloced within its own method under ARC, and it's regarded as "Undefined Behavior (or at least dangerous)" for your program to do this.

What would the reasoning be for it being strong or weak?

It's unretained for Performance -- to avoid what is (in the vast majority of cases) an unnecessary reference count inc/dec. Even if they did all those extra ref count operations, your program would still be susceptible to such problems in multithreaded programs or in the presence of a race condition (also UB). So this is one of those extreme edge cases they (rightly) determined they need not defend themselves from.

Is there documentation on this?

Of course! :)

like image 177
justin Avatar answered Sep 28 '22 02:09

justin


self is neither weak nor strong. If you can access self then you are in the scope of a method call, and that method call is being performed by somebody via a reference they must own. self is implied to be a valid reference as long as it's in scope, and it is implied that any memory management or ownership is handled by the caller.

When calling a method through a weak reference, ARC will retain the object for the duration of that method call (see this answer). With strict compiler warnings enabled, you will actually be forced to create a strong reference before sending any methods to that reference.

So by definition, if a method is being called on an object, the caller must already have ownership and nothing needs to be done.

Of course, it is possible to end up calling methods on deallocated objects but that is the result of bad caller code.

like image 38
Mike Weller Avatar answered Sep 28 '22 02:09

Mike Weller