0

弱い引数を使用する小さな例を次に示します。

@interface MYTestObject : NSObject

@end

@implementation MYTestObject {
   void(^_block)(void);
}

- (void)dealloc {
   NSLog(@"DEALLOC!");
}

- (id)init {
   if (self = [super init]) {
      [self doSomethingWithObject:self];
   }
   return self;
}

- (void)doSomethingWithObject:(id __weak /* <- weak argument! */)obj {
   _block = ^{
      NSLog(@"%p", obj);
   };
}

@end

そしてそれは動作します:-deallocと呼ばれます! また、削除する__weakと保持サイクルが発生し、それは完全に正しいです。

それが単なる副作用であり、弱い引数を使用するのは完全に安全ではないのだろうか? それとも、特定の動作で、私はただの悪い Google ユーザーですか?

4

1 に答える 1

5

2 つの観察:

  1. キャプチャ時に強力な参照サイクルを回避するで説明されているように、引数にするのではなく、 内でローカル__weak参照を作成する傾向があります。doSomethingWithObject__weakself

    あなたが尋ねたように、「弱い引数を使用するのは完全に安全ではない」とは思いません。しかし、他に何もないとしても、ローカル変数を使用するのがより一般的なパターンであり、メソッドのパブリック インターフェイスの一部ではなく__weak、実装の詳細として適切であると思います。doSomethingWithObject

  2. また、メモリ修飾子を使用blockしてプロパティを作成します。ドキュメントが言うようcopy

    copy元のスコープ外でキャプチャされた状態を追跡するためにブロックをコピーする必要があるため、プロパティ属性として指定する必要があります。これは自動的に行われるため、自動参照カウントを使用する際に心配する必要はありませんが、結果の動作をプロパティ属性で表示することをお勧めします。

したがって:

@interface MYTestObject : NSObject
@property (nonatomic, copy) void(^block)(void);
@end

@implementation MYTestObject

- (void)dealloc {
    NSLog(@"DEALLOC!");
}

- (id)init {
    if (self = [super init]) {
        [self doSomethingWithObject:self];
    }
    return self;
}

- (void)doSomethingWithObject:(MYTestObject *)obj { 
    
    typeof(obj) __weak weakObj = obj;
    
    self.block = ^{
        NSLog(@"%p", weakObj);
    };
}

@end
于 2013-08-19T18:00:39.680 に答える