docs: 汇编研究

This commit is contained in:
LiuBinPeng
2022-06-23 14:59:47 +08:00
parent 55d66cc4c5
commit f0e20eaf2e
30 changed files with 1042 additions and 347 deletions

View File

@@ -46,8 +46,6 @@ NSTimer、CADisplayLink 的 基础 API `[NSTimer scheduledTimersWithTimeInterval
1. 控制器不再强引用定时器
2. 定时器不再保留当前的控制器
## 解决方案:
### 替换 NSTimer API
@@ -84,14 +82,10 @@ dispatch_resume(timerSource);
self.timer = timerSource;
```
为什么 GCD timer 会更准确?因为普通定时器运行依赖 RunLoopRunLoop 一个运行周期内的任务繁忙程度是不确定的。当某次任务繁重,那么定时器调度就不准时。
GCD timer 不依赖 RunLoop系统底层驱动所以会更加准确。因为和 RunLoop 无关,所以和 UI 滚动RunLoop mode 切换到 UITrackingMode 也不影响 GCD timer。
### 打破循环引用NSTimer target 自定义
```objectivec
@@ -158,45 +152,45 @@ dispatch_semaphore_t semaphore_;
+ (NSString *)execTask:(void (^)(void))task start:(NSTimeInterval)start interval:(NSTimeInterval)interval repeats:(BOOL)repeats async:(BOOL)async
{
if (!task || start < 0 || (interval <= 0 && repeats)) return nil;
// 队列
dispatch_queue_t queue = async ? dispatch_get_global_queue(0, 0) : dispatch_get_main_queue();
// 创建定时器
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
// 设置时间
dispatch_source_set_timer(timer,
dispatch_time(DISPATCH_TIME_NOW, start * NSEC_PER_SEC),
interval * NSEC_PER_SEC, 0);
dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
// 定时器的唯一标识
NSString *name = [NSString stringWithFormat:@"%zd", timers_.count];
// 存放到字典中
timers_[name] = timer;
dispatch_semaphore_signal(semaphore_);
// 设置回调
dispatch_source_set_event_handler(timer, ^{
task();
if (!repeats) { // 不重复的任务
[self cancelTask:name];
}
});
// 启动定时器
dispatch_resume(timer);
return name;
}
+ (NSString *)execTask:(id)target selector:(SEL)selector start:(NSTimeInterval)start interval:(NSTimeInterval)interval repeats:(BOOL)repeats async:(BOOL)async
{
if (!target || !selector) return nil;
return [self execTask:^{
if ([target respondsToSelector:selector]) {
#pragma clang diagnostic push
@@ -210,9 +204,9 @@ dispatch_semaphore_t semaphore_;
+ (void)cancelTask:(NSString *)name
{
if (name.length == 0) return;
dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
dispatch_source_t timer = timers_[name];
if (timer) {
dispatch_source_cancel(timer);
@@ -245,8 +239,6 @@ dispatch_semaphore_t semaphore_;
![](https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/ignoreXcodewarning.png)
### NSProxy
```objectivec
@@ -276,8 +268,6 @@ QA: 自己写的继承自 NSObject 的代理对象和继承自 NSProxy 的代理
NSProxy 效率更高。继承自 NSObject 的代理内部运行的时候还是存在方法查找isa、superclass、cache、methods流程。
看一段神奇的代码
`LBPProxy`
@@ -297,7 +287,6 @@ NSProxy 效率更高。继承自 NSObject 的代理,内部运行的时候还
return self.target;
}
@end
```
`LBPProxy2`
@@ -352,9 +341,9 @@ appDelegateClassName = NSStringFromClass([AppDelegate class]);
```objectivec
- (BOOL) isKindOfClass: (Class)aClass
{
NSMethodSignature *sig;
NSInvocation *inv;
BOOL ret;
NSMethodSignature *sig;
NSInvocation *inv;
BOOL ret;
sig = [self methodSignatureForSelector: _cmd];
inv = [NSInvocation invocationWithMethodSignature: sig];
[inv setSelector: _cmd];
@@ -367,8 +356,6 @@ appDelegateClassName = NSStringFromClass([AppDelegate class]);
可以看到内部直接调用了消息转发。
### 采用 Block 的形式为 NSTimer 增加分类
```objectivec
@@ -487,4 +474,8 @@ __strong __typeof(&*weakSelf)self = weakSelf;
}
```
iOS 10 中,定时器 api 增加了 block 方法,实现原理与此类似,这里采用分类为 NSTimer 增加 block 参数的方法,最终的行为一致
iOS 10 中,定时器 api 增加了 block 方法,实现原理与此类似,这里采用分类为 NSTimer 增加 block 参数的方法,最终的行为一致
## 检测
根据 Instrucments 提供的工具的工作原理,写一个野指针探针工具去发现并定位问题。具体见[野指针监控工具](./1.74.md#zombieSniffer)