mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-25 04:17:17 +00:00
docs: 汇编研究
This commit is contained in:
@@ -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 会更准确?因为普通定时器运行依赖 RunLoop,RunLoop 一个运行周期内的任务繁忙程度是不确定的。当某次任务繁重,那么定时器调度就不准时。
|
||||
|
||||
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_;
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### 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)
|
||||
Reference in New Issue
Block a user