iOS 5 Twitter Framework & completionHandler block - “Capturing 'self' strongly in this block is likely to lead to a retain cycle”

前端 未结 4 1242
后悔当初
后悔当初 2021-02-14 13:34

I am very new to programming and Objective-C and I am trying to work out what is wrong with my code. I have read a bit about blocks but I don\'t know how any of what I have read

相关标签:
4条回答
  • 2021-02-14 14:04

    Your block is retaining self because you're using self as the delegate of the UIAlertView. If self is also retaining the block, they're retaining each other, which creates a retain cycle.

    Try

     __block WhateverTypeSelfIs *nonRetainedSelfForBlock = self;
    [tweetViewController setCompletionHandler: 
    

    and

    UIAlertView *alert = [[UIAlertView alloc] 
                                     initWithTitle:alertTitle 
                                     message:alertMessage 
                                     delegate:nonRetainedSelfForBlock 
                                     cancelButtonTitle:alertCancelButtonTitle 
                                     otherButtonTitles:otherAlertButtonTitle,nil];
    

    Check the Apple docs, section Object and Block Variables. Objects referenced within a block are retained, unless you use __block.

    0 讨论(0)
  • 2021-02-14 14:06

    The basic problem is that you're using self within a block. The block is being retained by the object and the block itself retains the object, too. So you have a retain-cycle and thus both will probably never be released because both have a reference pointing towards them. Fortunaly there is a simple workaround:

    By using a so-called weak reference to self the block will no longer retain the object. The object then can later be released which will release the block (set MyClass to the appropriate type):

    // before your block
    __weak MyObject *weakSelf = self;
    

    Inside your block you now can use weakSelf instead of self. Note that this is only for iOS 5 using ARC.

    Looking at this there is also a very good long explanation on How do I avoid capturing self in blocks when implementing an API? which also describes how to avoid this on iOS 4 and without ARC.

    0 讨论(0)
  • 2021-02-14 14:15

    There is a rather surprising way to get rid of the warning. Mind you, only do this if you are sure you are not creating a retain cycle, or you are sure that you will break it yourself later on (by setting the completion handler to nil when you're done, for example). If you have control over the interface, then rename your method so it does not start with "set". The compiler seems to give this warning only when the method name starts with "set".

    0 讨论(0)
  • 2021-02-14 14:24

    According to stuff I've seen elsewhere, “weak” won't work for ARC-compliant code, and that you must use “_unsafe_unretained” instead. This is what I did to fix the “Capturing 'self' strongly in this block is likely to lead to a retain cycle” warning in the Apple sample app "AVPlayerDemo":

    __unsafe_unretained id unself = self;
    mTimeObserver = [mPlayer addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(interval, NSEC_PER_SEC) 
                                queue:NULL /* If you pass NULL, the main queue is used. */
                                usingBlock:^(CMTime time) 
                                            {
                                                /* 'unself' replaced 'self' here: */
                                                [unself syncScrubber];
                                            }];
    
    0 讨论(0)
提交回复
热议问题