1

カメラから画像を取得するクラスを作成しました。そのヘッダーは次のとおりです。

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 を使用しているため、 ImageGetter のインスタンスが の呼び出しの直後に割り当て解除される-requestImage...ため、 の弱いデリゲートが にpickerなることnilです。

このような問題を解決する一般的な方法はどれですか?

いくつかの方法を見ることができますが、どれも完全に正しいとは思えません。

  1. クライアント コードから ImageGetter を保持します。たとえば、それを強力なプロパティに割り当てます。ここでの問題は次のとおりです。画像を取得した直後にこのプロパティを nil に設定して解放することはできません。これは、このオブジェクトのメソッドの実行中にオブジェクトの保持カウントを 0 に設定することを意味するためです。また、不要なプロパティは必要ありません (まあ、大きな問題ではありませんが)。
  2. ImageGetter の ARC を無効にし、開始時に手動で保持し、画像をコールバックに送信した後に解放します。
  3. メソッドを持つ静的マネージャーImageGetterManagerrequestImage...を作成すると、ImageGetterインスタンスが作成され、保持され、requestImage...呼び出しがリダイレクトされ、それらからコールバックが取得され、解放されます。これが最も一貫した方法のように思えますが、このような小さなコードでは少し複雑ではありませんか?

では、どうすればそのようなクラスを構築できますか?

4

3 に答える 3

0

ARC に切り替えたときにこの問題が発生した場合は、オプション 1 を選択して、それを強力なプロパティとして定義する必要があります。

ただし、動作はオプション 1 で説明したものとは少し異なります。プロパティを nil に設定しても、オブジェクトがすぐに解放されるわけではなく、retaincount が減少するだけです。ARC はその問題を処理し、参照されたすべてのオブジェクトがオブジェクトを「解放」するとすぐに、オブジェクトは解放されます。

于 2013-11-13T12:40:24.793 に答える
0

次の戦略を使用できます。

ImageGetter* imgGetter = [[ImageGetter alloc] init];
[imgGetter requestImageInView:_viewController.view withCompletionBlock:^(UIImage *image) {
    // do stuff with taken image
    [imgGetter releaseCompletionBlock]; // With this line, the completion block will retain automatically imgGetter, which will be released after the release of the completionBlock.
}];

ImageGetter 実装クラス内で、このようにブロック内で呼び出すことができるメソッドを作成します。

-(void) releaseCompletionBlock
{
  completionBlock = nil;
}
于 2013-11-13T13:07:51.283 に答える