iOS-2025进阶面试题加答案

1.copystrong修饰符的区别?为何NSString常用copy

  • 答案strong增加引用计数,copy创建不可变副本。NSString用copy防止外部可变字符串(如NSMutableString)修改导致值变化,保障数据不可变性。

2.GCD与NSOperation的适用场景?如何实现任务依赖和优先级控制?

答案:GCD适合简单任务(如异步加载),NSOperation适合复杂任务(支持取消、依赖、优先级)。通过addDependency设置依赖,queuePriority控制优先级。

3.Runtime的消息转发机制分哪几步?如何动态添加方法? 

答案:消息转发分为:

  1. 动态方法解析(resolveInstanceMethod:);

  2. 备用接收者(forwardingTargetForSelector:);

  3. 完整转发(methodSignatureForSelector:forwardInvocation:)。
    动态添加方法使用class_addMethod

4.如何优化UITableView滚动性能? 

答案

  • 复用Cell(dequeueReusableCellWithIdentifier:);

  • 异步解码图片、离屏渲染(如使用CATiledLayer);

  • 减少AutoLayout计算,预计算Cell高度;

  • 使用willDisplayCell延迟加载非关键资源。

5.Block的循环引用如何产生?如何用__weak和__block解决? 

答案:Block捕获外部对象强引用导致循环。解决:

  • 使用__weak弱引用(如__weak typeof(self) weakSelf = self);

  • __block修饰变量并在Block内手动置nil(需调用Block)。

6. Swift与Objective-C的Runtime消息转发机制对比 

问题:Objective-C的消息转发分为resolveInstanceMethodforwardingTargetForSelectormethodSignatureForSelector三阶段,而Swift中@dynamic修饰的方法如何实现类似机制?请结合Swift的Method Dispatch机制分析。

深度解析: 
1.Objective-C的消息转发流程
  • 动态方法解析resolveInstanceMethod允许运行时添加方法实现。

  • 快速转发forwardingTargetForSelector将消息转发给其他对象处理。

  • 完整转发methodSignatureForSelectorforwardInvocation构造NSInvocation对象。

2.Swift的动态性限制

Swift默认使用静态派发(值类型)或虚表派发(类),除非:

  • 使用@dynamic修饰符(如CoreData的NSManagedObject子类)。

  • 继承自NSObject并标记@objc dynamic

3.Swift中的消息转发实现
class MyClass: NSObject {  
  @objc dynamic func handleMessage() { /* 默认实现 */ }  
}  

