一句话笔记,某段时间内遇到或看到的某个可记录的点。
- 1、自动释放词的理解
- 2、怎样实现一个精确的 NSTimer ?
- 3、如何防止拦截潜在的崩溃?
一、自动释放词的理解
可以先想想自动释放词的理解和印象
- 概念
AutoreleasePool
(自动释放池)是OC中的一种内存自动回收机制,它可以延迟加入AutoreleasePool
中的变量release
的时机。在正常情况下,创建的变量会在超出其作用域的时候release
,但是如果将变量加入AutoreleasePool
,那么release
将延迟执行。 -
AtAutoreleasePool
和AutoreleasePoolPage
AtAutoreleasePool 调用函数
-
每执行
@autoreleasepool
底层对应执行objc_autoreleasePoolPush()
; 就会往AutoreleasePoolPage
添加POOL_BOUNDARY
,并返回POOL_BOUNDARY
所在AutoreleasePoolPage
的内存空间地址 -
@autoreleasepool{}
大括号结束 内部创建的__AtAutoreleasePool
对象销毁,调用析构函数objc_autoreleasePoolPop(atautoreleasepoolobj)
; -
AutoreleasePoolPage
开始从后往前遍历autorelease
对象调用release
方法直到objc_autoreleasePoolPop()
传入的POOL_BOUNDARY
地址为止 -
自动释放池在mrc和arc区别:
- ARC下除了NSAutoreleasePool不可用以外,其他相同
- Autorelease对象什么时候释放?
在没有手加Autorelease Pool
的情况下,Autorelease
对象是在当前的runloop
迭代结束时释放的,而它能够释放的原因是系统在每个runloop
迭代中都加入了自动释放池Push
和Pop
iOS程序运行 在主线程中注册了2个Observer 分别监听RunLoop
第一个Observer监听了kCFRunLoopEntry 会调用objc_autoreleasePoolPush
第二个Observer监听了kCFRunLoopBeforeWaiting 会调用objc_autoreleasePoolPop
笔记来源: iOS进阶四-自动释放池原理,iOS 自动释放池ARC与MRC
二、怎样实现一个精确的NSTimer?
2.1不准的原因如下:
-
NSTimer 加在
main Runloop
中,模式是NSDefaultRunLoopMode
,main
负责所有主线程事件,例如UI界面的操作,复杂的运算,这样在同一个Runloop
中timer
就会产生阻塞。 -
模式的可能改变。主线程的 RunLoop 里有两个预置的 Mode:kCFRunLoopDefaultMode 和 UITrackingRunLoopMode, 切换时需要退出和进入可能导致时间的不准。
2.2 解决的方案:
- 子线程中创建 NSTimer, 在子线程中进行定时任务的操作,需要UI操作时切换回主线程进行操作 。
- 对于模式的影响,直接将 NSTimer 的 mode 更换成
NSRunLoopCommonModes
。 - 转换用 GCD 的计时器,dispatch_source_t。
三、 如何防止拦截潜在的崩溃
1、利用 Runtime
方法交换技术,将系统方法替换成类添加的新方法。
- 类似 消息转发中,可能出现的问题,进行交换
- 类似数组越界的判断
- 类似字典,字符串 为空的
具体可以看 NSObjectSafe 的处理,其中一个如下
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
swizzleInstanceMethod([NSObject class], @selector(addObserver:forKeyPath:options:context:), @selector(hookAddObserver:forKeyPath:options:context:));
swizzleInstanceMethod([NSObject class], @selector(removeObserver:forKeyPath:), @selector(hookRemoveObserver:forKeyPath:));
swizzleInstanceMethod([NSObject class], @selector(methodSignatureForSelector:), @selector(hookMethodSignatureForSelector:));
swizzleInstanceMethod([NSObject class], @selector(forwardInvocation:), @selector(hookForwardInvocation:));
});
}
2、利用异常的捕获来防止程序的崩溃,并且进行相应的处理。
@try {
// 可能会出现崩溃的代码
}
@catch (NSException *exception) {
// 捕获到的异常exception
}
@finally {
// 结果处理
}
网友评论