传weakSelf没有用,并不能解决循环引用。这里target是参数传递,所以这里传self和weakself没啥区别,都是传的内存地址。行参默认参数是强指针,所以外面弱没用,weakself赋值给target还是个强指针。nstimer内部应该有个强指针属性,这个强指针属性存储的就是外面传进来的那个内存地址。也就是说nstimer对target产生的是强引用还是弱引用跟外面传进来的变量一点关系都没有
该方法能解决循环引用,原理是nstimer内部强引用着block,block弱引用着self,所以此时nstimer对self就是弱引用的
也可以自己写个中间代理来解决定时器的循环引用
原理图
控制器中的写法 *就算采用中间代理的写法,也需要在控制器的dealloc中调用定时器的invalidate方法把定时器从runloop中移除
代理类中的写法
也可以用中间代理的方式解决CADisplayLink的循环引用问题,就是可以用解决nstimer循环引用的方式去解决CADisplayLink的循环引用
NSProxy跟NSObject都是基类
只要我们去调用nsproxy的某一个方法的话,它就会马上直接去调用它的另一个方法,即
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
也就是说立马进入消息转发,用nsproxy做中间代理类效率高,它是专门用来做消息转发的(前提是它自己和父类没有
现实这个方法,自己有现实自然最好了,就调用自己的方法。所以nsproxy跟nsobject相比少步动态方法解析)
nsproxy找不到方法的时候报的错
nsobject找不到方法的时候报的错
继承自nsproxy
mjproxy1继承自nsobject对象,那mjproxy1就是普通的oc对象,所以iskindofclass就按照普通的oc对象来处理,也就是判断mjproxy1这个类是不是viewcontroller类这种类型或者是viewcontroller的子类.。而mjproxy继承自nsproxy对象,所以proxy1调用iskindofclass方法的时候,实际上经过消息转发,转发给了viewcontroller去调用了,所以打印的是1
这是iskindofclass方法在nsproxy.m中的底层现实
定时器不准时,是因为runloop的每一个循环周期的时间是不固定的,跟每个周期处理的任务多少,耗时有关(runloop每跑一圈后才会去看下时间),gcd的定时器不依赖runloop
gcd创建定时器时传的队列,就是将来定时器要执行任务所在的队列。只要把队列换成自己创建的,定时器要执
行的任务就会自动放到子线程执行。arc环境下,gcd创建的对象,都不需要我们去管理内存
gcd定时器是gcd的,跟runloop一点关系都没有,gcd定时器是直接跟系统内核挂钩的,所以gcd定时器是非常准确的
gcd定时器在方法中执行任务
只要把队列换成自己创建的,定时器要执行的任务就会自动放到子线程执行
网友评论