1

以下のコードでは、GCC_OPTIMIZATION_LEVEL を None に設定して実行すると、実行は期待どおりに機能し、コンソールに次のように出力されます。

My Obj - SomeObj

ただし、GCC_OPTIMIZATION_LEVEL を Xcode ターゲット構成で Fastest, Smallest に設定すると (通常、リリース ビルドで行うように)、コンソールに次のように出力されます。

My obj - (null)

[Foo doSomething] の __weak id myObj 変数に格納すると、オブジェクトが解放されているように見えます。myObj 変数から __weak フラグを削除すると、GCC_OPTIMIZATION_LEVEL が Fastest, Smallest に設定されているときに、コードが期待どおりに実行されます。

この例は、別のプロジェクトで使用した同様のパターンに基づいて作成し、保持サイクルが発生していたため、__weak フラグを追加しました。リテイン サイクルの警告はなくなりましたが、Release 用にビルドしたときに、この例でログに記録している場所に到達するまでに myObj が nil になることがわかりました。

__weak フラグを設定することで、どのような規則に違反していますか?

#import "FFAppDelegate.h"


///////////////////////////////////////////////////////
@interface SomeObject : NSObject

@end

@implementation SomeObject

- (NSString *)description; {
    return @"SomeObject";
}

@end


///////////////////////////////////////////////////////
@interface Factory : NSObject
@end

@implementation Factory

- (id)generateObj {
    id myObj = nil;
    if (!myObj) {
        SomeObject *anObj = [[SomeObject alloc] init];
        myObj = anObj;
    }
    return myObj;
}


@end


///////////////////////////////////////////////////////
@interface Bar : NSObject

- (id)barObj;

@end

@implementation Bar
{
    Factory *factory;
}

- (id)init {
    self = [super init];
    if (self) {
        factory = [[Factory alloc] init];
    }
    return self;
}
- (id)barObj {
    id anObj = [factory generateObj];
    return anObj;
}

@end


///////////////////////////////////////////////////////
@interface Foo : NSObject

@property (strong) Bar *aBar;

- (void)doSomething;

@end

@implementation Foo

- (id)init {
    self = [super init];
    if (self) {
        _aBar = [[Bar alloc] init];
    }
    return self;
}

- (void)doSomething {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        __weak id myObj = [self.aBar barObj];
        NSLog(@"My Obj - %@", myObj);
    });
}

@end


///////////////////////////////////////////////////////
@implementation FFAppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    Foo *f = [[Foo alloc] init];
    [f doSomething];
}

@end
4

2 に答える 2

3

__weak フラグを設定することで、どのような規則に違反していますか?

あなたの例では、から返されたインスタンスへの強い参照はありません[self.aBar barObj]myObjしたがって、変数を読み取るまでにインスタンスが有効であると想定することはできません。

最適化されていないビルドでは、返されたインスタンスは自動解放プールに追加されているため、印刷してもまだ生きていますmyObj。でブレークポイントを設定すると、これを確認できます-[SomeObject dealloc]

最適化されたビルドでは、ARC は自動解放プールを回避しているため、返されたインスタンスはすぐに割り当て解除されます。

詳細については、Clang ARC ドキュメントのセクション 3.2.3 を参照してください。具体的には:

そのような関数またはメソッドから戻るとき、ARC は return ステートメントの評価の時点で値を保持し、次にすべてのローカル スコープを離れて、値が呼び出し境界を越えて存在することを保証しながら、保持のバランスを取ります。最悪の場合、これには自動解放が含まれる可能性がありますが、呼び出し元は値が実際に自動解放プールにあると想定してはなりません

を使用__weakして保持サイクルを回避する場合は、オブジェクトを存続させるために、どこかに強い参照があることを確認する必要があります。

于 2013-05-25T05:56:59.657 に答える
-1

おそらく、GCC ではなく、Apple のデフォルト コンパイラ LLVM を使用する必要があります。

編集:また、あなたの「ファクトリー」メソッドは間違っているようです。たとえば、その if では、オブジェクトは常に nil です。ツアーに参加してください: http://developer.apple.com/library/ios/#documentation/general/conceptual/CocoaEncyclopedia/ClassFactoryMethods/ClassFactoryMethods.html

于 2013-05-25T07:57:06.957 に答える