1.CADisplayLink、NSTimer注意事项
会对target产生强引用,如果target又对它们产生强引用,那么就会引发循环引用
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerTest) userInfo:NULL repeats:YES];
// 第一种写法解除循环引用
__weak typeof(self) weakSelf = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
[weakSelf timerTest];
}];
// 第二种方法
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:[MyProxy proxyWithTargt:self] selector:@selector(timerTest) userInfo:NULL repeats:YES];
}
- (void)timerTest{
NSLog(@"%s", __func__);
}
- (void)dealloc{
[self.timer invalidate];
self.timer = nil;
NSLog(@"%s", __func__);
}
其中MyProxy代码如下
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MyProxy : NSProxy
+ (instancetype)proxyWithTargt:(id)target;
@end
NS_ASSUME_NONNULL_END
===================================
#import "MyProxy.h"
@interface MyProxy()
@property (nonatomic, weak) id target;
@end
@implementation MyProxy
+ (instancetype)proxyWithTargt:(id)target{
MyProxy *proxy = [MyProxy alloc];
proxy.target = target;
return proxy;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel{
return [self.target methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation{
[invocation invokeWithTarget:self.target];
}
@end
另外timer定时器不准受Runloop影响,如果在一个Runloop循环中有耗时操作,就会影响间隔,CADisplayLink调用频率和刷帧频率一致,一般是1秒60次。
最准的定时器还是用gcd.
2.iOS内存布局图
3.@autoreleasepool
底层是 一个叫AutoreleasePoolPage对象来管理的,是一页一页的。数据结构用到了“栈”。一个对象是0x1000的内存空间,即4096字节。所有的AutoreleasePoolPage对象通过双向链表的形式连接在一起
可以通过以下私有函数来查看自动释放池的情况
extern void _objc_autoreleasePoolPrint(void);
我们平常写的的代码为何会自动释放?
可以通过打印
NSLog(@"%@", [NSRunLoop mainRunLoop]);
可以知道如下结果:
iOS在主线程的Runloop中注册了2个Observer 第1个Observer监听了kCFRunLoopEntry事件,会调用objc_autoreleasePoolPush() 第2个Observer 监听了kCFRunLoopBeforeWaiting事件,会调用objc_autoreleasePoolPop()、objc_autoreleasePoolPush() 监听了kCFRunLoopBeforeExit事件,会调用objc_autoreleasePoolPop()
还有一个要点就是ARC环境下,在一个方法内的对象会在方法一结束就释放。因为ARC自动在末尾插入了release方法。
4.copy和mutableCopy
其实记住一个原理就是拷贝的目的:就是为了产生一个副本,并且不影响原来的对象。
所以会产生一些深浅拷贝的理论。
自定义的对象想要copy,需要遵守NSCopying协议。
5.引用计数的存储
在64bit中,引用计数可以直接存储在优化过的isa指针中,也可能存储在SideTable类中
refcnts是一个存放着对象引用计数的散列表
dealloc