什么是“presentModalViewController:animated:”和“dismissModalViewControllerAnimated:”的正确用法?

时间:2012-09-03 12:26:49

标签: iphone objective-c ios cocoa uiviewcontroller

我遇到了对象分配和释放的问题。 我正在开发一些具有图像编辑功能的应用。 当用户点击选择图像时,会出现UIImagePickerController,然后当用户从库中选择图像时,UIImagePickerController会解散,然后有一个方法:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    //some logic

    FilterViewController *filterViewController = [[FilterViewController alloc] initWithImage:imageToWorkWith
                                                                                    withDelegate:self];

        /* present image processing screen, then release it */
        [((UIViewController *)self.delegate) presentModalViewController:filterViewController animated:NO];            
        [filterViewController release];
}

然后出现FilterViewController - 图像编辑屏幕。点击“完成”按钮后,将调用下一个方法:

- (void)dismissWithDone {
    [self.filterViewDelegate doneImageEdittingWithImage:self.imageToWorkWithView.image];
}

调用:

#pragma mark - FilterViewDelegate

- (void)doneImageEdittingWithImage:(UIImage *)imageToSend {
    //some logic

    [((UIViewController *)self.delegate) dismissModalViewControllerAnimated:NO];
}

所有似乎都正常工作,但问题是,filterViewController没有解除分配并在内存中持久存在。如果我将再次选择编辑一些照片,我的意思是如果再次调用创建filterViewController的方法,那么将释放前一个实例并显示新的实例,依此类推。 我认为当调用[UIViewController setChildModalViewController:]时,在设置新实例时,会取消分配filterViewController的前一个实例。 如果再添加一个版本:

[((UIViewController *)self.delegate) presentModalViewController:filterViewController animated:NO];            
[filterViewController release];
[filterViewController release];

然后它将被解除后释放,但在创建新实例时将是bad_access,因为它将尝试解除分配已释放的实例。

我不明白: 1.为什么在解除filterViewController后,仍然有大于0的引用计数,这会导致不释放它? 2.为什么,如果再添​​加一个版本,deallocated对象的引用仍然存在于childModalViewController中?

1 个答案:

答案 0 :(得分:0)

我遇到的所有麻烦的原因是,我没有设置为在UIViewController中使用的某些类中的块的某些属性。例如:我在这个UIViewController中使用GPUImage框架,我正在设置块:

self.movieWriter.completionBlock = ^{
    //do something with self.* properties
    [self someMethod];
}

所以,在解除UIViewController之前,我没有设置nil来清理这个块属性:

self.movieWriter.completionBlock = nil;

这就是为什么在UIViewController上没有调用dealloc。

另外here是关于块的解释以及为什么我们需要将它们的属性设置为nil。