首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >__weak似乎保留了对象

__weak似乎保留了对象
EN

Stack Overflow用户
提问于 2013-10-04 12:55:32
回答 1查看 130关注 0票数 1

如果对象被释放,则弱属性应该指向零,但在这种情况下,弱属性似乎保留了对象。考虑以下情况:

代码语言:javascript
复制
@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循环所有添加到缓存中的对象,并调用对应的块(参见下面)

代码语言:javascript
复制
-(void)callDeadObject
{
  [self saveReference];
  [[ObjectCache sharedInstance] callSillyObjectBlocks];
}

现在,saveReference退出,SillyObject应该被解除分配,但是它没有,弱引用也不是零。

缓存的相关实现细节:

代码语言:javascript
复制
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,添加的对象的相应块不应该被调用,但是它是用对象的值被调用的。输出:

代码语言:javascript
复制
100
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-10-04 13:05:43

每当您有一个从块外部引用变量的块时,您也需要声明它是弱的。否则你会得到强有力的推荐信。所以应该是:

代码语言:javascript
复制
-(void)saveReference
{
  SillyObject* s = [SillyObject new];
  s.val = 100;
  SillyObject * __weak weakSilly = s;

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

同时,您可以通过从其他几个位置删除__weak来简化代码,因为它们只会影响方法参数,在相关的时间内不会保留实例:

代码语言:javascript
复制
-(instancetype)initWithRef:(id)obj callback:(Callback)cb {
    ...
}

-(void)addWeakRef:(id)obj callback:(Callback)block
{
  [self.savedObjects addObject:[[CacheSlot alloc] initWithRef:obj callback:block]];
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19181732

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档