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