我写了一个类,可以从相机中获取图像。其标题如下:

typedef void(^ImageTakenCallback)(UIImage *image);

@interface ImageGetter : NSObject <UIImagePickerControllerDelegate, UIPopoverControllerDelegate>
{
    UIImagePickerController *picker;
    ImageTakenCallback completionBlock
}

-(void) requestImageInView:(UIView*)view withCompletionBlock:(void(^)(UIImage*))completion;

@end

如您所见,我正在尝试在客户端代码中做类似的事情:
[[[ImageGetter alloc] init] requestImageInView:_viewController.view withCompletionBlock:^(UIImage *image) {
    // do stuff with taken image
}];

这是我实现ImageGetter的方式:
-(void) requestImageInView:(UIView*)view withCompletionBlock:(ImageTakenCallback)completion
{
    completionBlock = [completion copy];

    picker = [[UIImagePickerController alloc] init];
    picker.sourceType = UIImagePickerControllerSourceTypeCamera;
    picker.delegate = self;
    [view addSubview:picker.view];
}

- (void)imagePickerController:(UIImagePickerController *)picker_
        didFinishPickingImage:(UIImage *)image
                  editingInfo:(NSDictionary *)editingInfo
{
    [picker.view removeFromSuperview];
    picker = nil;

    completionBlock(image);
}

问题是,由于我使用的是ARC,因此在调用-requestImage...后立即释放了ImageGetter实例,因此picker的弱委托变成了nil

解决此问题的常用方法有哪些?

我可以看到一些方法,但是,似乎没有一种是正确的:
  • 保留客户端代码中的ImageGetter,例如,将其分配给强属性。这里的问题是:我将无法在获取图像后立即将此属性设置为nil来释放它,因为这将意味着在执行该对象的方法时将对象的保留计数设置为0。另外,我不要不必要的属性(虽然这不是一个大问题,但是尽管如此)。
  • 为ImageGetter禁用ARC,并在启动时手动保留并在将图像发送到回调后释放。
  • 创建静态管理器ImageGetterManager,它将具有requestImage...方法,它将创建ImageGetter实例,保留它们,重定向requestImage...调用,从它们获取回调并释放。这似乎是最一致的方法,但是对于这样的少量代码来说是否有点复杂?

  • 那么我该如何建立这样的 class 呢?

    最佳答案

    您可以在ImageGetter类中通过创建和释放“自引用”来解决该问题。
    在实现文件的类扩展中,声明一个属性

    @interface ImageGetter ()
    @property (strong, nonatomic) id selfRef;
    @end
    

    requestImageInView:中,设置self.selfRef = self以防止取消分配。

    在完成方法中,设置self.selfRef = nil

    备注:实际上,即使使用ARC,您也可以管理保留计数:
    CFRetain((__bridge CFTypeRef)(self));   // Increases the retain count to prevent deallocation.
    CFRelease((__bridge CFTypeRef)(self));  // Decreases the retain count.
    

    但是我不确定这是否被认为是ARC的“良好编程”。
    欢迎任何反馈!

    10-08 09:45