1

I have a block attached to a button (using this category):

__unsafe_unretained typeof(UIImage) *weakPic = originalPic;
[button addEventHandler:^{
    switch (state) {
    case state1:
        {
           UIViewController *vc = //some VC
           vc.pic = weakPic; // weakPic is nil at this point
                             // putting originalPic here would solve my problem
                             // but then I would have a retain cycle


        }  

    case state2:
        {
          // other stuff
        }
    }

}];

the action associated with the button is different depending on the state.

Here is the problem: I must keep the above __unsafe_unretained to avoid having a retain cycle. However, this code is called at a point where originalPic = nil.. and so when I assign weakPic to vc.pic I'm assigning it a nil value. If I replace weakPic with just originalPic, then it works fine.. (originalPic will have the updated value) but then I get the retain cycle.. ideas?

Community
  • 1
  • 1
abbood
  • 23,101
  • 16
  • 132
  • 246
  • What makes you think you think you have a dangerous retain cycle? – Abizern Sep 16 '13 at 15:16
  • 1
    If it is guaranteed that the event handler block is always called eventually, then you have a "temporary retain cycle", and you can ignore the warning or suppress it with a compiler pragma. – Martin R Sep 16 '13 at 15:18
  • 2
    Alternatively, if originalPic is a property, then you can get a weak reference to `self` and call `weakSelf.originalPic` within the block, which is how I usually do it. – Abizern Sep 16 '13 at 15:19
  • @MartinR You understood my point perfectly :) – Abizern Sep 16 '13 at 15:21

2 Answers2

1

Without knowing more about your code I suggest you consider declaring a weakSelf and implementing an accessor on self.

//the accessor
-(UIImage*)pic{
    return originalPic;
}

-(void)someSetupMethod{
    __weak id weakSelf = self;

    [button addEventHandler:^{
        switch (state) {
        case state1:
            {
               UIViewController *vc = //some VC
               vc.pic = [weakSelf pic]; // if weakself is nil at this point, then
                                        // originalPic is likely invalid


            }  

        case state2:
            {
              // other stuff
            }
        }

    }];
}

It may not be a weakSelf you want, but some other object. In that case just declare that other object to be weak, as long as you can be relatively sure it will exist as long or longer than the button.

Saltymule
  • 2,907
  • 2
  • 22
  • 30
-1

You might also want to look at declaring it as a __block variable. The __block keyword prevents a copy of the object from being made inside the block.

See this thread for a better explanation of __weak and __block references.

Community
  • 1
  • 1
Jordan
  • 4,133
  • 1
  • 27
  • 43
  • Under ARC it's no longer the case that a `__block` pointer does not retain: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#id50 – jscs Sep 16 '13 at 20:25