3

異なる型のいくつかの異なる変数を持つ構造を作成しようとしています。

いくつかの型は NSString ですが、これを行おうとするとエラーが発生しました

ARC forbids Objective-C objects in structs or unions

エラーについて読んだので、追加するのが賢明だと思います

__unsafe_unretained

NSString宣言の前に、しかし、これがどのような影響を与えるかはわかりません.

  • __強い
  • __弱い
  • __unsafe_unretained

しかし、その前に __unsafe_unretained を持つ構造体にある NSString で何が起こっているのかについてはまだ漠然としていて、誰かが何が起こっているのか、メモリに関して将来何を考える必要があるのか​​ を教えてくれることを望んでいました。

任意の助けをいただければ幸いです。

4

4 に答える 4

10

ARC の下で、次のような構造体を宣言できるとします。

typedef struct {
    __strong NSObject *someObject;
    int someInteger;
} MyStruct;

次に、次のようなコードを記述できます。

MyStruct *thing = malloc(sizeof(MyStruct));

問題:malloc返されるメモリをゼロで埋めません。ランダムthing->someObjectな値も同様です - 必ずしも NULL ではありません。次に、次のように値を割り当てます。

thing->someObject = [[NSObject alloc] init];

内部では、ARC はそれを次のようなコードに変換します。

NSObject *temporary = [[NSObject alloc] init];
[thing->someObject release];
thing->someObject = temporary;

ここでの問題は、プログラムがreleaseランダムな値を送信したことです! この時点でアプリがクラッシュする可能性があります。

これを防ぐために、ARC は への呼び出しを認識し、NULL へmallocの設定を処理する必要があると言うかもしれません。someObject問題はmalloc、次のように他の関数にラップされる可能性があることです。

void *myAllocate(size_t size) {
    void *p = malloc(size);
    if (!p) {
        // malloc failed.  Try to free up some memory.
        clearCaches();
        p = malloc(size);
    }
    return p;
}

OK、今度は ARC も関数について知る必要がありますmyAllocate...そしてそれは、バイナリとして取得した静的ライブラリ内にある可能性があります。

アプリには、毎回使用せずに古い割り当てをリサイクルする独自のメモリ アロケータがある場合もありfreeますmalloc。そのため、メモリを返す前にメモリをゼロで埋めるように変更mallocしても機能しません。ARC は、プログラム内のすべてのカスタム アロケーターを認識している必要があります。

これを確実に機能させることは非常に困難です。代わりに、ARCの作成者はあきらめて、「忘れてください。__strongおよび参照を構造体に入れることはできません__weak。」</p>

__unsafe_unretainedそのため、ARC に「これが参照するオブジェクトの所有権を管理しようとしないでください」と指示 した場合にのみ、オブジェクト ポインターを構造体に配置できます。</p>

__unsafe_unretainedおそらくCFRetainandを使用して、オブジェクト参照を含む構造体を使用して、CFReleaseそれらを手動で保持および解放することができます。次に、そのような構造体の配列を作成できます。これはエラーが発生しやすいため、プロファイラーがパフォーマンスにとって重要であると判断した場合にのみ実行してください。

代わりに、構造体の代わりに新しい Objective-C クラスを作成するだけです。@property構造体に入れるフィールドごとにクラスを指定します。を使用しNSMutableArrayて、この新しいクラスのインスタンスの配列を管理します。

于 2012-08-08T04:23:58.210 に答える
4

もう少し考えてみよう...

非目的の C コードで ARC ポインターが本当に必要な場合は、C++ でネイティブに使用できます。

実際、すべての標準テンプレート コンテナーに ARC ポインターを格納できますが、それらは適切なセマンティクスを保持しています (笑)。

struct Foo {
    NSDictionary *dictionary;
    NSString *string;
    __weak UIViewController *viewController;
};

std::list<UIView*> views;

コンパイラは ARC ポインターを重要なコンストラクターを持つオブジェクトとして扱うため、通常のセマンティクスを持つことができます。

彼らの ARC の栄光はすべて魔法のように処理されます。

于 2012-08-08T04:47:35.740 に答える
-3

構造体にObjectiveCオブジェクトを入れないでください。そのため、ObjCはクラスをサポートしています。あなたはCをコーディングしています。

于 2012-08-08T03:21:12.030 に答える