版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
2025年高频ios基础面试题及答案Objective-C中属性的nonatomic和atomic的核心区别是什么?实际开发中为何更倾向使用nonatomic?nonatomic和atomic是属性声明时的原子性修饰符。atomic(原子性)会保证属性的setter和getter方法是线程安全的,系统会通过自旋锁(spinlock_t)确保同一时间只有一个线程能访问该属性的赋值或取值操作。但这种安全仅针对单个属性的读写操作,无法保证复合操作(如先读再写)的线程安全。而nonatomic(非原子性)不提供线程安全保证,其setter/getter方法直接操作内存,没有锁的开销。实际开发中更常用nonatomic,主要原因是atomic的性能损耗(每次读写需要加锁解锁),而iOS应用的UI操作和大部分业务逻辑集中在主线程,nonatomic的性能优势更明显;此外,真正需要线程安全的场景通常通过更细粒度的锁(如os_unfair_lock)或GCD队列控制,atomic的单一属性保护意义有限。Swift中struct(结构体)和class(类)的核心差异有哪些?各自适用场景是什么?struct是值类型,class是引用类型。值类型的特点是赋值时复制整个实例(写时复制,COW),数据存储在栈或堆(取决于上下文),但所有权明确,无引用计数开销;引用类型赋值时共享同一实例,通过ARC(自动引用计数)管理内存,实例存储在堆中。具体差异包括:struct默认不可继承(无继承体系),class支持继承;struct的方法默认不能修改自身属性(需标记mutating),class的方法可自由修改属性;struct的初始化需严格满足所有属性的初始化(编译器强制),class可通过指定初始化器和便捷初始化器灵活处理。适用场景:struct适合轻量、数据封装且无需继承的场景(如坐标点CGPoint、数据模型),因其值语义天然线程安全;class适合需要状态共享、继承或复杂生命周期管理的场景(如视图控制器UIViewController、需要多模块共享状态的管理器)。Block的内存管理机制是怎样的?如何避免Block导致的循环引用?Block在iOS中本质是Objective-C对象,根据捕获变量的情况分为三种类型:NSGlobalBlock(全局Block)、NSStackBlock(栈Block)、NSMallocBlock(堆Block)。NSGlobalBlock不捕获任何外部变量(或仅捕获全局变量/静态变量),存储在全局区,生命周期与程序一致;NSStackBlock捕获局部变量(对象或基本类型),存储在栈区,生命周期随栈帧结束而销毁(离开作用域后被释放);NSMallocBlock由NSStackBlock调用copy方法后提供,存储在堆区,通过引用计数管理生命周期(copy时引用计数+1,释放时-1)。Block捕获变量的规则:对基本类型局部变量值捕获(拷贝值到Block结构体),对对象类型局部变量引用捕获(强引用,若Block在堆上则持有该对象),对__block修饰的变量(无论基本类型或对象类型)会提供一个结构体,Block持有该结构体的强引用,结构体内部持有原变量的引用(可修改)。循环引用通常发生在Block被某个对象(如self)强引用,同时Block内部又强引用该对象(如self.xxx),导致两者引用计数无法降为0。解决方案包括:使用__weak修饰符(如__weaktypeof(self)weakSelf=self;)使Block弱引用对象,对象释放时weakSelf自动置nil;在需要确保对象存活时结合__strong(如__strongtypeof(weakSelf)strongSelf=weakSelf;)避免在Block执行过程中对象被释放;Swift中使用[weakself]或[unownedself](unowned需确保对象在Block执行时一定存在,否则崩溃)。简述Objective-C的消息传递机制,objc_msgSend的执行流程是怎样的?Objective-C是动态语言,方法调用本质是“消息发送”,通过objc_msgSend函数实现。消息传递的核心流程分为三步:消息查找、动态方法解析、消息转发。1.消息查找:接收到消息(如[objmethod])时,首先通过对象的isa指针找到其类对象(Class),在类的方法列表(methodlist)中查找对应的SEL(方法选择器)。若未找到,沿继承链向上查找父类的方法列表,直到根类NSObject。2.动态方法解析:若消息查找未找到方法,进入动态解析阶段。调用+resolveInstanceMethod:(实例方法)或+resolveClassMethod:(类方法),允许运行时动态添加方法(通过class_addMethod函数关联IMP实现)。若在此阶段添加了方法,消息传递继续执行;若未处理,进入消息转发。3.消息转发:首先尝试快速转发(forwardingTargetForSelector:),返回一个能处理该消息的对象,若返回nil则进入标准转发。标准转发阶段调用methodSignatureForSelector:获取方法签名,若返回有效签名则调用forwardInvocation:方法,允许自定义处理消息(如转发给其他对象);若无法提供签名,最终调用doesNotRecognizeSelector:抛出异常。自动释放池的工作原理是什么?开发中何时需要手动创建自动释放池?自动释放池(NSAutoreleasePool)通过维护一个栈结构的自动释放对象列表,管理对象的延迟释放。当对象调用autorelease方法时,会被加入当前线程的自动释放池中(由Pthread的线程局部存储TLS维护)。自动释放池的释放时机由RunLoop控制:主线程的RunLoop在每次循环结束时(进入休眠前)会触发自动释放池的drain操作,将池中所有对象的引用计数减1(若引用计数降为0则释放)。子线程若未启用RunLoop,默认不会创建自动释放池,需手动管理。手动创建自动释放池的典型场景包括:长时间运行的循环(如批量处理大量数据):循环中创建大量临时对象(如NSString、UIImage),若不手动创建释放池,这些对象会累积到当前RunLoop结束时才释放,可能导致内存峰值过高。此时在循环内部添加@autoreleasepool{},可在每次循环迭代后及时释放临时对象。子线程中执行耗时操作:子线程默认无自动释放池(除非启动RunLoop),手动创建释放池可避免对象无法及时释放导致的内存泄漏。GCD中dispatch_sync和dispatch_async的核心区别是什么?死锁的常见场景及避免方法?dispatch_sync(同步分发)会阻塞当前线程,等待block在目标队列执行完毕后再继续执行后续代码;dispatch_async(异步分发)不会阻塞当前线程,block会被提交到目标队列的任务列表,由队列调度执行,当前线程继续执行后续代码。两者的本质区别是是否阻塞当前线程。死锁的常见场景是在串行队列中同步提交一个会在同一队列执行的block。例如:主线程(串行队列)中调用dispatch_sync(dispatch_get_main_queue(),^{...}),此时主线程等待block执行,但block需要主线程空闲才能执行,导致相互等待。另一种场景是在自定义串行队列中同步提交block到自身。避免死锁的方法:避免在串行队列中使用dispatch_sync提交任务到同一队列;若需同步获取结果,可使用dispatch_group(分组)或dispatch_semaphore(信号量)在并行队列中处理;主线程中避免使用dispatch_sync提交任务到主线程队列。KVO的底层实现原理是什么?如何手动触发KVO?KVO(键值观察)的底层通过Runtime的isa-swizzling机制实现。当对象(被观察对象)的某个属性被观察时,系统会动态创建一个该对象类的子类(命名格式为NSKVONotifying_原类名),并将被观察对象的isa指针指向这个子类(即isa-swizzling)。子类会重写被观察属性的setter方法,在setter中调用willChangeValueForKey:和didChangeValueForKey:方法,触发观察者的observeValueForKeyPath:ofObject:change:context:方法。原类的其他方法(如dealloc)会被保留或重写以确保功能正常。手动触发KVO需显式调用willChangeValueForKey:和didChangeValueForKey:方法,即使属性的值未发生变化。例如:```objc[objectwillChangeValueForKey:@"property"];//手动修改属性值(或不修改)[objectdidChangeValueForKey:@"property"];```这两个方法的调用顺序必须正确,否则无法触发KVO通知。RunLoop的核心作用是什么?它与线程的关系是怎样的?RunLoop是线程的事件循环机制,作用包括:控制线程的生命周期(保持线程存活,避免执行完任务后销毁)、处理输入事件(触摸、网络、定时器)、调度GCD任务(将block派发到对应线程)、优化界面渲染(配合CoreAnimation在RunLoop休眠前更新界面)。RunLoop与线程是一一对应的关系,通过TLS(线程局部存储)存储。主线程的RunLoop在应用启动时自动创建并运行(由UIApplicationMain函数启动),子线程的RunLoop默认未创建,需手动调用[NSRunLoopcurrentRunLoop]获取时创建,但不会自动运行(需调用run或runMode:beforeDate:启动)。RunLoop的运行模式(如NSDefaultRunLoopMode、UITrackingRunLoopMode)决定了当前处理哪些事件源,不同模式下监听的事件不同(如滑动列表时,主线程RunLoop会切换到UITrackingRunLoopMode,暂停NSDefaultRunLoopMode下的定时器)。Swift的ARC与Objective-C的ARC有何异同?Swift和Objective-C均使用ARC(自动引用计数)管理内存,但实现细节存在差异:1.对象类型:Objective-C中只有NSObject及其子类(引用类型)使用ARC,基本类型(如int)为值类型;Swift中class(引用类型)使用ARC,struct和enum(值类型)通过COW(写时复制)管理,无引用计数开销。2.所有权修饰符:Objective-C使用__strong(默认)、__weak、__unsafe_unretained;Swift使用strong(默认)、weak、unowned(类似__unsafe_unretained)、unowned(safe)/unowned(unsafe)(更细粒度控制)。3.闭包捕获:Objective-C的Block对对象的捕获默认是__strong(堆Block);Swift的闭包对值类型是值捕获,对引用类型默认是强引用,需显式声明[weakself]或[unownedself]。4.弱引用处理:Objective-C的__weak变量在对象释放后自动置nil(通过弱引用表);Swift的weak变量同样自动置nil,但仅适用于类或类的可选类型(protocol需标记@class-bound)。5.析构函数:Objective-C通过dealloc方法释放资源(需调用[superdealloc]);Swift通过deinit方法(无需手动调用父类deinit)。如何优化UITableView的滑动性能?UITableView的滑动性能优化需从数据源加载、单元格渲染、内存管理三方面入手:1.减少单元格内容计算:将耗时操作(如文本布局、图片解码)提前在子线程完成,使用异步绘制(如YYWebImage的预解码)或缓存计算结果(如使用NSCache存储单元格高度)。2.避免离屏渲染:设置cornerRadius+clipsToBounds时,若背景色与父视图不一致会触发离屏渲染(iOS9+对cornerRadius有优化,若视图为纯色且大小固定则不会);可改用CAShapeLayer绘制圆角,或使用mask图片(需权衡内存)。阴影(shadow)的绘制也会触发离屏渲染,可通过设置shadowPath(明确阴影路径)减少计算量。3.优化单元格复用:正确使用dequeueReusableCellWithIdentifier:方法,避免重复创建单元格;注册单元格类型(registerClass:forCellReuseIdentifier:)减少动态查找时间。4.减少图层层级:单元格的subview数量控制在5个以内,避免嵌套过多视图;使用CALayer替代UIView(如显示静态图片),减少视图层级的计算。5.延迟加载非必要内容:滑动时暂停图片加载(通过UIScrollView的delegate方法判断滑动状态),静止时加载;使用渐进式图片加载(如WebP格式)。6.内存管理:及时释放不再使用的缓存(如滑动到远区域时清除离屏单元格的图片缓存),避免内存峰值过高导致应用被系统终止。简述TCP三次握手和四次挥手的过程,iOS中如何实现网络请求的断点续传?TCP三次握手是建立连接的过程:1.客户端发送SYN包(seq=x),请求建立连接;2.服务器收到后发送SYN+ACK包(seq=y,ack=x+1),确认客户端请求;3.客户端发送ACK包(seq=x+1,ack=y+1),确认服务器响应,连接建立。四次挥手是断开连接的过程:1.客户端发送FIN包(seq=u),请求断开连接;2.服务器收到后发送ACK包(seq=v,ack=u+1),确认客户端请求;3.服务器处理剩余数据后发送FIN+ACK包(seq=w,ack=u+1),通知客户端可断开;4.客户端发送ACK包(seq=u+1,ack=w+1),确认服务器断开,连接终止。iOS中实现断点续传需利用HTTP的Range头字段。步骤如下:1.首次请求时记录文件总大小(通过响应头的Content-Length),并在本地创建临时文件;2.中断后重新请求时,获取本地临时文件的当前大小(offset),设置请求头Range:bytes=offset-;3.服务器返回206PartialContent状态码及从offset开始的数据,将新数据追加到临时文件;4.下载完成后校验文件完整性(如MD5哈希),重命名临时文件为最终文件。实际开发中可使用NSURLSession的NSURLSessionDownloadTask,通过resumeData(中断时的恢复数据)实现断点续传;或手动使用NSURLSessionDataTask,结合文件句柄(NSFileHandle)写入数据。什么是内存泄漏?iOS中如何检测和解决内存泄漏?内存泄漏指对象已不再使用,但引用计数无法降为0导致无法释放,造成内存持续占用。常见场景包括循环引用(如Block与self相互强引用)、未正确释放的代理(delegate未使用weak修饰)、NSTimer未invalidate(定时器对target强引用)、全局容器(如单例的数组)未及时移除对象。检测方法:Xcode的MemoryGraphDebugger(内存图调试器):通过Debug>MemoryGraphDebugger捕获内存快照,分析对象的引用链,定位未释放的对象。Instruments的Leaks工具:检测未被释放的堆内存,但无法检测循环引用(因对象仍被引用,不属于“泄漏”的内存)。静态分析(Analyze):通过Xcode的Analyze功能检查潜在的内存问题(如未释放的资源)。解决方法:打破循环引用:使用weak修饰符(如代理属性声明为weak)、Block内部使用weakSelf;及时释放资源:NSTimer需在dealloc中调用invalidate(并将timer置nil),避免强引用target;管理全局容器:单例或全局数组中的对象在不需要时主动移除;使用自动工具:如FBRetainCycleDetector(Facebook开源库)自动检测循环引用。Swift的可选类型(Optional)设计目的是什么?强制解包(!)和可选绑定(iflet/guardlet)的使用场景?可选类型用于表示值可能存在或不存在(即“可能为nil”),是Swift类型安全的核心特性。Objective-C中通过nil表示空值,但仅适用于对象类型;Swift的Optional是枚举(enumOptional<T>{casenone;casesome(T)}),可用于所有类型(如Int?、String?),明确标识值的可选性,避免隐式解包导致的崩溃。强制解包(!)用于开发者明确知道可选值一定有值的场景(如InterfaceBuilder连接的@IBOutlet属性,运行时已加载),但需承担崩溃风险(若值为nil则触发fatalError)。可选绑定(iflet/guardlet)用于安全地解包可选值。iflet适用于局部作用域内使用解包后的值(如:ifletname={...});guardlet适用于提前退出无效状态(如函数中校验参数,若为nil则return,保证后续代码使用非空值),提高代码可读性和安全性。简述Objective-C的类加载过程,+load和+initialize的核心区别?类加载过程发生在应用启动时(dyld动态链接阶段之后,main函数之前),由libobjc库的objc-os.mm负责。主要步骤包括:1.加载类、分类、协议的信息到内存(通过dyld获取所有image的信息);2.修复类的继承关系(确保父类已加载);3.调用类的+load方法(若实现),按“父类->子类->分类”的顺序执行;4.注册类到Runtime的类表中,完成类的初始化。+load和+initialize的区别:调用时机:+load在类被加载到内存时调用(早于main函数),每个类仅调用一次(即使多次加载);+initialize在类首次被使用时调用(如发送消息[Classmethod]),继承链中按“父类->子类”的顺序调用(若子类未实现则调用父类的)。调用次数:+load无论是否被继承,每个类和分类独立调用;+initialize若子类未实现,每次子类使用时会调用父类的+initialize(可能多次调用)。应用场景:+load用于需要尽早执行的操作(如方法交换);+
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 复混肥生产工岗前品质考核试卷含答案
- 医生外出学习请假条
- 2025年新能源环卫装备合作协议书
- 2025年PURL系列反应型皮革用聚氨酯乳液合作协议书
- 2026年新能源汽车换电模式项目可行性研究报告
- 2025年煤化工考试试题及答案
- 清水混凝土模板支撑施工方案
- 2025年期货证券公司年度工作总结
- 企业安全生产托管服务计划书
- 工业机器人系统集成技术2025年培训试卷及答案解析
- 2026年药店培训计划试题及答案
- 2026春招:中国烟草真题及答案
- 物流铁路专用线工程节能评估报告
- 2026河南省气象部门招聘应届高校毕业生14人(第2号)参考题库附答案
- 企业标准-格式模板
- 五年级上册道德与法治期末测试卷新版
- 2022年医学专题-石家庄中国鲍曼不动杆菌感染诊治与防控专家共识
- YY/T 1543-2017鼻氧管
- YS/T 903.1-2013铟废料化学分析方法第1部分:铟量的测定EDTA滴定法
- FZ/T 70010-2006针织物平方米干燥重量的测定
- 高血压的血流动力学基础课件
评论
0/150
提交评论