我正在尝试做一个简单的可重复使用的课程,该课程将启动一个动作表,从库或相机中选择pic,然后裁剪图像,然后将最终图像返回给调用者。
但是当我点击UIActionSheet中的任何按钮时,它会崩溃显示EXC_BAD_ACCESS
。
这是代码:
在我的MainViewController.m
- (IBAction)ClickOnAdd:(id)sender{
ImagePickerControl *pickerControl = [[ImagePickerControl alloc] initWithController:self Title:@"Chose Image" delegate:self cancelButtonTitle:@"Cancel" fromLibraryTitle:@"Library" fromCameraTitle:@"Camera"];
[pickerControl showInView:self.view];
}
ImagePickerControl.h中的代码
@protocol ImagePickerControlDelegate;
@interface ImagePickerControl : NSObject<UIActionSheetDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate>
@property (retain, nonatomic) UIActionSheet *menuSheet;
@property (assign, nonatomic) UIViewController *parentViewController;
- (id)initWithController:(UIViewController*) viewController Title:(NSString *)title delegate:(id<ImagePickerControlDelegate>)delegate cancelButtonTitle:(NSString *)cancelButtonTitle fromLibraryTitle:(NSString *)fromLibTitle fromCameraTitle:(NSString *)fromCamTitle;
-(void)showInView:(UIView*) parentView;
@end
@protocol ImagePickerControlDelegate <NSObject>
// Called when an image is picked. The view will be automatically dismissed after this call returns
- (void)imagePickerControlDidPickImage:(ImagePickerControl *)imagePickerControl pickedImage:(UIImage*)selectedImage;
// Called when we cancel the control's view
- (void)imagePickerControlDidCancel:(ImagePickerControl *)imagePickerControl;
@end
最后在ImagePickerControl.m
- (id)initWithController:(UIViewController*) viewController Title:(NSString *)title delegate:(id<NTImagePickerControlDelegate>)delegate cancelButtonTitle:(NSString *)cancelButtonTitle fromLibraryTitle:(NSString *)fromLibTitle fromCameraTitle:(NSString *)fromCamTitle
{
if(self = [super init]){
self.menuSheet = [[UIActionSheet alloc] initWithTitle:title
delegate:self cancelButtonTitle:cancelButtonTitle
destructiveButtonTitle:nil
otherButtonTitles:fromLibTitle,fromCamTitle,nil];
self.parentViewController = viewController;
}
return self;
}
-(void)showInView:(UIView*) parentView
{
[self.menuSheet showInView:parentView];
}
//This method was not called at all
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
}
经过快速研究后,我认为,从这个SO post开始,我的控制类在我调用之后就会被释放了。但在答案中,提到将控制器作为强属性分配给mainviewcontroller。但我不想通过创建属性和分配来使用它。只需在添加按钮单击时调用它并获取回调,就像我们使用UIActionSheet或UIAlertView一样。
还有一点需要注意的是,在我的ClickOnAdd
方法中,如果我删除自定义类并在那里添加UIActionSheet,那么回调工作正常。我期待使用我的班级的相同行为。怎么做?
提前致谢。
答案 0 :(得分:1)
您的代码的问题是,您的操作表会在clickButton的索引时解除分配。
您可以通过在“诊断”标签中启用Zombie Objects来轻松获取它(请参阅附件)。
在你的情况下你应该得到像
这样的错误-[ImagePickerControl actionSheet:clickedButtonAtIndex:]: message sent to deallocated instance
所以 pickerControl 应该是启动控制器中的iVar。
答案 1 :(得分:0)
正如在另一个答案中已经提到的那样,在点击按钮之前,您的ImagePickerControl
已被取消分配。因此,您的应用程序崩溃。
您应该使用ClickOnAdd
方法将选取器控制器分配给强大的ivar。然后在你的回调中(我假设MainViewController
在点击按钮时获得回调)你应该将此ivar设置为nil
,以便释放选择器控制器。
如果你没有使用ivar
,它可以在没有ARC
的情况下工作。在这种情况下,您可以将选择器控制器保留在内存中,方法是不在ClickOnAdd
上释放它并在回调上手动释放它。但是,这只是对内存泄漏的邀请,因此即使使用non-ARC
代码,我也会使用保留属性。
UIActionSheet
是UIView
的子类,因此我假设您在调用showInView
时将其添加到视图层次结构中并因此保留。它可能会在从层次结构中删除后立即释放,因此保留对它的强引用也是好的,以防它比预期更快发布。