1、runtime如何通过selector找到对应的IMP地址?(分别考虑类方法和实例方法)
答:每一个类对象都有一个方法列表,方法列表中记录着方法的名称,方法实现,以及参数类型,其实selector本质就是方法名称,通过方法名称就可以在方法列表中找到对应的方法实现 详解请见 http://blog.csdn.net/dp948080952/article/details/52437451
2、使用runtime Associate方法关联的对象,需要在主对象dealloc的时候释放么?
答:不需要。
3、objc中的类方法和实例方法有什么本质区别和联系?
类方法:
类方法是属于类对象的
类方法只能通过类对象调用
类方法中的self是类对象
类方法可以调用其他的类方法
类方法中不能访问成员变量
类方法中不定直接调用对象方法
实例方法:
实例方法是属于实例对象的
实例方法只能通过实例对象调用
实例方法中的self是实例对象
实例方法中可以访问成员变量
实例方法中直接调用实例方法
实例方法中也可以调用类方法(通过类名)
4、_objc_msgForward函数是做什么的,直接调用它将会发生什么?
答:_objc_msgForward是 IMP 类型,用于消息转发的:当向一个对象发送一条消息,但它并没有实现的时候,_objc_msgForward会尝试做消息转发。
直接调用_objc_msgForward是非常危险的事,如果用不好会直接导致程序Crash
一旦调用_objc_msgForward,将跳过查找 IMP 的过程,直接触发“消息转发”,如果调用了_objc_msgForward,即使这个对象确实已经实现了这个方法,你也会告诉objc_msgSend:“我没有在这个对象里找到这个方法的实现”
5、runtime如何实现weak变量的自动置nil?
答:runtime 对注册的类, 会进行布局,对于 weak 对象会放入一个 hash 表中。 用 weak 指向的对象内存地址作为 key,当此对象的引用计数为0的时候会 dealloc,假如 weak 指向的对象内存地址是a,那么就会以a为键, 在这个 weak 表中搜索,找到所有以a为键的 weak 对象,从而设置为 nil。
6、能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么?
答:不能向编译后得到的类增加实例变量
能向运行时创建的类中添加实例变量
解释:
编译后的类已经注册在runtime中,类结构体中的objc_ivar_list实例变量的链表和instance_size实例变量的内存大小已经确定,runtime会调用class_setvarlayout或class_setWeaklvarLayout来处理strong weak引用.所以不能向存在的类中添加实例变量
2.运行时创建的类是可以添加实例变量,调用class_addIvar函数.但是的在调用objc_allocateClassPair之后,objc_registerClassPair之前,原因同上.
7、runloop和线程有什么关系?
答: RunLoop的作用就是来管理线程的,当线程的RunLoop开启后,线程就会在执行完任务后,处于休眠状态,随时等待接受新的任务,而不是退出。
8、runloop的mode作用是什么?
答:model 主要是用来指定事件在运行循环中的优先级的,分为:
NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默认,空闲状态
UITrackingRunLoopMode:ScrollView滑动时
UIInitializationRunLoopMode:启动时
NSRunLoopCommonModes(kCFRunLoopCommonModes):Mode集合
苹果公开提供的 Mode 有两个:
NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
NSRunLoopCommonModes(kCFRunLoopCommonModes)
9、以+ scheduledTimerWithTimeInterval...的方式触发的timer,在滑动页面上的列表时,timer会暂定回调
RunLoop只能运行在一种mode下,如果要换mode,当前的loop也需要停下重启成新的。利用这个机制,ScrollView滚动过程中NSDefaultRunLoopMode(kCFRunLoopDefaultMode)的mode会切换到UITrackingRunLoopMode来保证ScrollView的流畅滑动:只能在NSDefaultRunLoopMode模式下处理的事件会影响scrllView的滑动。
如果我们把一个NSTimer对象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主运行循环中的时候, ScrollView滚动过程中会因为mode的切换,而导致NSTimer将不再被调度。
同时因为mode还是可定制的,所以:
Timer计时会被scrollView的滑动影响的问题可以通过将timer添加到NSRunLoopCommonModes(kCFRunLoopCommonModes)来解决。
或者通过在创建一个线程来运行,避免mode切换来解决。
10、猜想runloop内部是如何实现的?
答:内部就是do-while循环,在这个循环内部不断地处理各种事件(任务),比如:Source、Timer、Observer;
每条线程都有唯一一个RunLoop对象与之对应,主线程的RunLoop默认已经启动
子线程的RunLoop需要手动启动;
每次RunLoop启动时,只能指定其中一个Mode,这个Mode被称作CurrentMode,
如果需要切换Mode,只能退出Loop,再重新指定一个Mode进入,这样做主要是为了隔离不同Mode中的Source、Timer、Observer,让其互不影响
11、objc使用什么机制管理对象内存?
答:通过 retainCount 的机制来决定对象是否需要释放。每次 runloop 的时候,都会检查对象的 retainCount,如果retainCount 为 0,说明该对象没有地方需要继续使用了,可以释放掉了
12、ARC通过什么方式帮助开发者管理内存?
答:ARC相对于MRC,不是在编译时添加retain/release/autorelease这么简单。应该是编译期和运行期两部分共同帮助开发者管理内存。
在编译期,ARC用的是更底层的C接口实现的retain/release/autorelease,这样做性能更好,也是为什么不能在ARC环境下手动retain/release/autorelease,同时对同一上下文的同一对象的成对retain/release操作进行优化(即忽略掉不必要的操作);
ARC也包含运行期组件,这个地方做的优化比较复杂,但也不能被忽略。
13、不手动指定autoreleasepool的前提下,一个autorealese对象在什么时刻释放?(比如在一个vc的viewDidLoad中创建)
14、不手动指定autoreleasepool的前提下,一个autorealese对象在什么时刻释放?(比如在一个vc的viewDidLoad中创建)
答:分两种情况:手动干预释放时机、系统自动去释放。
手动干预释放时机 - 指定autoreleasepool就是所谓的:当前作用域大括号结束时释放。
系统自动去释放 - 不手动指定autoreleasepool
Autorelease对象出了作用域之后,会被添加到最近一次创建的自动释放池中,并会在当前的 runloop 迭代结束时释放。
如果在一个vc的viewDidLoad中创建一个 Autorelease对象,那么该对象会在 viewDidAppear 方法执行前就被销毁了。
15、BAD_ACCESS在什么情况下出现?
答:访问了野指针,比如对一个已经释放的对象执行了release、访问已经释放对象的成员变量或者发消息。
死循环
16、苹果是如何实现autoreleasepool的?
答:autorelease类似于C语言中Automatic variable自动变量,程序执行时,若某自动变量超出其作用域,该自动变量将被自动废弃。 参考:http://www.jianshu.com/p/cc3ee2909457