13

完了ハンドラーを「保存」する方法があるかどうか疑問に思っていました。

-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{

}

- (void)actionHere {
    completionHandler(UIBackgroundFetchResultNewData);
}

上記のように、別の関数で結果を送信したいと考えています。

4

3 に答える 3

33

tl;dr

コピー プロパティを宣言します (奇妙な構文、私は知っています... http://fuckingblocksyntax.com/ )

@property (nonatomic, copy) void (^completionHandler)(UIBackgroundFetchResult fetchResult);

次のように使用します

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    self.completionHandler = completionHandler;
}

- (void)actionHere {
    if (self.completionHandler)
        self.completionHandler(UIBackgroundFetchResultNewData);
}

討論

ブロックはObjective -C の本格的なオブジェクトですが、大きな違いがあります。デフォルトでは、ブロックはスタックに割り当てられます。

ブロックへの参照を保存したい場合は、それをヒープにコピーする必要があります。スタックにブロックを保持しても、スタック フレームが破棄されるたびにブロックが失われるのを防ぐことはできないからです。

ヒープにブロックをコピーするには、Block_Copy()関数を呼び出す必要があります。必要に応じてcopyメソッドを呼び出すことができます (前の関数が呼び出されます)。

属性を使用してプロパティを宣言すると、プロパティ セッターを介してオブジェクトを割り当てるたびにcopy、コンパイラが自動的に呼び出しを挿入します。copy

于 2013-10-04T01:00:38.730 に答える
2

ブロックはオブジェクトです (そうです、実際の ObjC オブジェクトです!)。唯一重要なことは、後で使用するために保存する必要があるときはいつでもブロックをコピーする必要があることです (保持しないでください)。

したがって、次のいずれかを行う必要があります。

_myCompletionHandler = [completionHandler copy];

また:

_myCompletionHandler = Block_copy(completionHandler);
于 2013-10-04T00:23:59.867 に答える