美文网首页iOS 底层学习方向、面试总结
精选面试题教你应对高级iOS开发面试官(提供底层进阶规划蓝图)

精选面试题教你应对高级iOS开发面试官(提供底层进阶规划蓝图)

作者: 编程怪才_凌雨画 | 来源:发表于2021-05-12 21:53 被阅读0次

    Runloop和线程的关系

    1.—一对应,主线程的runloop已经创建,子线程的必须手动创建
    2.runloop在第一次获取时创建,在线程结束时销毁
    //在runloop中有多个运行模式,但是只能选择一种模式运行,mode 中至少要有一个timer或者是source
    Mode:
    系统默认注册5个Mode:
    kCFRunLoopDefaultMode:App默认mode,通常主线程在这个mode下运行
    UITrackingRunLoopMode:界面跟踪mode,用于Scrollview追踪触摸滑动,保证滑动时不受其他 mode 影响

    kCFRunLoopCommonModes:占位用的mode,不是一个真正的mode
    NSRunLoopCommonModes 相当于NSDefaultRunLoopMode + UITrackingRunLoopModeUIInitializationRunLoopMode
    UITrackingRunLoopModeUIInitializationRunLoopMode:刚启动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_setAssociatedObject
    objc _getAssociatedobject

    @property中有哪些属性关键字?

    1、原子性—- nonatomic特质
    2、读/写权限 readwrite(读写)、readonly(只读)
    3、内存管理语义— assign、strong、weak、unsafe_unretained、copy
    4、方法名一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()函数

    int main( int argc,_char * argv[]) {
    autoreleasepool i
    return UIApplicationMain(argc,argv,nil,NSStringFromClass([AppDelegate
    class]));
    
    

    重点是UIApplicationMain()函数,这个方法会为main thread设置一个NSRunLoop对象,这就解释了∶

    • 为什么我们的应用可以在无人操作的时候休息,需要让它干活的时候又能立马响应。
    • 对其它线程来说,run loop默认是没有启动的,如果你需要更多的线程交互则可以手动配置

    和启动,如果线程只是去执行一个长时间的已确定的任务则不需要。

    • 在任何一个Cocoa程序的线程中,都可以通过以下代码来获取到当前线程的 run loop 。
    NSRunLoop *runloop = [ NSRunLoop currentRunLoop];
    

    runloop的mode作用是什么?

    model主要是用来指定事件在运行循环中的优先级的,分为:

    • NSDefaultRunLoopMode (kCFRunLoopDefaultMode):默认,空闲状态UlTrackingRunLoopMode: > - > - ScrollView滑动时
    • UlInitializationRunLoopMode:启动时
    • NSRunLoopCommonModes (kCFRunLoopCommonModes) : Mode集合

    苹果公开提供的Mode有两个:

    • NSDefaultRunLoopMode (kCFRunLoopDefaultMode)
    • NSRunLoopCommonModes (kCFRunLoopCommonModes)

    runloop内部是如何实现的?

    一般来讲,一个线程一次只能执行一个任务,执行完成后线程就会退出。如果我们需要一个机制,让线程能随时处理事件但并不退出,通常的代码逻辑是这样的:

    function loop(){
    initialize();
    do {
        var msg = get_next_msg();
        process_msg(msg);
    }while (msg !=nil);
    }
    
    

    或使用伪代码来展示下:

    
    int main( int argc, char * argv[]) {
    //程序一直运行状态
    while (AppIsRunning) {
    //睡眠状态,等待唤醒事件
    id whowakesMe = sleepForwakingup();//得到唤醒事件
    id event = GetEvent(whowakesMe ) ;//开始处理事件
    HandleEvent(event);
    }
    return 0;
    }
    

    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。

    dispatch_queue_t queue =
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group,queue,^{/*加载图片1 */ });
    dispatch_group_async(group,queue,^{/*加载图片2*/ });
    dispatch_group_async(group,queue,^{/*加载图片3*/ });
    dispatch_group_notify(group,dispatch_get_main_queue(),^{
    /合并图片
    });
    

    题库资料已上传到 Gitee iOS工程师飞升秘籍,欢迎大家来访。
    ✍ 万水千山总是情,点赞收藏行不行,还望各位大侠多多支持❤️

    原文地址:https://blog.csdn.net/chenzuoY/

    相关文章

      网友评论

        本文标题:精选面试题教你应对高级iOS开发面试官(提供底层进阶规划蓝图)

        本文链接:https://www.haomeiwen.com/subject/abszdltx.html