Objective-C基础-内存管理

2019-08-04  本文已影响0人  学习天亦

1、CADisplayLink、NSTimer使用

CADisplayLink、NSTimer会对target产生强引用,如果target又对它们产生强引用,那么就会引发循环引用
解决方案

__weak typeof(self) weakSelf = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 repeats:YES block:^(NSTimer *timer) {
    [weakSelf test];
}];

- (void)test {
    
}
@interface SRProxy : NSProxy
+ (instancetype)proxyWithTarget:(id)target;
@property (weak, nonatomic) id target;
@end

@implementation SRProxy

+ (instancetype)proxyWithTarget:(id)target {
    // NSProxy对象不需要调用init,因为它本来就没有init方法
    SRProxy *proxy = [SRProxy alloc];
    proxy.target = target;
    return proxy;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    return [self.target methodSignatureForSelector:sel];
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    [invocation invokeWithTarget:self.target];
}
@end

self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                              target:[SRProxy proxyWithTarget:self]
                                            selector:@selector(test)
                                            userInfo:nil
                                             repeats:YES];
                                             
- (void)test {
    
}

2、GCD定时器

dispatch_queue_t queue = dispatch_queue_create("queue", NULL);

//创建定时器
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
//设置时间
uint64_t start = 2.0; // 2秒后开始执行
uint64_t interval = 1.0; // 每隔1秒执行
dispatch_source_set_timer(timer,
                          dispatch_time(DISPATCH_TIME_NOW, (int64_t)(start * NSEC_PER_SEC)),
                          interval * NSEC_PER_SEC,
                          0 * NSEC_PER_SEC);
    
//设置回调
dispatch_source_set_event_handler(timer, ^{
    
});
    
//启动定时器
dispatch_resume(timer);

3、iOS程序的内存布局

内存布局.jpg

4、Tagged Pointer

//objc-internal.h
#if TARGET_OS_OSX && __x86_64__
    // 64-bit Mac - tag bit is LSB
#   define OBJC_MSB_TAGGED_POINTERS 0
#else
    // Everything else - tag bit is MSB
#   define OBJC_MSB_TAGGED_POINTERS 1
#endif

#if OBJC_MSB_TAGGED_POINTERS
#   define _OBJC_TAG_MASK (1UL<<63)
#else
#   define _OBJC_TAG_MASK 1UL
#endif
//objc-internal.h
static inline bool 
_objc_isTaggedPointer(const void * _Nullable ptr) 
{
    return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
}

例子
多线程访问设置NSString崩溃

@interface ViewController ()
@property (strong, nonatomic) NSString *name;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    for (int i = 0; i < 1000; i++) {
        dispatch_async(queue, ^{
            self.name = [NSString stringWithFormat:@"abcdefghijk"];
        });
    }
}
@end

将字符串改为短点的abc不崩溃,因为abc直接存储到name的指针中。

@interface ViewController ()
@property (strong, nonatomic) NSString *name;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    for (int i = 0; i < 1000; i++) {
        dispatch_async(queue, ^{
            self.name = [NSString stringWithFormat:@"abc"];
        });
    }
}
@end

5、OC对象的内存管理

extern void _objc_autoreleasePoolPrint(void);

6、copy和mutableCopy

Left Aligned copy mutableCopy
NSString NSString(浅拷贝) NSMutableString(深拷贝)
NSMutableString NSString(深拷贝) NSMutableString(深拷贝)
NSArray NSArray(浅拷贝) NSMutableArray(深拷贝)
NSMutableArray NSArray(深拷贝) NSMutableArray(深拷贝)
NSDictionary NSDictionary(浅拷贝) NSMutableDictionary(深拷贝)
NSMutableDictionary NSDictionary(深拷贝) NSMutableDictionary(深拷贝)

7、引用计数的存储

在64bit中,引用计数可以直接存储在优化过的isa指针中,也可能存储在SideTable类中

struct SideTable {
    spinlock_t slock;
    RefcountMap refcnts;
    weak_table_t weak_table;
};

struct weak_table_t {
    weak_entry_t *weak_entries;
    size_t    num_entries;
    uintptr_t mask;
    uintptr_t max_hash_displacement;
};

refcnts是一个存放着对象引用计数的散列表

8、dealloc

当一个对象要释放时,会自动调用dealloc,接下的调用轨迹是

dealloc
_objc_rootDealloc
rootDealloc
object_dispose
objc_destructInstance、free
void *objc_destructInstance(id obj) 
{
    if (obj) {
        // Read all of the flags at once for performance.
        bool cxx = obj->hasCxxDtor();
        bool assoc = obj->hasAssociatedObjects();

        // This order is important.
        if (cxx) object_cxxDestruct(obj);//清除成员变量
        if (assoc) _object_remove_assocations(obj);
        obj->clearDeallocating();//将指向当前对象的弱指针制为nil
    }

    return obj;
}

9、自动释放池

class AutoreleasePoolPage 
{
    magic_t const magic;
    id *next;
    pthread_t const thread;
    AutoreleasePoolPage * const parent;
    AutoreleasePoolPage *child;
    uint32_t const depth;
    uint32_t hiwat;
};
AutoreleasePoolPage的结构.jpg

10、Runloop和Autorelease关系

iOS在主线程的Runloop中注册了2个Observer

上一篇 下一篇

猜你喜欢

热点阅读