Objective-C 高频面试题及详细答案(实战版)_第1页
Objective-C 高频面试题及详细答案(实战版)_第2页
Objective-C 高频面试题及详细答案(实战版)_第3页
Objective-C 高频面试题及详细答案(实战版)_第4页
Objective-C 高频面试题及详细答案(实战版)_第5页
已阅读5页,还剩4页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Objective-C高频面试题及详细答案(实战版)一、OC基础语法核心面试题1、简述Objective-C的语言特性,以及和C语言的区别?答案:Objective-C是基于C语言扩展的面向对象编程语言,保留了C语言所有语法特性,同时新增了面向对象、消息机制、动态运行时等核心能力,是iOS、macOS开发的原生语言。核心特性:动态性:依托Runtime机制,方法调用、属性访问、类的绑定都在运行时完成,而非编译时面向对象:具备封装、继承、多态三大特性,仅支持单继承,可通过协议实现多继承效果消息传递机制:OC调用方法本质是发送消息,而非函数调用兼容C语言:可直接嵌入C、C++代码,底层性能损耗极低和C语言核心区别:C是面向过程的静态语言,编译时确定函数调用;OC是面向对象的动态语言,运行时确定方法实现C无对象、类、协议等概念;OC完整支持面向对象全套特性C内存需要手动精细化管理;OC在ARC下自动管理对象内存,MRC下手动引用计数管理2、@property的本质是什么?修饰符有哪些、各自作用?答案:@property是编译器指令,本质是自动生成成员变量、getter方法、setter方法,简化代码开发,不会直接生成私有成员变量,默认生成带下划线的私有成员。核心修饰符及作用:(1)内存语义修饰符(核心)strong:强引用,默认修饰对象类型。持有对象引用,只要有强引用指向对象,对象就不会被释放,适用于所有OC对象。weak:弱引用,不持有对象引用,不会增加引用计数。对象销毁后,指针自动置空,主要用于解决循环引用(代理、block、控件引用)。copy:拷贝修饰,赋值时会拷贝对象副本,新对象和原对象内存独立。主要用于NSString、NSArray等不可变对象,防止可变对象赋值后篡改原数据。assign:直接赋值,不做内存管理,默认修饰基本数据类型(int、float)、枚举、结构体。修饰对象会产生野指针,对象销毁后指针不会置空。retain:MRC专用,作用等同于strong,ARC下废弃不用。(2)读写权限修饰符readwrite:默认,同时生成getter、setter方法readonly:只生成getter方法,无法赋值,常用于对外暴露只读数据(3)线程安全修饰符atomic:默认,原子性操作,保证读写线程安全,性能较低,仅保证单条语句安全,不保证业务逻辑安全nonatomic:非原子性,不保证线程安全,读写速度快,开发中几乎全部使用3、copy和mutableCopy的区别?深浅拷贝原理?答案:核心定义copy:产生不可变副本,无论原对象是否可变,拷贝结果都是不可变对象mutableCopy:产生可变副本,无论原对象是否可变,拷贝结果都是可变对象深浅拷贝规则浅拷贝:只拷贝对象指针,不拷贝内存数据,新旧对象指向同一块内存,引用计数+1深拷贝:拷贝对象内存数据,生成全新内存地址的对象,新旧对象互不影响具体场景不可变对象(NSString、NSArray)调用copy:浅拷贝,指针赋值,无新内存不可变对象调用mutableCopy:深拷贝,生成可变新对象可变对象(NSMutableString、NSMutableArray)调用copy/mutableCopy:均为深拷贝,生成全新对象开发使用场景:字符串、数组属性用copy修饰,防止外部传入可变对象,篡改内部数据,保证数据稳定性。二、内存管理核心面试题(ARC/MRC)1、ARC的原理是什么?ARC是完全不用管内存吗?答案:ARC即自动引用计数,是编译器层面的内存管理机制,而非运行时机制。编译代码时,编译器会自动在合适的位置插入retain、release、autorelease代码,替代手动内存管理。ARC不是完全不用管理内存,只是规避了手动写释放代码的繁琐,依然需要处理内存问题:需要手动规避循环引用(最核心问题)Block捕获外部变量的内存持有问题需要手动处理NSTimer、CADisplayLink容易产生常驻内存泄漏,需要手动销毁代理属性必须用weak修饰,否则控制器无法释放2、什么是循环引用?如何解决常见循环引用场景?答案:两个或多个对象互相强引用对方,导致引用计数永远无法归零,对象无法释放,造成内存泄漏。常见场景及解决方案:代理循环引用:代理属性统一用weak修饰,打破强引用闭环Block循环引用:使用__weak修饰外部对象,在block内部用__strong临时持有,避免提前释放父子对象互相引用:子对象对父对象的引用用weak,父对象对子对象用strongNSTimer循环引用:使用timer分类、中介者模式,或在视图销毁前手动invalidate定时器3、__weak、__strong、__autoreleasing、__unsafe_unretained区别?答案:__strong:默认修饰符,强引用,持有对象,引用计数+1,对象不会自动释放__weak:弱引用,不持有对象,引用计数不变,对象销毁后指针自动置空,安全无野指针__autoreleasing:自动释放,修饰临时变量,加入自动释放池,出作用域后延迟释放,多用于指针返回值场景__unsafe_unretained:无引用计数管理,类似assign修饰对象,对象销毁后指针不置空,会产生野指针,极不安全,基本不使用三、Runtime运行时机制高频题1、简述Runtime的核心作用,OC方法调用的底层流程?答案:Runtime是OC的底层C语言库,是OC动态特性的核心支撑,所有OC代码底层都会转换为RuntimeC函数调用。核心作用:动态创建类、动态添加/替换方法、动态关联属性、消息转发、获取类/方法/属性信息。方法调用底层流程:OC方法调用[objmethod:]底层转换为objc_msgSend(obj,@selector(method:))Runtime先通过obj找到对应的类对象,遍历类的方法缓存列表查找方法缓存未命中,遍历类的方法列表查找SEL对应的IMP函数地址当前类未找到方法,逐级遍历父类、根类NSObject的方法列表全程未找到方法,进入消息转发机制,防止程序崩溃2、Runtime消息转发机制完整流程?答案:当对象无法响应某个方法时,不会直接崩溃,会依次执行三层消息转发,给程序补救机会:第一层:动态方法解析调用+resolveInstanceMethod:/+resolveClassMethod:,可动态为当前类添加未实现的方法,返回YES则重新执行方法。第二层:快速消息转发(备用接收者)调用-forwardingTargetForSelector:,返回一个能响应该方法的对象,将消息转发给该对象处理,效率最高。第三层:完整消息转发调用-methodSignatureForSelector:生成方法签名,再调用-forwardInvocation:自定义消息转发逻辑,可修改方法、转发给多个对象。三层转发全部失败,程序抛出unrecognizedselector崩溃。3、Category分类的底层原理?为什么不能添加成员变量?如何实现分类存属性?答案:Category底层是结构体,编译时仅存放方法、协议、属性声明,不会生成成员变量。底层原理:编译后分类的方法会被加载到类的方法列表中,主类方法和分类方法冲突时,分类方法会覆盖主类方法,多个分类优先级由编译顺序决定。不能添加成员变量的原因:类的成员变量内存结构在编译时已经确定,分类无法修改原有内存布局,所以无法直接添加ivar。分类实现存属性:通过Runtimeobjc_setAssociatedObject和objc_getAssociatedObject关联对象,动态绑定属性数据,模拟成员变量存储。四、Block核心面试题1、Block的本质是什么?三种Block类型区别?答案:Block本质是封装了函数代码块和外部变量捕获的OC对象,底层是结构体,包含函数指针、捕获变量、描述信息。三种类型及区别:全局Block(__NSGlobalBlock__):没有捕获任何外部变量,存储在数据段,生命周期和程序一致,不会释放栈Block(__NSStackBlock__):捕获外部变量,存储在栈区,出作用域后立即销毁,ARC下基本不会出现堆Block(__NSMallocBlock__):ARC下栈Block被强引用、赋值给变量、作为返回值时,会自动拷贝到堆区,需要内存管理,支持生命周期延续2、Block变量捕获规则?__block的作用?答案:变量捕获规则全局变量:直接访问,不捕获局部基本变量:值捕获,拷贝变量当前值,block内部无法修改外部变量局部对象变量:指针捕获,拷贝变量指针,可修改对象内部属性,无法修改指针本身static静态变量:指针捕获,通过指针可修改外部变量值__block核心作用修饰局部变量,允许Block内部修改外部变量本身。底层原理:将变量包装成结构体对象,Block捕获结构体指针,实现变量共享修改,同时解决变量值拷贝问题。五、多线程与GCD面试题1、GCD队列和任务的区别?串行、并行队列区别?答案:任务:需要执行的代码块(block);队列:用来存放任务的容器,遵循FIFO先进先出原则。队列类型区别:串行队列(Serial):队列内任务逐个执行,上一个任务结束才会执行下一个,只开启一条线程并行队列(Concurrent):队列内任务同时执行,自动开启多条线程,任务执行顺序不确定核心注意:串行/并行决定任务执行方式,同步/异步决定是否开启新线程。2、同步、异步的区别?死锁场景及原理?答案:同步dispatch_sync:不开启新线程,阻塞当前线程,等待任务执行完毕后,代码继续往下走异步dispatch_async:开启新线程(并行队列下),不阻塞当前线程,代码直接往下执行,任务异步执行常见死锁场景:主队列同步执行任务原理:主线程正在执行当前代码,又同步向主队列添加任务,主队列串行执行,需要等待新任务完成才能继续执行当前代码,新任务需要当前代码执行完毕才能调度,互相等待,形成死锁。3、GCD信号量、栅栏函数的作用?答案:栅栏函数dispatch_barrier用于并行队列中,隔离读写任务。栅栏任务执行前,等待队列所有已有任务完成;栅栏任务执行期间,队列新任务阻塞;栅栏任务完成后,后续任务正常执行。主要解决多线程读写安全问题。信号量dispatch_semaphore核心作用:控制最大并发线程数、线程同步、解决资源竞争。通过信号量计数,wait等待信号、signal释放信号,可实现线程加锁效果,性能优于NSLock。六、UI与RunLoop核心面试题1、RunLoop的作用是什么?主线程RunLoop运行逻辑?答案:RunLoop是运行循环,本质是保活线程、处理事件、休眠线程,让线程不会执行完代码后立即销毁,实现线程常驻。主线程RunLoop默认开启,核心作用:监听UI点击、滑动、刷新、定时器、网络回调等事件,循环处理任务,无事件时线程休眠,节省性能。RunLoop运行模式:默认模式、追踪滚动模式、通用模式,不同模式监听不同事件,滚动时切换模式保证滑动流畅。2、NSTimer为什么不准?如何解决?答案:NSTimer依赖RunLoop运行,存在两个核心问题导致不准:RunLoop模式切换:列表滑动时RunLoop切换到追踪模式,默认模式下的定时器事件无法触发,造成计时卡顿RunLoop任务堆积:主线程任务过多,定时器任务被延后执行,出现计时偏差解决方案:将定时器添加到RunLoop通用模式(NSRunLoopCommonModes)使用GCD定时器dispatch_source_timer,不依赖RunLoop,精度更高、更稳定3、UIView和CALayer的区别与关系?答案:UIView是视图载体,负责事件响应、用户交互;CALayer是图层,负责视图渲染、样式展示,不处理交互。核心关系:UIView底层依赖CALayer渲染,每一个UIView内部都有一个默认layer,所有圆角、阴影、边框等样式都是layer的属性,view只是封装层。区别:View继承自UIResponder,支持点击、触摸事件;Layer继承自NSObject,无交互能力View侧重业务交互,Layer侧重图形渲染Layer可以做动画、遮罩,性能优于直接操作View七、常见底层及笔试面试题1、isKindOfClass和isMemberOfClass区别?答案:isMemberOfClass:精准判断,对象必须是当前类的实例,子类实例返回NOisKindOfClass:模糊判断,对象是当前类实例或当前类的子类实例,均返回YES日常开发判断对象类型,统一使用isKindOfClass,适配继承场景。2、NSObject

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论