美文网首页
iOS "weak reference" 自

iOS "weak reference" 自

作者: 派大星的博客 | 来源:发表于2019-01-12 16:19 被阅读0次
    1、什么意思

    在OC中,向nil发消息不会导致崩溃,向野指针发送消息会造成crash。

    所以如下图,weak reference 指向的Object,在没有strong reference指向时,【Object dealloc】后,Weak_ref会被自动置为nil,而不会变成野指针。

    weak 变量自动置nil
    2、runtime 如何实现weak变量的自动置nil?

    weak 对象会放入一个 hash 表中。用 weak 指向的对象内存地址作为 key,当此对象的引用计数为0的时候会 dealloc。假如 weak 指向的对象内存地址是ADDRESS(0X2333333),那么就会以ADDRESS为键, 在这个 weak 表中搜索,找到所有以ADDRESS为键的 weak 对象,从而设置为 nil。

    3、具体机制

    objc_storeWeak(&weakPo, Model)函数:

    objc_storeWeak函数把赋值对象(Model)的内存地址作为键值key,将weak修饰的属性变量(weakPo)的内存地址(& weakPo)作为value,注册到 weak 表中。

    如果Model为0(nil),那么把变量(weakPo)的内存地址(& weakPo)从weak表中删除,可以把objc_storeWeak(&weakPo, Model)理解为:objc_storeWeak(value, key),并且当key变nil,将value置nil。

    在Model非nil时,weakPo和Model指向同一个内存地址,在Model变nil时,weakPo变nil。此时向weakPo发送消息不会崩溃:在Objective-C中向nil发送消息是安全的。

    源码链接

    /*
     * Copyright (c) 2010-2011 Apple Inc. All rights reserved.
     *
     * @APPLE_LICENSE_HEADER_START@
     * 
     * This file contains Original Code and/or Modifications of Original Code
     * as defined in and that are subject to the Apple Public Source License
     * Version 2.0 (the 'License'). You may not use this file except in
     * compliance with the License. Please obtain a copy of the License at
     * http://www.opensource.apple.com/apsl/ and read it before using this
     * file.
     * 
     * The Original Code and all software distributed under the License are
     * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
     * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
     * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
     * Please see the License for the specific language governing rights and
     * limitations under the License.
     * 
     * @APPLE_LICENSE_HEADER_END@
     */
    
    #ifndef _OBJC_WEAK_H_
    #define _OBJC_WEAK_H_
    
    #include <objc/objc.h>
    #include "objc-config.h"
    
    __BEGIN_DECLS
    
    /*
    The weak table is a hash table governed by a single spin lock.
    An allocated blob of memory, most often an object, but under GC any such 
    allocation, may have its address stored in a __weak marked storage location 
    through use of compiler generated write-barriers or hand coded uses of the 
    register weak primitive. Associated with the registration can be a callback 
    block for the case when one of the allocated chunks of memory is reclaimed. 
    The table is hashed on the address of the allocated memory.  When __weak 
    marked memory changes its reference, we count on the fact that we can still 
    see its previous reference.
    
    So, in the hash table, indexed by the weakly referenced item, is a list of 
    all locations where this address is currently being stored.
     
    For ARR, we also keep track of whether an arbitrary object is being 
    deallocated by briefly placing it in the table just prior to invoking 
    dealloc, and removing it via objc_clear_deallocating just prior to memory 
    reclamation.
    
    */
    
    /// The address of a __weak object reference
    typedef objc_object ** weak_referrer_t;
    
    #if __LP64__
    #define PTR_MINUS_1 63
    #else
    #define PTR_MINUS_1 31
    #endif
    
    /**
     * The internal structure stored in the weak references table. 
     * It maintains and stores
     * a hash set of weak references pointing to an object.
     * If out_of_line==0, the set is instead a small inline array.
     */
    #define WEAK_INLINE_COUNT 4
    struct weak_entry_t {
        DisguisedPtr<objc_object> referent;
        union {
            struct {
                weak_referrer_t *referrers;
                uintptr_t        out_of_line : 1;
                uintptr_t        num_refs : PTR_MINUS_1;
                uintptr_t        mask;
                uintptr_t        max_hash_displacement;
            };
            struct {
                // out_of_line=0 is LSB of one of these (don't care which)
                weak_referrer_t  inline_referrers[WEAK_INLINE_COUNT];
            };
        };
    };
    
    /**
     * The global weak references table. Stores object ids as keys,
     * and weak_entry_t structs as their values.
     */
    struct weak_table_t {
        weak_entry_t *weak_entries;
        size_t    num_entries;
        uintptr_t mask;
        uintptr_t max_hash_displacement;
    };
    
    /// Adds an (object, weak pointer) pair to the weak table.
    id weak_register_no_lock(weak_table_t *weak_table, id referent, id *referrer);
    
    /// Removes an (object, weak pointer) pair from the weak table.
    void weak_unregister_no_lock(weak_table_t *weak_table, id referent, id *referrer);
    
    #if !NDEBUG
    /// Returns true if an object is weakly referenced somewhere.
    bool weak_is_registered_no_lock(weak_table_t *weak_table, id referent);
    #endif
    
    /// Assert a weak pointer is valid and retain the object during its use.
    id weak_read_no_lock(weak_table_t *weak_table, id *referrer);
    
    /// Called on object destruction. Sets all remaining weak pointers to nil.
    void weak_clear_no_lock(weak_table_t *weak_table, id referent);
    
    __END_DECLS
    
    #endif /* _OBJC_WEAK_H_ */
    

    相关文章

      网友评论

          本文标题:iOS "weak reference" 自

          本文链接:https://www.haomeiwen.com/subject/dpoqdqtx.html