iOS闪退:Cannot form weak reference to instance (xxx) of class
Posted 长沙火山
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS闪退:Cannot form weak reference to instance (xxx) of class相关的知识,希望对你有一定的参考价值。
一、问题的描述
闪退日志:Cannot form weak reference to instance (0x161c6ddd0) of class JYCodeLoginController. It is possible that this object was over-released, or is in the process of deallocation.
这段日志大概的意思是说 JYCodeLoginController 的实例不能形成弱引用,它可能被过度释放或者正在被取消分配的过程中。
出现这种问题的原因是在dealloc方法中,调用了如下代码:
- (void)dealloc
__weak __typeof(self)weak_self = self;
NSLog(@"%@", weak_self);
二、产生问题的原因
原因如下:__weak 会调用weak_register_no_lock,里边有对于当前实例是否处在deallocating状态(正在被释放的状态)的判断,如果处在deallocating状态,则crash。
id
weak_register_no_lock(weak_table_t *weak_table, id referent_id, id *referrer_id)
objc_object *referent = (objc_object *)referent_id;
objc_object **referrer = (objc_object **)referrer_id;
if (!referent || referent->isTaggedPointer()) return referent_id;
// ensure that the referenced object is viable
bool deallocating;
if (!referent->ISA()->hasCustomRR())
deallocating = referent->rootIsDeallocating();
else
BOOL (*allowsWeakReference)(objc_object *, SEL) =
(BOOL(*)(objc_object *, SEL))
object_getMethodImplementation((id)referent,
SEL_allowsWeakReference);
if ((IMP)allowsWeakReference == _objc_msgForward)
return nil;
deallocating =
! (*allowsWeakReference)(referent, SEL_allowsWeakReference);
if (deallocating)
_objc_fatal("Cannot form weak reference to instance (%p) of "
"class %s. It is possible that this object was "
"over-released, or is in the process of deallocation.",
(void*)referent, object_getClassName((id)referent));
// now remember it and where it is being stored
weak_entry_t *entry;
if ((entry = weak_entry_for_referent(weak_table, referent)))
append_referrer(entry, referrer);
else
weak_entry_t new_entry;
new_entry.referent = referent;
new_entry.out_of_line = 0;
new_entry.inline_referrers[0] = referrer;
for (size_t i = 1; i < WEAK_INLINE_COUNT; i++)
new_entry.inline_referrers[i] = nil;
weak_grow_maybe(weak_table);
weak_entry_insert(weak_table, &new_entry);
// Do not set *referrer. objc_storeWeak() requires that the
// value not change.
return referent_id;
三、解决办法
在实际项目中,一般不会直接在dealloc方法中调用weakSelf,而是间接的调用了某个方法,里面包含了weakSelf的操作。比如下面这种情况:
- (void)dealloc
[self.loginUIView stopDurationTimer];
在dealloc方法中,有一个定时器释放的操作,而这个loginUIView是采用懒加载创建的:
- (JYLoginUIView *)loginUIView
if (!_loginUIView)
_loginUIView = [[JYLoginUIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT-120)];
_loginUIView.loginDelegate = self; //loginDelegate是用weak修饰的
[self.view addSubview:_loginUIView];
return _loginUIView;
在deallcoc中如果loginUIView不存在,就会调用懒加载的方法去创建loginUIView,而在创建loginUIView有一个delegate的赋值,而这个delegate是用weak修饰的,所以就相当于是间接的在dealloc方法中做了weakSelf的操作,也会造成闪退。
解决办法:
- (void)dealloc
[_loginUIView stopDurationTimer];
以上是关于iOS闪退:Cannot form weak reference to instance (xxx) of class的主要内容,如果未能解决你的问题,请参考以下文章
iOS闪退:Cannot form weak reference to instance (xxx) of class
iOS之报错“Cannot create __weak reference in file using manual reference counting”解决办法
weak cannot be applied to non-class type '.......'
Xcode 7.3 cannot create __weak reference in file using manual reference counting
Cannot synthesize weak property in file using manual reference counting解决方案
Cannot create __weak reference in file using manual reference counting