版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Objective-C高频面试题及详细答案(企业实战版)一、基础语法核心题1、简述Objective-C的特性,以及和C语言的区别?答案:Objective-C是在C语言基础上拓展的面向对象编程语言,完全兼容C语言所有语法,核心新增了面向对象、消息传递、动态运行三大核心能力,也是iOS、macOS开发的原生语言。和C语言的核心区别:编程思想不同:C是面向过程,侧重流程和步骤;OC是面向对象,侧重封装、继承、多态,以类和对象为核心。调用机制不同:C是函数调用,编译时就确定调用地址;OC是消息发送机制,运行时才确定方法调用对象。内存管理不同:C靠手动malloc/free管理堆内存;OC有一套专属的引用计数内存管理机制,后期支持ARC自动管理。拓展能力不同:OC拥有分类、协议、扩展、运行时动态特性,可动态新增方法、修改类行为,C语言无此类能力。2、#import和#include的区别?@class的作用是什么?答案:#import与#include区别:#include是C语言原生指令,只会单纯引入头文件,会出现重复导入、循环导入问题,需要手动用宏防护。#import是OC专属指令,底层做了去重处理,自动防止头文件重复导入,无需手动防护,iOS开发中统一使用#import。@class作用:属于类前置声明,只告诉编译器“这是一个类”,不引入类的具体实现和成员变量。主要用在头文件中解决循环依赖问题,减少编译耗时;实现文件中仍需#import对应头文件。3、readonly、readwrite、assign、retain、copy、strong、weak关键字的区别及使用场景?答案:1.权限修饰符readwrite:默认属性,可读可写,会自动生成getter、setter方法。readonly:只读,只生成getter方法,不生成setter,外部无法修改属性值,常用于对外暴露数据、禁止外部修改的场景。2.内存修饰符(核心)assign:直接赋值,不操作引用计数,不产生新内存。
适用场景:基本数据类型(int、float、BOOL)、枚举、结构体;
注意:修饰对象会产生野指针,对象销毁后指针不会置空。strong:ARC下默认对象修饰符,强引用,持有对象并让引用计数+1,只要有强引用指向,对象就不会销毁。
适用场景:所有OC对象(NSString、NSArray、自定义类等)。weak:弱引用,不增加引用计数,不持有对象。对象销毁后,指针会自动置空,不会产生野指针。
适用场景:代理、block自引用、循环引用破解(控制器、view互相持有)。copy:拷贝特性,赋值时会复制一份新内存,新旧对象互不影响。
适用场景:NSString、NSBlock、NSDictionary等不可变容器,防止外部修改原数据影响当前属性。retain:MRC下的强引用,功能等同于ARC的strong,现在项目基本不用,仅老旧项目可见。4、深拷贝和浅拷贝的区别?copy和mutableCopy底层原理?答案:浅拷贝(浅复制):只拷贝对象指针,不拷贝对象本身,新旧指针指向同一块内存,修改一个会影响另一个,引用计数+1。深拷贝(深复制):重新开辟内存,拷贝对象所有内容,生成全新对象,新旧对象内存独立,互不影响。copy/mutableCopy规则:不可变对象(NSString、NSArray)调用copy:浅拷贝,指针复用,无新内存。不可变对象调用mutableCopy:深拷贝,生成可变新对象。可变对象(NSMutableString、NSMutableArray)调用copy、mutableCopy:均为深拷贝,生成全新对象,其中copy生成不可变对象,mutableCopy生成可变对象。二、内存管理高频题(ARC/MRC)1、ARC的原理是什么?ARC是编译时机制还是运行时机制?答案:ARC是编译时自动内存管理机制,并非运行时机制。编译器会在编译代码阶段,自动为对象插入retain、release、autorelease代码,替代手动MRC内存管理代码,无需开发者手动管理内存。核心规则:凡是alloc、new、copy、mutableCopy开头的方法创建的对象,开发者持有,需要释放;ARC自动补全释放代码。其他方式创建的对象,系统自动管理,无需手动处理。ARC不会完全杜绝内存问题,仍会存在循环引用、内存泄漏、野指针等问题,需要手动规避。2、什么是循环引用?如何解决常见的循环引用场景?答案:两个或多个对象互相使用strong强引用对方,导致双方引用计数都无法归零,对象无法销毁,最终造成内存泄漏,这就是循环引用。常见场景及解决方案:代理循环引用:父视图/控制器强引用代理对象,代理对象又强引用父对象。解决方案:代理属性用weak修饰。Block自引用:Block内部使用self,Block又被self强持有。解决方案:用__weak弱化self,内部如需防止提前销毁,可搭配__strong临时持有。父子对象互相持有:子对象strong持有父对象,父对象strong持有子对象。解决方案:子对象用weak持有父对象。3、autoreleasepool自动释放池的原理及作用?答案:autoreleasepool是OC的自动释放机制,核心作用是延迟释放对象。被加入释放池的autorelease对象,不会立即释放,会在当前runloop迭代结束、释放池销毁时统一批量release。底层原理:每个线程都有专属的autoreleasepool栈,创建释放池就是入栈操作,销毁就是出栈操作。所有autorelease对象会被记录在栈中,栈弹出时统一释放所有对象。使用场景:循环中大量创建临时对象,导致内存峰值过高,手动添加autoreleasepool及时释放临时对象,降低内存占用。子线程需要手动创建释放池,否则线程内autorelease对象无法释放,造成内存泄漏(主线程系统自动创建默认释放池)。三、Block核心面试题1、Block的本质是什么?Block有几种类型?答案:Block本质是封装了函数代码块、局部变量捕获的结构体,是带自动变量捕获功能的匿名函数。根据内存位置分为三种类型:全局Block(_NSGlobalBlock):存放在数据段,无外部变量捕获。生命周期和程序一致,不会销毁。栈Block(_NSStackBlock):存放在栈区,捕获外部变量,未被强引用。函数出栈后会立即销毁,极易出现野指针崩溃,MRC下常见。堆Block(_NSMallocBlock):存放在堆区,栈Block被copy/strong引用后生成。需要手动管理内存(MRC),ARC自动管理,生命周期由引用计数决定。2、Block捕获变量的规则?为什么Block内部无法直接修改外部局部变量?答案:变量捕获规则:全局变量:直接访问,不捕获,无拷贝。静态局部变量(static):捕获变量指针,可直接修改外部变量值。普通局部变量:值捕获,Block初始化时拷贝一份变量值,后续外部变量修改不影响Block内部。无法直接修改普通局部变量的原因:Block捕获的是局部变量的副本,编译器会报错防止开发者混淆内外变量。如果需要在Block内部修改外部局部变量,需要用__block修饰,__block会将变量包装成结构体,让Block可以操作变量原值。3、__block和__weak的区别?答案:__block:用于修改外部变量值,可修饰基本数据类型和对象类型,不会打破循环引用,会保留对象持有关系。__weak:用于解决循环引用、防止内存泄漏,只能修饰对象类型,弱化引用,不增加引用计数,无法修改变量值。四、RunLoop面试高频题1、RunLoop的作用是什么?RunLoop和线程的关系?答案:RunLoop是运行循环,本质是让线程保活、循环处理事件的消息循环机制。没有RunLoop的线程,执行完任务后会立即退出销毁;有RunLoop的线程会持续休眠、等待、处理事件,保持常驻。RunLoop与线程的关系:一一对应,线程专属,保存在线程的字典中。主线程RunLoop系统自动创建并开启,常驻运行;子线程RunLoop需要手动创建、开启、运行。线程销毁时,对应的RunLoop也会随之销毁。核心作用:维持线程常驻、监听触摸/网络/定时器事件、管理线程任务、节省CPU资源(无事件时线程休眠)。2、NSTimer为什么会不准?如何解决?答案:不准的核心原因:NSTimer是依赖RunLoop运行的定时器,并非实时触发。RunLoop是循环处理任务,如果当前RunLoop正在执行耗时操作,定时器事件会被延后堆积,错过触发时机。NSTimer默认加入主线程RunLoop,主线程卡顿、任务繁忙时,定时器无法准时执行。RunLoop的模式切换会导致定时器暂停失效。解决方案:将NSTimer加入NSRunLoopCommonModes通用模式,避免模式切换导致暂停。将定时器放到子线程RunLoop中运行,避开主线程卡顿影响。使用GCD定时器替代NSTimer,GCD定时器基于内核时钟,精准度更高,不依赖RunLoop。五、多线程(GCD)面试题1、GCD队列和线程的区别?串行、并行、主队列、全局队列的特点?答案:核心区别:队列是任务调度容器(存放任务、管理执行顺序),线程是任务执行载体(真正执行代码)。GCD只负责将任务加入队列,系统自动分配线程执行。四种队列特性:主队列(main):串行队列,所有任务在主线程执行,任务按顺序逐个执行,主要用于刷新UI。全局队列(global):并行队列,系统自带,自动开辟子线程,多个任务并发执行,无需手动创建。自定义串行队列:手动创建,单线程执行,任务先进先出、顺序执行,可解决线程安全问题。自定义并行队列:手动创建,多线程并发执行,任务执行顺序无序,效率更高。2、sync和async的区别?死锁产生的原因?答案:async异步执行:立刻返回,不阻塞当前线程,开辟新线程执行任务。sync同步执行:阻塞当前线程,等待队列中任务执行完成后,代码才会继续往下走。GCD死锁核心原因:当前线程等待自己队列的任务执行完成,互相等待、互相阻塞,线程卡死无法继续执行。最常见死锁场景:主线程中调用dispatch_sync往主队列添加任务。主线程正在执行当前代码,同时等待主队列新任务完成,新任务需要主线程空闲才能执行,形成死锁。3、dispatch_once的底层原理和作用?答案:dispatch_once用于保证代码在程序生命周期内只执行一次,常用于单例创建、全局配置初始化。底层原理:依靠静态变量标记+原子锁机制。首次执行时标记为已执行,后续所有线程调用都会直接跳过,天然线程安全,无需额外加锁,执行效率极高。六、运行时Runtime基础面试题1、Runtime是什么?核心作用有哪些?答案:Runtime是OC的底层运行时库,是一套纯C语言编写的API,OC代码编译后并不会直接执行,而是全部转换成Runtime底层函数调用,OC的动态特性完全依赖Runtime实现。核心作用:消息发送:方法调用本质是objc_msgSend消息发送。动态操作类:动态新增、修改、替换方法,动态添加成员变量。方法交换(hook):拦截系统方法,自定义逻辑。获取类的所有属性、方法、协议,实现字典转模型、归档解档。2、OC方法调用的本质?objc_msgSend执行流程?答案:OC中[objmethod]方法调用,编译后本质是objc_msgSend(obj,@selector(method)),运行时动态查找并执行方法。执行流程:判断接收消息的对象是否为空,为空直接返回。从对象的类缓存中查找方法,找到直接调用。缓存未找到,去类的方法列表遍历查找。当前类未找到,逐级遍历父类、根类方法列表。最终未找到方法,进入消息动态解析、消息转发流程,防止崩溃。七、常见实操故障面试题1、常见的iOS崩溃原因有哪些?答案:野指针崩溃:指针指向已销毁的内存,继续调用对象方法/属性。数组/字典越界:访问不存在的下标、插入空值、
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025~2026学年湖南湘西土家族苗族自治州龙山县思源实验学校人教版下册一年级数学阶段学情自测卷【附答案】
- 2025~2026学年甘肃平凉市某校人教版第二册期末学业水平检测六年级数学【附答案】
- 2025-2026学年黑龙江省富锦市初中数学八年级期末上册自我评估高分特训题(详细参考解析)
- Photoshop职业技能等级考证模拟试题(含详细答案解析)
- 2026年电力调度员考试题及答案
- 强夯机司机安全操作规程
- 物流分拣线设备操作安全方案
- 贵州省黔东南州名校2027届数学八上期末统考模拟试题含解析
- 2025-2026学年山东省龙口市初中生物七年级期末上册高分通关高频易错题附答案
- 班组安全班前会标准化执行方案
- 2024-2025学年山东省聊城市东昌府区九年级(上)期中物理试卷(含答案)
- 04-家庭教育:3至12岁好习惯养成实操手册
- 2026年中国电信应届生校园招聘笔试真题(含详细答案解析)
- 电动机的正反转控制公开课
- 药品营销推广方案与市场分析报告
- 4.2 厘米和米(2)(教学课件) 人教版(2024)小学数学二年级上册
- 消防站建设项目环评报告
- 饲料化验检验试题
- 空调设备安装安全生产培训
- CJT 340-2016 绿化种植土壤
- 频率的稳定性省公开课一等奖新名师比赛一等奖课件
评论
0/150
提交评论