iOS 5 Twitter Framework和completionHandler块 - "在这个块中强烈捕获'自我'可能会导致保留周期"

iMa*_*din 10 iphone objective-c ipad objective-c-blocks ios5

我是编程和Objective-C的新手,我正在尝试解决我的代码有什么问题.我已经阅读了一些关于块的内容,但我不知道到目前为止我所阅读的内容与我的代码有什么关系.

我的代码使用的是iOS 5 Twitter Framework.我使用Apple提供的大多数示例代码,所以我实际上一开始并不知道我使用了一个块作为完成处理程序.

现在我从Xcode 4获得了这两条消息:" 1.块将被捕获对象强烈保留的对象保留 ",并且" 在此块中捕获'自我'可能会导致保留周期 ".

基本上,我所做的是删除Apple在其完成处理程序中使用的代码(使用TWTweetComposeViewControllerResultCancelled和TWTweetComposeViewControllerResultDone的switch语句)并使用我的if语句[imagePickerController sourceType].

因此,sendTweet在将图像添加到推文后调用.

我希望有人可以向我解释为什么会这样,以及我如何解决它.另外:我可以将完成处理程序代码放入方法而不是块中吗?

- (void)sendTweet:(UIImage *)image
{
    //adds photo to tweet
    [tweetViewController addImage:image];

    // Create the completion handler block.
    //Xcode: "1. Block will be retained by an object strongly retained by the captured object"
    [tweetViewController setCompletionHandler:
                             ^(TWTweetComposeViewControllerResult result) {
            NSString *alertTitle,
                     *alertMessage,
                     *otherAlertButtonTitle,
                     *alertCancelButtonTitle;

            if (result == TWTweetComposeViewControllerResultCancelled) 
            {
                //Xcode: "Capturing 'self' strongly in this block is likely to lead to a retain cycle"
                if ([imagePickerController sourceType])
                {
                    alertTitle = NSLocalizedString(@"TCA_TITLE", nil);
                    alertMessage = NSLocalizedString(@"TCA_MESSAGE", nil);
                    alertCancelButtonTitle = NSLocalizedString(@"NO", nil);
                    otherAlertButtonTitle = NSLocalizedString(@"YES", nil);

                    //user taps YES
                    UIAlertView *alert = [[UIAlertView alloc] 
                                             initWithTitle:alertTitle 
                                                   message:alertMessage 
                                                  delegate:self   // Note: self
                                         cancelButtonTitle:alertCancelButtonTitle 
                                         otherButtonTitles:otherAlertButtonTitle,nil];
                    alert.tag = 1;
                    [alert show];                
                }            
            }
Run Code Online (Sandbox Code Playgroud)

Den*_*cht 21

基本问题是你self在一个街区内使用.该对象保留该块,块本身也保留该对象.所以你有一个保留周期,因此两者都可能永远不会被释放,因为它们都有一个指向它们的引用.Fortunaly有一个简单的解决方法:

通过对自身使用所谓的弱引用,块将不再保留对象.然后可以释放该对象,该对象将释放该块(设置MyClass为适当的类型):

// before your block
__weak MyObject *weakSelf = self;
Run Code Online (Sandbox Code Playgroud)

在您的块中,您现在可以使用weakSelf而不是self.请注意,这仅适用于使用ARC的iOS 5.

看一下这里还有一个非常好的长解释,如何在实现API时避免在块中捕获self?其中还介绍了如何在iOS 4和没有ARC的情况下避免这种情况.