弹出控制器(UIPopoverController)在弹出框仍可见时已达到释放(dealloc)状态

111

我向您保证我已在Stack Overflow上寻找答案,但是没有任何帮助。这里我有一个简单的代码,应该呈现一个UIImagePickerController在一个UIPopoverController中:

-(void)takePicture:(id)sender{
UIImagePickerController *picker=[[UIImagePickerController alloc] init];
picker.delegate=self;
picker.sourceType=UIImagePickerControllerSourceTypeCamera;
picker.allowsEditing=YES;
UIPopoverController *poc=[[UIPopoverController alloc] 
                            initWithContentViewController:picker];
[poc presentPopoverFromBarButtonItem:bbItem 
            permittedArrowDirections:UIPopoverArrowDirectionAny
                            animated:NO];
}

现在,即使我第一次收到 [UIPopoveController dealloc] 崩溃时...错误并且程序崩溃。 根据 ARC,我没有执行任何保留、释放或自动释放操作。 在使用 ARC 时,是否有关于 UIPopoverControllers 的特别考虑?

3个回答

203

UIPopoverControllers应始终存储在实例变量中。为其创建一个强引用属性是一个很好的做法。

更新:

从iOS 8开始,您应该使用UIPopoverPresentationController。然后,您不需要保留对弹出窗口的引用,因为它由表示控制器管理。

代码示例(适用于iPhone和iPad):

UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.allowsEditing = YES;
picker.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController* popoverPC = picker.popoverPresentationController;
popoverPC.barButtonItem = bbItem;
popoverPC.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:picker animated:YES completion:nil];

1
哦,我明白了。但这不像是一个UIAlertView 吗?我从来没有为此声明一个ivar,只是在需要的地方alloc init它,显示它,然后[曾经]释放它。那么popovercontroller有什么不同呢? - Mikayil Abdullayev
17
alertView会被其父视图保留(因为所有视图都会被保留),但是popoverController不是一个视图,所以没有父视图可以保留它。如果你不保留它(或者将它存储在作用域比当前方法更长的强变量中,例如一个实例变量),那么它就不会被任何人保留。 - fzwo
1
但我仍然对UIPopoverController的保留计数感到困惑。因为我在分配和初始化之前进行了检查。只有当它为空时,我才会分配一个新的。但是,在第一次分配后,我永远不会得到它为空的情况。我的意思是,我调用一个方法一次。在那里,我分配并初始化我的实例变量。下一次当我再次调用该方法时,这次我发现我的实例变量已经被分配了。如果ARC负责此事,那么它何时释放它。或者它是否自动释放? - Mikayil Abdullayev
@Mikayil 当对象被释放或设置为nil时,ARC会释放ivars。 - Felix
但是他们在文档中没有提到这一点,在“如何使用”部分中他们使用了局部变量。 - Amit Battan

11

当函数退出时,没有其他对弹出式窗口控制器的引用,因此它会过早地被释放。

尝试将其添加为类的成员变量。

蒂姆


我在它被释放之前不应该仍然能够看到它吗? - Mikayil Abdullayev

10

在@phix23的回答后,创建*poc属性如下:

@property (nonatomic, retain) IBOutlet UIPopoverController *poc;

然后改变

UIPopoverController *poc = [[UIPopoverController alloc] 
                            initWithContentViewController:picker];

对于

self.poc = [[UIPopoverController alloc] 
                            initWithContentViewController:picker];

11
你不必把它放在.h文件中。那样会使它变成公共的,除非你想要这样,否则只需将其作为.m文件中的属性即可。 - Joshua Dance

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接