3

私がブロックをサポートすることを期待するすべてのものの中で、不思議なことに NSUndoManager はサポートしていないようです。これには何らかの固有の理由があるのでしょうか、それとも Apple は単にこの API のビットを最新化することに取り組まなかったのでしょうか?

特に、NSObject でメソッドを定義したいと思います。

- (void)performBlock {
    void (^block)(void) = (id)self;
    block();
}

電話できるようにするには、

[[undoManager prepareWithInvocationTarget:^{
    NSLog( @"hello world" );
}] performBlock];

私は何かを逃しましたか?これに問題はありますか?

(2009 年の Mike Ash の記事に触発され、ブロックでメソッドを定義しないことを推奨しています。私もそこにコメントを残しました。)

4

1 に答える 1

2

マイクの主な論点は、このアイデアに根本的な問題があるということではなく、読みにくいコードを作成することだと思います。

しかし、私はあなたが書いたものにいくつかの問題があります。1つは、NSObjectにカテゴリメソッドを追加することですが、ブロックではないオブジェクトでそれを呼び出すと、クラッシュします。おそらく、それを修正する方法がありperformBlockます。たとえば、非ブロックで呼び出された場合にメソッドが何もしないようにする、または少なくともクラッシュする前にエラーをログに記録するなどです。私はこれがどのように機能するか正確にはわかりません。

また、ブロックはスタックから開始されるため、後で実行できるようにブロックを保持するメソッドに渡す前に、ブロックをコピーする必要があります。ブロックを取るように書かれたメソッドはこれを処理します。おそらく-[NSUndoManager prepareWithInvocationTarget:]、渡されたターゲットをコピーしません。したがって、ブロックを渡す前に、(-copyまたはのいずれかを使用して)自分でブロックをコピーする必要があります。Block_copy()

void (^block)(void) = [^{
    NSLog(@"hello world");
} copy];

[[undoManager prepareWithInvocationTarget:block] performBlock];
[block release];

少なくとも初期のバージョンのARCでは、ブロックがid(Mike AshのARC記事のブロックセクションで説明されているように)を期待するメソッドに渡されているため、これは依然として問題でした。おそらくそれは修正されましたか?私はそれを当てにしないでしょう...

于 2012-07-18T04:40:10.983 に答える