目录
- 1、block的本质
- 2、可变集合类 和 不可变集合类的 copy 和 mutablecopy有什么区别?如果是集合是内容复制的话,集合里面的元素也是内容复制么?
- 3、关于nonatomic和atomic
- 4、objc在向一个对象发送消息时,发生了什么?
- 5、能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么?
- 6 为什么把NSTimer对象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主运行循环以后,滑动scrollview的时候NSTimer却不动了?
- 7 有没有用过运行时,用它都能做什么?
- 8、frame和bounds有什么不同,如果修改其中的值,会有什么变化?
- 9、load和initialize的区别
- 10、怎么交换两个变量的值?不用临时变量呢?
- 11、简单介绍一下KVC和KVO,他们都可以应用在哪些场景?
- 12、浅复制和深复制的区别
- 13、__block和__weak修饰符的区别是什么?
- 14、a,b任务并发执行,然后执行c任务怎么做,有哪些方法实现
- 15、objc_msgSend(消息传递)
- 16、这个写法会出什么问题:@property (nonatomic, copy) NSMutableArray *arr
- 17、KVC的底层实现
- 18、KVO
- 19、下面的代码输出什么?(关于self和super)
- 20、isKindOfClass、isMemberOfClass、selector作用分别是什么
- 21、如根据若干个url异步加载多张图片,然后在都下载完成后合成一张整图(如何用GCD同步若干个异步调用)
- 22、以下代码运行结果如何?(多线程死锁)
- 23、谈谈 UITableView 的优化
- 24、如何实行cell的动态的行高
- 25、runtime中,SEL、Method 和 IMP有什么区别,使用场景?
- 26、常见的内存泄漏有哪些情况?如何排查和避免?
- 27、struct和class的区别
- 28、self和super的区别
- 29、id 和 instanceType 有什么区别?
- 30、nil、NIL、NSNULL 有什么区别?
- 31、Category 的实现原理?
- 32、如何优化 ‘APP’ 的电量?
- 33、说一下调用方法在runtime时是怎么样的?([obj makeText])
- 34、layoutSubviews方法什么时候调用?
- 35、定义一个NSString类型属性时,为什么用copy不用strong?
- 36、子视图超出父视图的部分能看到么?超出的部分有什么影响?
- 37、一个objc对象如何进行内存布局?(考虑有父类的情况)
- 38、SDWebImage缓存机制
- 39、property相关面试题
- 40、OC 如何实现多重继承?
- 41、runtime 如何实现 weak 属性
- 42、iOS的消息机制和消息转发
最近开始找工作,日常记录一些遇到的面试题,可能会有重复发,持续更新、修改,如果那里不对、不准确,欢迎留言,共同进步
1、block的本质
1.1 block的本质
block的本质就是一个object-c对象。
block:存储位置,可能分为3个地方:代码去,堆区、栈区(ARC情况下会自动拷贝到堆区,因此ARC下只能有两个地方:代码去、堆区)
代码区:不访问栈区的变量(如局部变量),且不访问堆区的变量(alloc创建的对象),此时block存放在代码去。
堆区:访问了处于栈区的变量,或者堆区的变量,此时block存放在堆区。–需要注意实际是放在栈区,在ARC情况下会自动拷贝到堆区,如果不是ARC则存放在栈区,所在函数执行完毕就回释放,想再外面调用需要用copy指向它,这样就拷贝到了堆区,strong属性不会拷贝、会造成野指针错区。
1.2 为什么在默认情况下无法修改被block捕获的变量? __block都做了什么?
默认情况下,block里面的变量,拷贝进去的是变量的值,而不是指向变量的内存的指针。
当使用__block修饰后的变量,拷贝到block里面的就是指向变量的指针,所以我们就可以修改变量的值。
1.3 block反向传值
在前一个控制器的touchesBegan:方法内实现如下代码。
// OneViewController.m
TwoViewController *twoVC = [[TwoViewController alloc] init];
twoVC.valueBlcok = ^(NSString *str) {
NSLog(@"OneViewController拿到值:%@", str);
};
[self presentViewController:twoVC animated:YES completion:nil];
// TwoViewController.h (在.h文件中声明一个block属性)
@property (nonatomic ,strong) void(^valueBlcok)(NSString *str);
// TwoViewController.m (在.m文件中实现方法)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// 传值:调用block
if (_valueBlcok) {
_valueBlcok(@"123456");
}
}
2、可变集合类 和 不可变集合类的 copy 和 mutablecopy有什么区别?如果是集合是内容复制的话,集合里面的元素也是内容复制么?
可变集合类使用copy表示深拷贝,不可变集合类使用copy的时候是浅拷贝。
可变集合类、不可边类型使用mutablecopy表示深拷贝
当是浅拷贝的时候,容器的内容是没有复制的。如果是深拷贝的话,容器的内容都会收到一条copy消息,拷贝出新的内容,从新组成新的容器返回。
3、关于nonatomic和atomic
3.1 区别
nonatomic:表示非原子,不安全,但是效率高。
atomic:表示原子行,安全,但是效率低。
nonatomic的内存管理语义是非原子性的,非原子性的操作本来就是线程不安全的,而atomic的操作是原子性的,但是并不意味着它是线程安全的,它会增加正确的几率,能够更好的避免线程的错误,但是它仍然是线程不安全的。
3.2 atomic是绝对的线程安全么?为什么?
当使用nonatomic的时候,属性的setter,getter操作是非原子性的,所以当多个线程同时对某一属性读和写操作时,属性的最终结果是不能预测的。
当使用atomic时,虽然对属性的读和写是原子性的,但是仍然可能出现线程错误:当线程A进行写操作,这时其他线程的读或者写操作会因为该操作而等待。当A线程的写操作结束后,B线程进行写操作,然后当A线程需要读操作时,却获得了在B线程中的值,这就破坏了线程安全,如果有线程C在A线程读操作前release了该属性,那么还会导致程序崩溃。所以仅仅使用atomic并不会使得线程安全,我们还要为线程添加lock来确保线程的安全。
也就是要注意:atomic所说的线程安全只是保证了getter和setter存取方法的线程安全,并不能保证整个对象是线程安全的。如下列所示:
比如:@property(atomic,strong)NSMutableArray *arr;
如果一个线程循环的读数据,一个线程循环写数据,那么肯定会产生内存问题,因为这和setter、getter没有关系。如使用[self.arr objectAtIndex:index]就不是线程安全的。
据说,atomic要比nonatomic慢大约20倍
3.3 如果不是,那应该如何实现?
好的解决方案就是加锁
具体请见保证线程安全的方式
4、objc在向一个对象发送消息时,发生了什么?
根据对象的isa指针找到类对象id,在查询类对象里面的methodLists方法函数列表,如果没有在好到,在沿着superClass,寻找父类,再在父类methodLists方法列表里面查询,最终找到SEL,根据id和SEL确认IMP(指针函数),在发送消息;
5、能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么?
1.不能向编译后得到的类增加实例变量
编译后的类已经注册在runtime中,类结构体中的objc_ivar_list实例变量的链表和instance_size实例变量的内存大小已经确定,runtime会调用class_setvarlayout或class_setWeaklvarLayout来处理strong weak引用.所以不能向存在的类中添加实例变量
2.能向运行时创建的类中添加实例变量
运行时创建的类是可以添加实例变量,调用class_addIvar函数.但是的在调用objc_allocateClassPair之后,objc_registerClassPair之前,原因同上.
6 为什么把NSTimer对象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主运行循环以后,滑动scrollview的时候NSTimer却不动了?
nstime对象是在 NSDefaultRunLoopMode下面调用消息的,但是当我们滑动scrollview的时候,NSDefaultRunLoopMode模式就自动切换到UITrackingRunLoopMode模式下面,却不可以继续响应nstime发送的消息。所以如果想在滑动scrollview的情况下面还调用nstime的消息,我们可以把nsrunloop的模式更改为NSRunLoopCommonModes
7 有没有用过运行时,用它都能做什么?
7.1 交换方式
一般写在类的+(void)load方法里面
/** 获取原始setBackgroundColor方法 */
Method originalM = class_getInstanceMethod([self class], @selector(setBackgroundColor:));
/** 获取自定义的pb_setBackgroundColor方法 */
Method exchangeM = class_getInstanceMethod([self class], @selector(pb_setBackgroundColor:));
/** 交换方法 */
method_exchangeImplementations(originalM, exchangeM);
7.2 创建类
Class MyClass = objc_allocateClassPair([NSObject class], "Person", 0);
7.3 添加方法
/**参数一、类名参数
二、SEL 添加的方法名字参数
三、IMP指针 (IMP就是Implementation的缩写,它是指向一个方法实现的指针,每一个方法都有一个对应的IMP)
参数四、其中types参数为"i@:@“,按顺序分别表示:具体类型可参照[官方文档](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html)i 返回值类型int,若是v则表示void@ 参数id(self): SEL(_cmd)@ id(str)
V@:表示返回值是void 带有SEL参数 (An object (whether statically typed or typed id))
*/
class_addMethod(Person, @selector(addMethodForMyClass:), (IMP)addMethodForMyClass, "V@:");
7.4 添加实例变量
/**参数一、类名参数
二、属性名称参数
三、开辟字节长度参数
四、对其方式参数
五、参数类型 “@” 官方解释 An object (whether statically typed or typed id) (对象 静态类型或者id类型) 具体类型可参照[官方文档](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html)return: BOOL 是否添加成功
*/
BOOL isSuccess = class_addIvar(Person, "name", sizeof(NSString *), 0, "@");
isSuccess?NSLog(@"添加变量成功"):NSLog