6

私のクラスでは、次のdispatch_queue_tように宣言されたプロパティがあります。

@property (nonatomic, assign) dispatch_queue_t queue;

次に、私のinitメソッドで次のことを行います。

- (id)initWithServerUrls: (NSString*)serverUrls
{
    if (self = [super init])
    {
        _queue = dispatch_queue_create("com.xxx.my_send_queue", DISPATCH_QUEUE_SERIAL);
    }

    return self;
}

Xcode 4.4.1では、それは機能し、問題を引き起こしませんでした(アプリは+アプリストアでテストされました)。Xcode 4.5にアップグレードした後、アプリがEXC_BAD_ACCESSでクラッシュし、Xcodeがその行に次のような警告を表示します。

保持されたオブジェクトをunsafe_unretained変数に割り当てます。オブジェクトは割り当て後に解放されます

AppleはXcode4.5のコンパイラをLLVM4.0からLLVM4.1に更新しましたが、コードが現在クラッシュしている理由がわかりません。

コードをステップスルーすると、その行の直後にクラッシュが発生します。何が間違っている可能性があり、どうすれば修正できますか?

解決:

両方のSDKで動作させることができました。追加しました:

#if OS_OBJECT_USE_OBJC
@property (nonatomic, strong) dispatch_queue_t queue; // this is for Xcode 4.5 with LLVM 4.1 and iOS 6 SDK
#else
@property (nonatomic, assign) dispatch_queue_t queue; // this is for older Xcodes with older SDKs
#endif

誰かがそれが役に立つと思うことを願っています

4

1 に答える 1

13

まず、ターゲット プラットフォームが 5 以上の場合は、iOS 5 SDK でビルドすることを強くお勧めします。より新しい SDK でビルドして「ターゲット」を設定することは機能しますが、多くの問題があります (特に、サポートされていないメソッドを使用した場所を見つけるためのコンパイラのヘルプが得られないことは問題です)。答え 1: iOS 5 が必要です。iOS 5 に対してビルドしますが、これは問題ではありません。

iOS 6 ではdispatch_queue_t、ObjC オブジェクトです。これは大きな改善です。つまり、プロパティを作成するだけstrongで、後は ARC が処理します。iOS 6 をターゲットにしている場合、これでうまくいくはずです。

iOS 5 と iOS 6 で同じコードをビルドする必要がある場合は、必要なときにメモリ管理を配置し、不要なときに除外できるように、どちらがどちらであるかを知る必要があります。使用する正しいテストは#if OS_OBJECT_USE_OBJC. これはコンパイル時のチェックであることを忘れないでください。これは、さまざまな SDK に対して記述したいコードを処理する場合にのみ適用されます。特定の SDK の場合、動作はいずれかの方法になります。

「unsafe_unretained」と「assign」の混乱について: この場合、それらは同じものです。「割り当て」は非オブジェクトにのみ適用されます。「unsafe_unretained」は、オブジェクトに適用されたときに「assign」が変換されるものです。そして iOS6 ではdispatch_queue_t、オブジェクトです。

もう 1 つの回避策があります。特に、iOS 6 SDK を使用してビルドする際に古いメモリ管理コードを保持したい場合は特にそうです。-DOS_OBJECT_USE_OBJC=0コンパイラに渡すことができます。これにより、新しいモデルがオプトアウトされます。しかし、これは最後の手段としてお勧めします。詳しくはos/object.hSDK内の をご覧ください。(Cmd-Shift-O、object.h)

于 2012-09-20T13:47:07.073 に答える