4

Objective-C クラス用の優れたブロックベースのイニシャライザを作成しようとしています。スーパークラスで宣言していますが、すべてのサブクラスで役立つようにしたいと考えています。

今私は持っています:

+ (id)createWithBlock:(void (^) (id newObject))creationBlock {
    id newObject = [self object];    
    creationBlock(newObject);
    return newObject;
}

そのように(サブクラスで)使用できるもの:

Record *newRecord = [Record createWithBlock:^(id newObject) {
    Record *newRecord = (Record *)newObject;
    newRecord.name = @"Ginger";
    newRecord.type = @"Rhizome";
}];

今はこれでいいのですが、もう少し減らしたいと思います。理想的には、次のようになります。

Record *newRecord = [Record createWithBlock:^{
    name = @"Ginger";
    type = @"Rhizome";
}];

しかし、それは少し野心的なようです。私も大丈夫です:

Record *newRecord = [Record createWithBlock:^(Record *newRecord) {
    newRecord.name = @"Ginger";
    newRecord.type = @"Rhizome";
}];

この最後のバージョンは、clang がコンパイル時にブロックの型チェックを行うように見えるため、難しいものです。上記は、上記の createWithBlock: の定義ではコンパイルされませんincompatible block pointer types initializing 'void (^)(struct Record *)', expected 'void (^)(struct objc_object *)

この強力な型チェックを行わなければ、実行時にメソッドを入れ替えることができました。(または、ブロック宣言を型定義すれば、今すぐそれを行うことができますか?)

私はしばらくこれについて頭を悩ませてきました.clang仕様を含め、見つけたブロックに関するほぼすべてのドキュメントを読みました。これはオープン ソース プロジェクトのためのものであり、このパターンはすべての Objective-C ユーザーに役立つと思います。

今、私の考えは に傾いていimp_implementationWithBlock()ます。しかし、その後、その内容に基づいて新しい IMP を「構築」し、交換する必要があります。実現可能?

4

1 に答える 1

3

どのコンパイラを使用していますか? LLVM の最近のバージョンは、あなたが提供した最後のコード例を受け入れると思います。(つまり、あなたが与えるエラーは起こらないはずです。)

特に、これは Xcode 4.3.3 の新しい Xcode プロジェクトの LLVM 3.1 で機能します。

于 2012-06-25T00:17:53.520 に答える