精选面试题教你应对高级 iOS 开发面试官(提供底层进阶规划蓝图)
Runloop 和线程的关系
1.—一对应,主线程的 runloop 已经创建,子线程的必须手动创建 2.runloop 在第一次获取时创建,在线程结束时销毁//在 runloop 中有多个运行模式,但是只能选择一种模式运行,mode 中至少要有一个 timer 或者是 sourceMode:系统默认注册 5 个 Mode:kCFRunLoopDefaultMode:App 默认 mode,通常主线程在这个 mode 下运行 UITrackingRunLoopMode:界面跟踪 mode,用于 Scrollview 追踪触摸滑动,保证滑动时不受其他 mode 影响 kCFRunLoopCommonModes:占位用的 mode,不是一个真正的 modeNSRunLoopCommonModes 相当于 NSDefaultRunLoopMode + UITrackingRunLoopModeUIInitializationRunLoopModeUITrackingRunLoopModeUIInitializationRunLoopMode:刚启动 App 时进入的第一个 mode,启动完成之后不再使用 GSEventReceiveRunLoopMode:接受系统事件的内部 mode,通常用不到
自动释放池什么时候释放?
//第一次创建︰启动 runloop 时候//最后一次销毁:runloop 退出的时候//其他时候的创建和销毁:当 runloop 即将睡眠时销毁之前的释放池,重新创建一个新的
什么情况下使用 weak 关键字,和 assign 的区别?
1、ARC 中,有可能出现循环引用的地方使用,比如:delegate 属性 2、自定义 IBOutlet 控件属性一般也是使用 weak 区别: weak 表明一种非持有关系,必须用于 OC 对象;assign 用于基本数据类型
怎么用 copy 关键字?
1、NSString、NSArray、NSDictionary 等等经常使用 copy 关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary;他们之间可能进行赋值操作,为确保对象中的字符串值不会无意间变动,应该在设置新属性值时拷贝一份。2、block 也使用 copy
*@property (copy)NSMutableArray array;这写法会出什么问题?
1、添加,删除,修改数组内的元素的时候,程序会因为找不到对应的方法而崩溃,因为 copy 就是复制一个不可变 NSArray 的对象;2、使用了 atomic 属性会严重影响性能﹔
如何让自己的类用 copy 修饰符?即让自己写的对象具备拷贝功能
具体步骤:1、需声明该类遵从 NSCopying 或 NSMutableCopying 协议 2、实现 NSCopying 协议。该协议只有一个方法:-(id)copywithzone : (NSzone *)zone;
@property 的本质是什么? ivar、getter、setter 如何生成并添加到这个类中的
本质:@property = ivar + getter + setter;(实例变量+getter 方法+setter 方法)在编译期自动生成 getter、setter,还自动向类中添加适当类型的实例变量,也可以用 synthesize 语法来指定实例变量的名字
@protocol 和 category 中如何使用 @property?
1、在 protocol 中使用 property 只会生成 setter 和 getter 方法声明,使用属性的目的,是希望遵守该协议的对象能实现该属性 2、category 使用 @property 也是只会生成 setter 和 getter 方法声明,如果真的需要给 category 增加属性的实现,需要借助于运行时的两个函数︰objc_setAssociatedObjectobjc _getAssociatedobject
@property 中有哪些属性关键字?
1、原子性—- nonatomic 特质 2、读/写权限 readwrite(读写)、readonly(只读)3、内存管理语义— assign、strong、weak、unsafe_unretained、copy4、方法名一 getter=< name > . setter=< name >
weak 属性需要在 dealloc 中置 nil 么?
不需要,在 ARC 环境无论是强指针还是弱指针都无需在 dealloc 设置为 nil,ARC 会自动帮我们处理,即便是编译器不帮我们做这些,weak 也不需要在 dealloc 中置 nil,runtime 内部已经帮我们实现了
@synthesize 和 @dynamic 分别有什么作用?
1、@property 有两个对应的词,一个是 @synthesize,一个是 @dynamic。如果 @synthesize 和 @dynamic 都没写,那么默认的就是 @syntheszie var = _var;2、@synthesize 的语义是如果你没有手动实现 setter 方法和 getter 方法,那么编译器会自动为你加上这两个方法 3、@dynamic 告诉编译器∶属性的 setter 与 getter 方法由用户自己实现,不自动生成。(当然对于 readonly 的属性只需提供 getter 即可)。假如一个属性被声明为 dynamic var,然后你没有提供 @setter 方法和 @getter 方法,编译的时候没问题,但是当程序运行到 instance.var = someVar,由于缺 setter 方法会导致程序崩溃;或者当运行到 someVar = var 时,由于缺 getter 方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。
@synthesize 合成实例变量的规则是什么?假如 property 名为 foo,存在一个名为_foo 的实例变量,那么还会自动合成新变量么?
@synthesize 合成实例变量的规则,有以下几点:
如果指定了成员变量的名称,会生成一个指定的名称的成员变量,
如果这个成员已经存在了就不再生成了.
如果是 @synthesize foo;还会生成一个名称为 foo 的成员变量,也就是说:如果没有指定成员变量的名> 称会自动生成一个属性同名的成员变量,
如果是 @synthesize foo = _foo;就不会生成成员变量了.假如 property 名为 foo,存在一个名为_foo 的实例变量,那么还会自动合成新变量么?不会。
在有了自动合成属性实例变量之后,@synthesize 还有哪些使用场景?
同时重写了 setter 和 getter 时,系统就不会生成 ivar,使用 @synthesize foo =_foo;关联 @property 与 ivar
重写了只读属性的 getter 时
使用了 @dynamic 时
在 @protocol 中定义的所有属性
在 category 中定义的所有属性
重载的属性,当在子类中重载了父类中的属性,必须使用 @synthesize 来手动合成 ivar
objc 中向一个 nil 对象发送消息将会发生什么?
在 objective-C 中向 nil 发送消息是完全有效的—只是在运行时不会有任何作用如果一个方法返回值是一个对象,那么发送给 nil 的消息将返回 o(nil),如果向一个 nil 对象发送消息,首先在寻找对象的 isa 指针时就是 o 地址返回了,所以不会出现任何错误。
objc 中向一个对象发送消息[obj foo]和 objc_msgSend()函数之间有什么关系?
[obj foo];在 objc 动态编译时,每个方法在运行时会被动态转为消息发送,即为:objc_msgSend(obj,@selector(foo) ) ;
runtime 如何通过 selector 找到对应的 IMP 地址?(分别考虑类方法和实例方法)
每一个类对象中都一个方法列表,方法列表中记录着方法名称、方法实现、参数类型,其实 selector 本质就是方法名称,通过这个方法名称就可以在方法列表中找到对应的方法实现.
题库资料已上传到 Gitee iOS工程师飞升秘籍,欢迎大家来访。✍ 万水千山总是情,点赞收藏行不行,还望各位大侠多多支持❤️
使用 runtime Associate 方法关联的对象,需要在主对象 dealloc 的时候释放么?
无论在 MRC 下还是 ARc 下均不需要。//对象的内存销毁时间表 1.调用-release :引用计数变为零
对象正在被销毁,生命周期即将结束.
不能再有新的_weak 弱引用,否则将指向 nil.*调用[ self dealloc]
2.子类调用-dealloc
继承关系中最底层的子类在调用-dealloc
如果是 MRC 代码则会手动释放实例变量们(ivars)*继承关系中每一层的父类都在调用-dealloc
3.NSobject 调用-dealloc
只做一件事:调用 objective-C runtime 中的 object_dispose()方法 4.调用 object_dispose()
为 C++的实例变量们(ivars)调用 destructors
为 ARC 状态下的实例变量们(ivars)调用-release*解除所有使用 runtime Associate 方法关联的对象
解除所有_weak 引用
调用 free()
objc 中的类方法和实例方法有什么本质区别和联系?
类方法:
类方法是属于类对象的
类方法只能通过类对象调用
类方法中的 self 是类对象
类方法可以调用其他的类方法
类方法中不能访问成员变量
类方法中不能直接调用对象方法
实例方法:
实例方法是属于实例对象的
实例方法只能通过实例对象调用
实例方法中的 self 是实例对象实例方法中可以访问成员变量
实例方法中直接调用实例方法
实例方法中也可以调用类方法(通过类名)方法
runloop 和线程有什么关系?
实际上,run loop 和线程是紧密相连的,可以这样说 run loop 是为了线程而生,没有线程,它就没有存在的必要。Run loops 是线程的基础架构部分,Cocoa 和 CoreFundation 都提供了 runloop 对象方便配置和管理线程的 run loop(以下都以 cocoa 为例)。每个线程,包括程序的主线程( main thread )都有与之相应的 run loop 对象。
runloop 和线程的关系∶主线程的 run loop 默认是启动的。ios 的应用程序里面,程序启动后会有一个如下的 main()函数
重点是 UIApplicationMain()函数,这个方法会为 main thread 设置一个 NSRunLoop 对象,这就解释了∶
为什么我们的应用可以在无人操作的时候休息,需要让它干活的时候又能立马响应。
对其它线程来说,run loop 默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动,如果线程只是去执行一个长时间的已确定的任务则不需要。
在任何一个 Cocoa 程序的线程中,都可以通过以下代码来获取到当前线程的 run loop 。
runloop 的 mode 作用是什么?
model 主要是用来指定事件在运行循环中的优先级的,分为:
NSDefaultRunLoopMode (kCFRunLoopDefaultMode):默认,空闲状态 UlTrackingRunLoopMode: > - > - ScrollView 滑动时
UlInitializationRunLoopMode:启动时
NSRunLoopCommonModes (kCFRunLoopCommonModes) : Mode 集合
苹果公开提供的 Mode 有两个:
NSDefaultRunLoopMode (kCFRunLoopDefaultMode)
NSRunLoopCommonModes (kCFRunLoopCommonModes)
runloop 内部是如何实现的?
一般来讲,一个线程一次只能执行一个任务,执行完成后线程就会退出。如果我们需要一个机制,让线程能随时处理事件但并不退出,通常的代码逻辑是这样的:
或使用伪代码来展示下:
objc 使用什么机制管理对象内存?
通过 retaincount 的机制来决定对象是否需要释放。每次 runloop 的时候,都会检查对象的 retainCount,如果 retainCount 为 e,说明该对象没有地方需要继续使用了,可以释放掉了。
使用 block 时什么情况会发生引用循环,如何解决?
一个对象中强引用了 block,在 block 中又强引用了该对象,就会发生循环引用。解决方法是将该对象使用_weak 或者_block 修饰符修饰之后再在 block 中使用。
id weak weakSelf = self;或者 weak __typeof(&*self)weakSelf = self 该方法可以设置宏
id _block weakSelf = self;或者将其中一方强制置空 xxx = nil。
GCD 的队列(dispatch_queue_t)分哪两种类型?
串行队列 Serial Dispatch Queue
并行队列 Concurrent Dispatch Queue
如何用 GCD 同步若干个异步调用?(如根据若干个 url 异步加载多张图片,然后在都下载完成后合成一张整图)
使用 Dispatch Group 追加 block 到 Global Group Queue,这些 block 如果全部执行完毕,就会执行 Main Dispatch Queue 中的结束处理的 block。
题库资料已上传到 Gitee iOS工程师飞升秘籍,欢迎大家来访。✍ 万水千山总是情,点赞收藏行不行,还望各位大侠多多支持❤️
原文地址:https://blog.csdn.net/chenzuoY/article/details/116711090
评论