let obj = MyClass()  
// 替换方法实现  
let originalMethod = class_getInstanceMethod(MyClass.self, #selector(handleMessage))  
let newMethod = class_getInstanceMethod(MyClass.self, #selector(newHandleMessage))  
method_exchangeImplementations(originalMethod, newMethod)  
面试延伸
  • Swift如何实现KVO?答:通过@objc dynamic强制使用Objective-C Runtime。

  • Swift的协议扩展(Protocol Extension)是否支持动态派发?答:协议扩展方法静态派发,除非在协议中声明为@objc


7.Swift Concurrency(async/await)与GCD的底层线程管理对比

问题:Swift的async/await语法在底层如何管理线程?与GCD的Work Item和队列优先级有何本质区别?

深度解析: 
1.GCD的线程管理
  • 基于线程池和队列(Serial/Concurrent),通过优先级(QoS)调度任务。

  • 问题:优先级反转(Priority Inversion)、线程爆炸(Thread Explosion)。

2.Swift Concurrency模型
  • 协作式线程池:由系统管理的线程池(默认线程数=CPU核心数),任务通过挂起(Suspend)而非阻塞(Block)让出线程。

  • 结构化并发:通过TaskGroupasync let绑定子任务生命周期。

  • 优先级继承:子任务自动继承父任务优先级,避免优先级反转。

3.性能对比
// GCD  
DispatchQueue.global(qos: .userInitiated).async {  
  let data = fetchData()  
  DispatchQueue.main.async { updateUI(data) }  
}  

// Swift Concurrency  
Task(priority: .userInitiated) {  
  let data = await fetchData()  
  await MainActor.run { updateUI(data) }  
}  
  • 优势:更少线程切换、自动取消传播、无回调地狱。

面试延伸
  • MainActorDispatchQueue.main的区别?答:MainActor是全局串行执行器,整合了Swift Concurrency的调度机制。

  • 如何避免Task的循环引用?答:使用[weak self]捕获列表或Task.detached

8. Swift Actor模型与GCD线程调度的性能对比及死锁预防

问题:Swift的Actor如何通过隔离状态保证线程安全?对比GCD的串行队列,分析两者在10k任务并发下的性能差异。

深度解析
  • Actor机制:每个Actor独立串行队列,通过await挂起非阻塞任务。

  • 性能对比

    指标Swift ActorGCD串行队列
    上下文切换开销低(协作式)高(线程切换)
    死锁风险低(编译器静态检查)高(需手动避免)
    内存占用更优(少量Continuation)线程栈积累
  • 死锁案例

actor A { 
  func foo() async { await bar() } 
  func bar() async { ... } 
}  
// 无死锁,编译器强制异步调用  

9.Objective-C与Swift混编下的内存管理陷阱 

问题:在Swift中调用Objective-C的retain/release方法会导致什么问题?如何通过Unmanaged正确转换Core Foundation对象?

 深度解析
  • 陷阱场景:Swift的ARC自动插入retain/release,手动调用会导致重复释放。

  • 安全转换

let cfStr = CFStringCreateWithCString(nil, "test", kCFStringEncodingUTF8)  
let swiftStr = Unmanaged<CFString>.fromOpaque(cfStr).takeRetainedValue()  
  • 调试工具:Xcode的Memory Graph可检测野指针和循环引用.

10.Metal API在实时滤镜渲染中的优化策略

问题:如何通过Metal的MTLHeapMTLFence实现纹理内存的高效复用?对比Core Image的性能瓶颈。

深度解析: 
  • MTLHeap优化:预分配GPU内存池,避免频繁申请释放。

  • MTLFence应用:同步GPU指令队列,防止资源竞争。

  • 对比Core Image

    • Metal:延迟<5ms,支持自定义Shader。

    • Core Image:延迟15-30ms,但API更简洁。

实战建议

        混合使用Core Image预处理和Metal后处理。


11.LLVM编译优化对Swift协议扩展方法派发的影响

问题:分析Swift协议扩展方法在O2优化下的静态派发机制,如何通过@objc dynamic强制改为动态派发?

深度解析: 
  • 静态派发条件:方法未在协议声明中定义,直接通过扩展实现。

  • 动态派发实现

@objc protocol MyProtocol {}  
extension MyProtocol {  
  @objc dynamic func foo() { ... }  
}  
  • 性能代价:动态派发增加方法查找开销约20%。


12.基于Combine框架的响应式状态管理设计模式

问题:在SwiftUI中如何通过Combine的@PublishedCurrentValueSubject实现跨View共享状态?对比RxSwift的内存泄漏风险。

深度解析: 
  • 状态共享方案
class Store: ObservableObject {  
  @Published var state = AppState()  
  private let subject = CurrentValueSubject<AppState, Never>(AppState())  
}  
  • 内存安全

    • Combine自动管理订阅生命周期。

    • RxSwift需手动dispose(),易遗漏导致泄漏。

最佳实践

        结合weak self.store(in: &cancellables)



扩展建议

  • 研究Swift Concurrency(async/await)与GCD的性能对比,分析线程管理的最佳实践。
  • 掌握Swift Concurrency的底层原理(如Continuation、Actor模型),对比Objective-C Runtime的历史局限性。
  • 深入Instrument的Time Profiler定制化分析技巧,优化冷启动时间。

持续更新中。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小怪人研究院

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值