1

オブジェクトの割り当てが解除された場合、Objective-C の弱いプロパティは nil を指す必要がありますが、この場合、弱いプロパティはオブジェクトを保持しているように見えます。ケースを考えてみましょう:

@interface SillyObject : NSObject

@property (nonatomic, assign) NSInteger val;

-(void)printVal;

@end

@implementation SillyObject

-(void)printVal
{
  NSLog(@"%d", self.val);
}

@end

-(void)saveReference
{
  SillyObject* s = [SillyObject new];
  s.val = 100;

  [[ObjectCache sharedInstance] addWeakRef:s callback:^(NSString* junk) {
    [s printVal];
  }];
}

callSillyObjectBlocks は、キャッシュに追加されたすべてのオブジェクトをループし、対応するブロックを呼び出します (以下を参照)。

-(void)callDeadObject
{
  [self saveReference];
  [[ObjectCache sharedInstance] callSillyObjectBlocks];
}

saveReference が終了し、SillyObject の割り当てを解除する必要がありますが、そうではなく、弱参照は nil ではありません。

関連するキャッシュの実装の詳細:

typedef void (^Callback)(NSString* junk);

@interface CacheSlot : NSObject

@property (nonatomic, copy) Callback callback;
@property (nonatomic, weak) id source;
// More irrelevant properties.

-(instancetype)initWithRef:(__weak id)obj callback:(Callback)cb;

@end

@implementation CacheSlot

@synthesize callback, source;

-(instancetype)initWithRef:(__weak id)obj callback:(Callback)cb
{
  self = [super init];
  if(self)
  {
    self.callback = cb;
    self.source = obj;
  }
  return self;
}

@end

@interface ObjectCache()

// This array contains CacheSlot objects
@property (nonatomic, strong) NSMutableArray* savedObjects;
@end

// Implementation.
-(void)addWeakRef:(id)obj callback:(Callback)block
{
  __weak id src = obj;
  [self.savedObjects addObject:[[CacheSlot alloc] initWithRef:src callback:block]];
}

-(void)callSillyObjectBlocks
{
  for(CacheSlot* slot in self.savedObjects)
  {
    if(slot.source)
    {
      slot.callback(@"Whatever!");
    }
    else
    {
      // Remove the slot from cache
    }
  }
}

最初に saveReference を呼び出すと、関数が終了するとすぐに解放される一時オブジェクトが作成されます (代わりに addWeakRef:nil を呼び出すとそうなります)。

saveReference を呼び出した後、callSillyObjectBlocks を実行すると、追加されたオブジェクトの対応するブロックは呼び出されませんが、オブジェクトの値で呼び出されます。出力:

100
4

1 に答える 1

3

ブロックの外部から変数を参照するブロックがある場合は常に、それも弱いとして宣言する必要があります。そうしないと、強力な参照が得られます。したがって、次のようになります。

-(void)saveReference
{
  SillyObject* s = [SillyObject new];
  s.val = 100;
  SillyObject * __weak weakSilly = s;

  [[ObjectCache sharedInstance] addWeakRef:s callback:^(NSString* junk) {
    [weakSilly printVal];
  }];
}

同時に、__weak関連する時間のインスタンスを保持しないメソッド引数のみに影響するため、他のいくつかの場所から削除することでコードを簡素化できます。

-(instancetype)initWithRef:(id)obj callback:(Callback)cb {
    ...
}

-(void)addWeakRef:(id)obj callback:(Callback)block
{
  [self.savedObjects addObject:[[CacheSlot alloc] initWithRef:obj callback:block]];
}
于 2013-10-04T13:05:43.977 に答える