Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I reference __weak self in dealloc method

I have a method called in various places called "cancelAllPendingDownloads" This is a general method that cancels various jobs and updates internal counters.

Problem happens when it is called within the dealloc method

-(void)dealloc
{
  [self cancelAllPendingDownloads]; // want to cancel some jobs
}

-(void)cancelAllPendingDownloads // updates some internals
{
    __weak __typeof__(self) weakSelf = self; // This line gets a EXC_BAD_INSTRUCTION error in runtime
   for(Download *dl in self.downloads)
   {
      dl.completionHandler = ^{ // want to replace the previous block
        weakSelf.dlcounter--;
      }
      [dl cancel];
   }
}

Not sure why it fails in the dealloc method as "self" still exists

When I change the code to

__typeof__(self) strongSelf = self; //everything works fine
__weak __typeof__(self) weakSelf = strongSelf; (or "self") BAD_INSTRUCTION error

The error happens on the second line

like image 244
Avner Barr Avatar asked Nov 11 '13 13:11

Avner Barr


1 Answers

Just to make the "you are not supposed" or "You can't" part of the other good answers more precise:

The runtime function for storing a weak reference is objc_storeWeak(), and the Clang/ARC documentation states:

id objc_storeWeak(id *object, id value);

... If value is a null pointer or the object to which it points has begun deallocation, object is assigned null and unregistered as a __weak object. Otherwise, object is registered as a __weak object or has its registration updated to point to value.

Since the self object has already begun deallocation, weakSelf should be set to NULL (and therefore is not of any use).

However, there seems to be a bug (as discussed here http://www.cocoabuilder.com/archive/cocoa/312530-cannot-form-weak-reference-to.html) that objc_storeWeak() crashes in this case, instead of returning NULL.

like image 116
Martin R Avatar answered Sep 19 '22 13:09

Martin R