尝试从我的自定义类调用UIActionSheet时,应用程序崩溃了

时间:2014-01-28 06:43:34

标签: objective-c ios7 automatic-ref-counting uiactionsheet

我正在尝试做一个简单的可重复使用的课程,该课程将启动一个动作表,从库或相机中选择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,那么回调工作正常。我期待使用我的班级的相同行为。怎么做?

提前致谢。

2 个答案:

答案 0 :(得分:1)

您的代码的问题是,您的操作表会在clickButton的索引时解除分配。

您可以通过在“诊断”标签中启用Zombie Objects来轻松获取它(请参阅附件)。

在你的情况下你应该得到像

这样的错误
-[ImagePickerControl actionSheet:clickedButtonAtIndex:]: message sent to deallocated instance

所以 pickerControl 应该是启动控制器中的iVar。

enter image description here

答案 1 :(得分:0)

正如在另一个答案中已经提到的那样,在点击按钮之前,您的ImagePickerControl已被取消分配。因此,您的应用程序崩溃。

您应该使用ClickOnAdd方法将选取器控制器分配给强大的ivar。然后在你的回调中(我假设MainViewController在点击按钮时获得回调)你应该将此ivar设置为nil,以便释放选择器控制器。

如果你没有使用ivar,它可以在没有ARC的情况下工作。在这种情况下,您可以将选择器控制器保留在内存中,方法是不在ClickOnAdd上释放它并在回调上手动释放它。但是,这只是对内存泄漏的邀请,因此即使使用non-ARC代码,我也会使用保留属性。

UIActionSheetUIView的子类,因此我假设您在调用showInView时将其添加到视图层次结构中并因此保留。它可能会在从层次结构中删除后立即释放,因此保留对它的强引用也是好的,以防它比预期更快发布。