Hi~
Hi~
文章目录
  1. 资深 iOS 开发工程师面试题
    1. 一、Objective-C 高级
      1. 1. 内存管理
      2. 2. Runtime
      3. 3. 多线程
    2. 二、Swift 高级
      1. 1. struct vs class
      2. 2. Optional
      3. 3. 协议 & 泛型
      4. 4. 闭包
      5. 5. 多线程(Swift)
      6. 6. Codable
      7. 7. 内存管理(Swift)
      8. 8. 响应式编程
    3. 三、iOS 开发高级
      1. 1. UI & 动画
      2. 2. 网络
      3. 3. 数据库
      4. 4. 性能优化
      5. 5. 架构 & 设计模式
    4. 四、高频 Swift 面试题(扩展)
      1. 1. struct vs class
      2. 2. Codable
      3. 3. 多线程
      4. 4. 内存管理
      5. 5. 响应式编程
    5. 五、综合问题
    6. 六、总结

资深 iOS 开发工程师面试题

资深 iOS 开发工程师面试题


一、Objective-C 高级

1. 内存管理

  1. ARC 下如何精确管理对象的生命周期?如何处理复杂引用场景(如 Block 和 Delegate 混合使用)?
    答案:

    • ARC 自动管理引用计数,但需手动处理循环引用。
    • 复杂场景
      • Block 捕获 self 和 Delegate 可能导致多重循环引用。
      • 使用 __weak typeof(self) weakSelf 在 Block 中避免循环引用。
      • Delegate 使用 weak 修饰,防止强引用。
    • 示例
      @interface MyViewController : UIViewController
      @property (nonatomic, weak) id<Delegate> delegate;
      @property (nonatomic, copy) void (^completionBlock)(void);
      @end
      @implementation MyViewController
      - (void)setup {
      __weak typeof(self) weakSelf = self;
      self.completionBlock = ^{
      __strong typeof(weakSelf) strongSelf = weakSelf;
      [strongSelf.delegate performAction];
      };
      }
      @end
    • 高级点:分析 objc_retainobjc_release 在 ARC 下的插入逻辑,使用 Instruments 的 Allocations 工具跟踪引用计数。
  2. 在 MRC 中,手动管理内存的常见问题及优化策略?
    答案:

    • 问题
      • 忘记 releaseautorelease,导致内存泄漏。
      • 过度 retain,导致对象无法释放。
      • dealloc 中未正确释放资源。
    • 优化
      • 使用命名规范(如 create 方法返回需手动释放对象)。
      • 借助 NSAutoreleasePool 管理临时对象。
      • 使用静态分析工具检测内存问题。
    • 注意:MRC 现已淘汰,但理解其原理有助于深入掌握 ARC。
  3. 如何在 Objective-C 中实现自定义内存管理策略(类似 ARC 的弱引用表)?
    答案:

    • 使用 objc_setAssociatedObjectobjc_getAssociatedObject 模拟弱引用。
    • 示例:
      static char kWeakRefKey;
      @implementation NSObject (WeakReference)
      - (void)setWeakReference:(id)object {
      objc_setAssociatedObject(self, &kWeakRefKey, object, OBJC_ASSOCIATION_ASSIGN);
      }
      - (id)weakReference {
      return objc_getAssociatedObject(self, &kWeakRefKey);
      }
      @end
    • 高级点:分析 Runtime 的 objc_storeWeak 实现,探讨弱引用表如何管理对象释放。
  4. autoreleasepool 的底层实现?如何在高内存压力场景下优化?
    答案:

    • 实现NSAutoreleasePool 创建一个池,对象调用 autorelease 时加入池,池销毁时释放所有对象。
    • 优化
      • 在循环中创建局部 autoreleasepool 减少内存峰值。
      • 示例:
        @autoreleasepool {
        for (int i = 0; i < 1000000; i++) {
        NSString *temp = [NSString stringWithFormat:@"%d", i];
        // 处理
        }
        }
      • 使用 @autoreleasepool 包装高频临时对象创建(如 JSON 解析)。
    • 高级点:分析 objc_autoreleasePoolPushobjc_autoreleasePoolPop 的调用栈。
  5. 如何调试复杂的内存泄漏问题(如第三方库导致)?
    答案:

    • 使用 Instruments 的 Leaks 和 Allocations 工具。
    • 结合 MLeaksFinderFBRetainCycleDetector 检测循环引用。
    • 手动注入 dealloc 日志,跟踪对象释放。
    • 高级点:分析第三方库源码,检查是否正确使用 weakunowned,必要时通过 Category 重写方法。

2. Runtime

  1. Objective-C Runtime 如何支持动态方法解析?实现一个动态添加方法的案例。
    答案:

    • 动态方法解析
      • 使用 resolveInstanceMethod:resolveClassMethod: 动态添加方法。
      • 示例:
        @implementation MyClass
        void dynamicMethod(id self, SEL _cmd) {
        NSLog(@"Dynamic method called");
        }
        + (BOOL)resolveInstanceMethod:(SEL)sel {
        if (sel == @selector(dynamicMethod)) {
        class_addMethod([self class], sel, (IMP)dynamicMethod, "v@:");
        return YES;
        }
        return [super resolveInstanceMethod:sel];
        }
        @end
    • 高级点:探讨 IMP 类型和方法签名编码(如 v@: 表示 void 返回、id 和 SEL 参数)。
  2. 消息转发机制的完整流程?如何优化性能?
    答案:

    • 流程
      1. resolveInstanceMethod::尝试动态添加方法。
      2. forwardingTargetForSelector::转发给其他对象。
      3. methodSignatureForSelector:forwardInvocation::自定义转发逻辑。
    • 优化
      • 优先使用 forwardingTargetForSelector:,避免昂贵的 NSInvocation
      • 缓存方法签名,减少运行时开销。
    • 示例
      @implementation Proxy
      - (id)forwardingTargetForSelector:(SEL)aSelector {
      return self.target; // 转发给 target 对象
      }
      @end
  3. 如何使用 Runtime 实现 AOP(面向切面编程)?
    答案:

    • 使用 method swizzling 拦截方法,插入切面逻辑。
    • 示例(记录方法调用时间):
      @implementation UIViewController (AOP)
      + (void)load {
      Method original = class_getInstanceMethod(self, @selector(viewDidLoad));
      Method swizzled = class_getInstanceMethod(self, @selector(swizzled_viewDidLoad));
      method_exchangeImplementations(original, swizzled);
      }
      - (void)swizzled_viewDidLoad {
      CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
      [self swizzled_viewDidLoad]; // 调用原方法
      NSLog(@"viewDidLoad took %f ms", (CFAbsoluteTimeGetCurrent() - start) * 1000);
      }
      @end
    • :多线程下的 swizzling 需加锁;确保方法存在;避免父类/子类冲突。
  4. KVO 的实现原理?如何手动实现 KVO?
    答案:

    • 原理
      • KVO 通过 Runtime 动态创建子类(NSKVONotifying_ 前缀),重写 setter 方法,触发通知。
    • 手动实现
      • 使用 objc_setAssociatedObject 存储观察者。
      • 重写 setter 方法,调用观察者回调。
      • 示例:
        @implementation MyObject
        - (void)setName:(NSString *)name {
        [self willChangeValueForKey:@"name"];
        objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_RETAIN);
        [self didChangeValueForKey:@"name"];
        }
        @end
    • 高级点:分析 NSKeyValueObserving 的内部实现,探讨性能瓶颈。
  5. 如何使用 Runtime 实现一个简单的依赖注入框架?
    答案:

    • 使用 objc_getAssociatedObjectobjc_setAssociatedObject 动态绑定依赖。
    • 示例:
      @protocol Service <NSObject>
      - (void)perform;
      @end
      @implementation MyClass
      - (void)setService:(id<Service>)service {
      objc_setAssociatedObject(self, @selector(service), service, OBJC_ASSOCIATION_RETAIN);
      }
      - (id<Service>)service {
      return objc_getAssociatedObject(self, @selector(service));
      }
      @end
    • 高级点:结合 Protocol 和 Runtime 实现类型安全的依赖注入。

3. 多线程

  1. 如何设计一个高性能的多线程任务调度系统?
    答案:

    • 架构
      • 使用 NSOperationQueue 管理任务,支持优先级和依赖。
      • 结合 GCD 的串行/并发队列,优化任务分配。
      • 使用 DispatchSemaphore 控制并发上限。
    • 示例
      NSOperationQueue *queue = [[NSOperationQueue alloc] init];
      queue.maxConcurrentOperationCount = 4;
      NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
      // 任务 1
      }];
      NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
      // 任务 2
      }];
      [op2 addDependency:op1];
      [queue addOperations:@[op1, op2] waitUntilFinished:NO];
    • 高级点:分析 GCD 的 libdispatch 源码,探讨线程池管理和 QoS 优化。
  2. dispatch_once 的底层实现?如何替代?
    答案:

    • 实现dispatch_once 使用原子操作(atomic_compare_exchange)确保单次执行。
    • 替代
      • 使用 static 变量和 std::once_flag(C++)。
      • 示例:
        static id instance;
        static std::once_flag flag;
        std::call_once(flag, ^{
        instance = [[MyClass alloc] init];
        });
    • 高级点:探讨 dispatch_once_t 的内存结构和性能优化。
  3. 如何在高并发场景下避免死锁?
    answers:

    • 避免嵌套锁,使用 dispatch_async 替代同步调用。
    • 使用 NSLockdispatch_semaphore 控制资源访问。
    • 示例:
      dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
      dispatch_async(queue, ^{
      dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
      // 访问共享资源
      dispatch_semaphore_signal(semaphore);
      });
    • 高级点:分析死锁的调试方法(如 Thread Sanitizer)。
  4. NSOperationQueue 如何实现优先级调度?
    答案:

    • 设置 NSOperationqueuePriorityqualityOfService
    • 示例:
      NSOperation *op = [NSBlockOperation blockOperationWithBlock:^{
      // 任务
      }];
      op.queuePriority = NSOperationQueuePriorityHigh;
      [queue addOperation:op];
    • 高级点:探讨 NSOperationQueue 的线程池管理和调度算法。
  5. 如何在 Objective-C 中实现线程安全的单例?
    答案:

    • 使用 dispatch_once 确保初始化线程安全。
    • 示例:
      @implementation Singleton
      + (instancetype)shared {
      static Singleton *instance = nil;
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{
      instance = [[Singleton alloc] init];
      });
      return instance;
      }
      @end
    • 高级点:分析多线程下的单例初始化性能瓶颈。

二、Swift 高级

1. struct vs class

  1. struct 和 class 在性能优化中的选择?如何结合 Copy-on-Write 优化 struct?
    答案:

    • 选择
      • struct:适合小数据量、值语义场景(如模型),栈分配性能高。
      • class:适合复杂对象、需要继承或引用语义(如视图控制器)。
    • Copy-on-Write
      • struct 内部使用引用类型(如 Array)时,需实现 COW 避免不必要复制。
      • 示例:
        final class Ref<T> {
        var value: T
        init(_ value: T) { self.value = value }
        }
        struct MyArray {
        private var ref: Ref<[Int]>
        var values: [Int] {
        get { ref.value }
        set {
        if !isKnownUniquelyReferenced(&ref) {
        ref = Ref(newValue)
        } else {
        ref.value = newValue
        }
        }
        }
        }
    • 高级点:分析 struct 的值语义对线程安全的影响。
  2. struct 和 class 在并发环境下的行为差异?
    answers:

    • struct:值类型,复制后独立,天然线程安全。
    • class:引用类型,需使用 actor 或锁机制(如 NSLock)保护共享状态。
    • 示例:
      actor SafeCounter {
      var value = 0
      func increment() { value += 1 }
      }
    • 高级点:探讨 Swift 6 数据竞争检查对 struct 和 class 的影响。
  3. 如何在 struct 中实现类似 class 的继承行为?
    答案:

    • 使用 Protocol 和默认实现模拟继承。
    • 示例:
      protocol Animal {
      func makeSound()
      }
      extension Animal {
      func makeSound() { print("Generic sound") }
      }
      struct Dog: Animal {
      func makeSound() { print("Woof") }
      }
    • 高级点:分析 Protocol 扩展与 class 继承的性能差异。

2. Optional

  1. Optional 的高级用法(如 map、flatMap、compactMap)?
    答案:

    • map:转换 Optional 的值。
    • flatMap:处理嵌套 Optional。
    • compactMap:过滤 nil 并转换。
    • 示例:
      let optionalString: String? = "123"
      let number = optionalString.map { Int($0) } // Optional<Int>?
      let flattened = optionalString.flatMap { Int($0) } // Int?
      let array = ["1", "a", "2"].compactMap { Int($0) } // [1, 2]
    • 高级点:探讨 Optional 的 monadic 性质和编译器优化。
  2. 如何自定义 Optional 的行为(如自定义解包逻辑)?
    答案:

    • 通过扩展 Optional 添加方法。
    • 示例:
      extension Optional {
      func unwrap(orDefault defaultValue: Wrapped) -> Wrapped {
      return self ?? defaultValue
      }
      }
      let value: String? = nil
      print(value.unwrap(orDefault: "default")) // 输出 "default"
    • 高级点:分析 Optional 的内存布局和性能开销。

3. 协议 & 泛型

  1. 如何设计一个类型安全的泛型网络层?
    答案:

    • 使用泛型和 Protocol 约束返回值类型。
    • 示例:
      protocol APIEndpoint {
      associatedtype Response: Decodable
      var url: URL { get }
      }
      struct UserEndpoint: APIEndpoint {
      typealias Response = User
      var url: URL { URL(string: "https://api.example.com/user")! }
      }
      class NetworkLayer {
      func fetch<T: APIEndpoint>(_ endpoint: T) async throws -> T.Response {
      let (data, _) = try await URLSession.shared.data(from: endpoint.url)
      return try JSONDecoder().decode(T.Response.self, from: data)
      }
      }
    • 高级点:探讨泛型约束对编译器类型推断的影响。
  2. associatedtype 和 where 子句的高级用法?
    答案:

    • associatedtype:定义协议中的类型占位符。
    • where 子句:约束关联类型或泛型。
    • 示例:
      protocol Container {
      associatedtype Item where Item: Equatable
      func add(_ item: Item)
      }
      struct Stack<T: Equatable>: Container {
      typealias Item = T
      var items: [T] = []
      func add(_ item: T) { items.append(item) }
      }
    • 高级点:分析 PAT(Protocol with Associated Types)的动态分发问题。
  3. 如何实现 Protocol 的动态分发?
    answers:

    • 使用 Self 要求或 @objc 协议支持动态分发。
    • 示例:
      @objc protocol DynamicProtocol {
      @objc func perform()
      }
      class MyClass: DynamicProtocol {
      @objc func perform() { print("Performed") }
      }
    • 高级点:探讨 objc 协议与 Swift 原生协议的性能差异。

4. 闭包

  1. 如何优化闭包在高频场景下的性能?
    答案:

    • 减少捕获变量,降低内存开销。
    • 使用 @inlinable@inline(__always) 优化编译器内联。
    • 示例:
      @inlinable func execute(_ closure: () -> Void) {
      closure()
      }
    • 高级点:分析闭包捕获的内存分配(堆 vs 栈)。
  2. 逃逸闭包和非逃逸闭包的性能差异?
    answers:

    • 非逃逸闭包:编译器可内联,栈分配,性能更高。
    • 逃逸闭包:需堆分配,增加引用计数开销。
    • 高级点:探讨逃逸闭包的逃逸分析(Escape Analysis)。
  3. 如何在闭包中实现复杂的状态管理?
    答案:

    • 使用捕获列表和类包装状态。
    • 示例:
      class State {
      var value = 0
      }
      let state = State()
      let closure = { [state] in state.value += 1 }
    • 高级点:分析闭包状态管理与 actor 的对比。

5. 多线程(Swift)

  1. 如何在 Swift 6 中确保数据竞争安全?
    answers:

    • 使用 actor 隔离状态。
    • 实现 Sendable 协议,确保数据跨并发上下文安全。
    • 示例:
      actor DataStore: Sendable {
      private var data: [String: Int] = [:]
      func set(_ key: String, value: Int) { data[key] = value }
      }
    • 高级点:分析 Swift 6 的并发检查器(Concurrency Checker)。
  2. async/await 如何与 Combine 集成?
    answers:

    • 使用 FuturePassthroughSubject 桥接。
    • 示例:
      import Combine
      func fetchAsync() async throws -> Int {
      return 42
      }
      let publisher = Future<Int, Error> { promise in
      Task {
      do { promise(.success(try await fetchAsync())) }
      catch { promise(.failure(error)) }
      }
      }
    • 高级点:探讨 Combine 与 async/await 的性能差异。
  3. 如何实现一个自定义并发调度器?
    answers:

    • 使用 DispatchQueueRunLoop 实现调度。
    • 示例:
      struct CustomScheduler {
      let queue = DispatchQueue(label: "com.custom.scheduler")
      func schedule(_ task: @escaping () -> Void) {
      queue.async(execute: task)
      }
      }
    • 高级点:分析 Swift Concurrency 的 Continuation 机制。

6. Codable

  1. 如何在 Codable 中处理复杂嵌套 JSON 和动态键?
    answers:

    • 使用 unkeyedContainersingleValueContainer 解码动态结构。
    • 示例(动态键):
      struct DynamicResponse: Decodable {
      let data: [String: Any]
      init(from decoder: Decoder) throws {
      let container = try decoder.container(keyedBy: CodingKeys.self)
      data = try container.decode([String: Any].self, forKey: .data)
      }
      private enum CodingKeys: String, CodingKey { case data }
      }
    • 高级点:探讨 JSONSerializationCodable 的性能对比。
  2. 如何在 Codable 中实现多态解码?
    answers:

    • 使用枚举和 Codable 实现多态。
    • 示例:
      enum Animal: Codable {
      case dog(name: String)
      case cat(age: Int)
      private enum CodingKeys: String, CodingKey { case type, data }
      init(from decoder: Decoder) throws {
      let container = try decoder.container(keyedBy: CodingKeys.self)
      let type = try container.decode(String.self, forKey: .type)
      switch type {
      case "dog": self = .dog(name: try container.decode(String.self, forKey: .data))
      case "cat": self = .cat(age: try container.decode(Int.self, forKey: .data))
      default: throw DecodingError.dataCorruptedError(forKey: .type, in: container, debugDescription: "Invalid type")
      }
      }
      func encode(to encoder: Encoder) throws {
      var container = encoder.container(keyedBy: CodingKeys.self)
      switch self {
      case .dog(let name):
      try container.encode("dog", forKey: .type)
      try container.encode(name, forKey: .data)
      case .cat(let age):
      try container.encode("cat", forKey: .type)
      try container.encode(age, forKey: .data)
      }
      }
      }
    • 高级点:分析多态解码的性能开销和替代方案。

7. 内存管理(Swift)

  1. 如何在 Swift 中实现自定义引用计数机制?
    answers:

    • 使用 ManagedBuffer 或自定义引用计数类。
    • 示例:
      final class RefCounted<T> {
      private var count = 0
      var value: T
      init(_ value: T) { self.value = value }
      func retain() { count += 1 }
      func release() { count -= 1; if count == 0 { /* 释放 */ } }
      }
    • 高级点:对比 ARC 和手动引用计数的内存管理效率。
  2. 如何在 Swift 中调试复杂循环引用?
    answers:

    • 使用 Instruments 的 Leaks 工具。
    • 注入 deinit 日志,跟踪对象生命周期。
    • 使用 swift_mangled_name 检查编译器生成的符号。
    • 高级点:分析 Swift ARC 的 objc_retainobjc_release 实现。

8. 响应式编程

  1. Combine 和 RxSwift 的高级集成场景(如与 UIKit/SwiftUI 结合)?
    answers:

    • Combine
      • 使用 @PublishedObservableObject 驱动 SwiftUI。
      • 示例:
        class ViewModel: ObservableObject {
        @Published var text = ""
        }
        struct ContentView: View {
        @ObservedObject var viewModel = ViewModel()
        var body: some View {
        Text(viewModel.text)
        }
        }
    • RxSwift
      • 使用 RxCocoa 绑定 UIKit 控件。
      • 示例:
        import RxSwift
        import RxCocoa
        textField.rx.text.orEmpty
        .bind(to: label.rx.text)
        .disposed(by: disposeBag)
    • 高级点:分析 Combine 和 RxSwift 在内存管理和性能上的差异。
  2. 如何实现一个自定义 Combine Operator?
    answers:

    • 扩展 Publisher 定义自定义操作符。
    • 示例:
      extension Publisher {
      func customMap<T>(_ transform: @escaping (Output) -> T) -> Publishers.Map<Self, T> {
      return map(transform)
      }
      }
    • 高级点:分析 Publishers 的内部实现(如 Inner 类)。

三、iOS 开发高级

1. UI & 动画

  1. 如何优化复杂 UITableView 的性能?
    answers:

    • 优化
      • 使用 dequeueReusableCell 复用单元格。
      • 异步加载图片(SDWebImage)。
      • 缓存行高(estimatedHeightForRow)。
      • 避免离屏渲染(减少 cornerRadiusshadow)。
    • 高级点:分析 UITableView 的重用机制和 CATiledLayer 的应用。
  2. 如何实现复杂 SwiftUI 动画(如多阶段动画)?
    answers:

    • 使用 withAnimationAnimation 组合。
    • 示例:
      struct ContentView: View {
      @State private var scale = 1.0
      var body: some View {
      Circle()
      .scaleEffect(scale)
      .onTapGesture {
      withAnimation(.spring()) {
      scale = 1.5
      } completion: {
      withAnimation(.easeOut) { scale = 1.0 }
      }
      }
      }
      }
    • 高级点:探讨 SwiftUI 的 Animatable 协议和自定义动画曲线。
  3. 如何在 UIKit 中实现自定义转场动画?
    answers:

    • 实现 UIViewControllerAnimatedTransitioningUIViewControllerTransitioningDelegate
    • 示例:
      class CustomTransition: NSObject, UIViewControllerAnimatedTransitioning {
      func transitionDuration(using context: UIViewControllerContextTransitioning?) -> TimeInterval {
      return 0.5
      }
      func animateTransition(using context: UIViewControllerContextTransitioning) {
      guard let toView = context.view(forKey: .to) else { return }
      context.containerView.addSubview(toView)
      toView.alpha = 0
      UIView.animate(withDuration: transitionDuration(using: context), animations: {
      toView.alpha = 1
      }, completion: { _ in
      context.completeTransition(true)
      })
      }
      }
    • 高级点:分析 CAAnimation 的底层实现。

2. 网络

  1. 如何设计一个支持离线缓存和断点续传的网络层?
    answers:

    • 使用 URLSessionDownloadTask 支持断点续传。
    • 使用 FileManager 缓存响应。
    • 示例:
      class DownloadManager {
      func download(with url: URL, resumeData: Data?) async throws -> URL {
      let task = resumeData == nil ?
      URLSession.shared.downloadTask(with: url) :
      URLSession.shared.downloadTask(withResumeData: resumeData!)
      return try await task.download()
      }
      }
      extension URLSessionDownloadTask {
      func download() async throws -> URL {
      return try await withCheckedThrowingContinuation { continuation in
      resume()
      // 实现 delegate 监听进度和完成
      }
      }
      }
    • 高级点:分析 URLSessionURLSessionTask 状态机。
  2. 如何实现一个支持 HTTP/2 的网络层?
    answers:

    • 使用 URLSessionhttp/2 支持(iOS 9+ 默认启用)。
    • 配置 URLSessionConfigurationhttpShouldUsePipelining
    • 高级点:探讨 HTTP/2 的多路复用和服务器推送。

3. 数据库

  1. 如何优化 Core Data 在高并发场景下的性能?
    answers:

    • 使用多 NSManagedObjectContext(主线程和后台线程)。
    • 示例:
      let container = NSPersistentContainer(name: "Model")
      container.loadPersistentStores { _, _ in
      let backgroundContext = container.newBackgroundContext()
      backgroundContext.perform {
      // 后台操作
      try? backgroundContext.save()
      }
      }
    • 高级点:分析 Core Data 的 NSMergePolicy 和冲突解决。
  2. 如何实现一个自定义 ORM 框架?
    answers:

    • 使用 Codable 和 SQLite 实现轻量级 ORM。
    • 示例:
      protocol Model: Codable {
      static var tableName: String { get }
      }
      class ORM {
      func save<T: Model>(_ model: T) throws {
      let data = try JSONEncoder().encode(model)
      // 保存到 SQLite
      }
      }
    • 高级点:探讨 ORM 的性能瓶颈和索引优化。

4. 性能优化

  1. 如何使用 Instruments 分析复杂性能问题?
    answers:

    • Leaks:检测内存泄漏。
    • Time Profiler:分析 CPU 热点。
    • Core Animation:检查离屏渲染。
    • 高级点:结合 os_signpost 自定义性能埋点。
  2. 如何优化 App 启动时间?
    answers:

    • 延迟非必要初始化。
    • 异步加载资源。
    • 使用 dyld 分析动态链接时间。
    • 高级点:探讨 dyld3dyld4 的启动优化。

5. 架构 & 设计模式

  1. 如何设计一个模块化的 iOS 架构?
    answers:

    • 使用组件化(如 SPM 或 CocoaPods)。
    • 分层架构:UI 层、业务逻辑层、数据层。
    • 示例(路由):
      protocol Router {
      func route(to destination: String, parameters: [String: Any])
      }
      class AppRouter: Router {
      func route(to destination: String, parameters: [String: Any]) {
      // 动态加载模块
      }
      }
    • 高级点:分析模块化的动态加载和依赖管理。
  2. 如何实现一个依赖注入容器?
    answers:

    • 使用 Protocol 和工厂模式。
    • 示例:
      protocol Service {
      func perform()
      }
      class DIContainer {
      private var services: [String: Any] = [:]
      func register<T>(_ type: T.Type, factory: @escaping () -> T) {
      services["\(T.self)"] = factory
      }
      func resolve<T>(_ type: T.Type) -> T? {
      return (services["\(T.self)"] as? () -> T)?()
      }
      }
    • 高级点:探讨 DI 容器的线程安全和生命周期管理。

四、高频 Swift 面试题(扩展)

1. struct vs class

  • 如何在 struct 中实现深拷贝?
    • 使用 Codable 或手动复制。
    • 示例:
      struct DeepCopy: Codable {
      var data: [Int]
      func copy() -> DeepCopy {
      try! JSONDecoder().decode(DeepCopy.self, from: JSONEncoder().encode(self))
      }
      }

2. Codable

  • 如何处理动态 JSON 结构?
    • 使用 AnyCodable 或自定义解码器。
  • 如何优化 Codable 的性能?
    • 缓存 JSONDecoder 实例,减少反射开销。

3. 多线程

  • 如何在 async/await 中实现超时机制?
    • 使用 withTimeout 或自定义 Task
    • 示例:
      func fetchWithTimeout() async throws -> Data {
      try await withTaskCancellationHandler {
      try await Task.sleep(nanoseconds: 5_000_000_000) // 5s 超时
      throw CancellationError()
      } operation: {
      return try await fetchData()
      }
      }

4. 内存管理

  • 如何在 Swift 中实现自定义内存分配器?
    • 使用 UnsafeMutablePointerUnsafeBufferPointer
    • 高级点:分析 Swift 的内存分配器(Swift Allocator)。

5. 响应式编程

  • 如何在 Combine 中实现自定义 Publisher?
    • 继承 Publisher 并实现 receive(subscriber:)
    • 示例:
      struct CustomPublisher: Publisher {
      typealias Output = Int
      typealias Failure = Never
      func receive<S: Subscriber>(subscriber: S) where S.Input == Output, S.Failure == Failure {
      subscriber.receive(42)
      subscriber.receive(completion: .finished)
      }
      }

五、综合问题

  1. 设计一个支持插件化的 iOS 架构,动态加载模块。
    answers:

    • 使用 NSBundledlopen 动态加载。
    • 结合 Protocol 和 DI 实现模块解耦。
    • 高级点:分析 App Store 的动态加载限制。
  2. 如何实现一个支持 A/B 测试的网络层?
    answers:

    • 使用配置中心动态切换 API。
    • 示例:
      class ABTestingNetwork {
      var endpoint: APIEndpoint
      init(config: [String: String]) {
      endpoint = config["variant"] == "A" ? EndpointA() : EndpointB()
      }
      }
    • 高级点:探讨 A/B 测试的数据收集和分析。
  3. 如何在 SwiftUI 中实现复杂的状态管理?
    answers:

    • 使用 ObservableObjectEnvironmentObject
    • 示例:
      class AppState: ObservableObject {
      @Published var user: User?
      }
      struct ContentView: View {
      @EnvironmentObject var state: AppState
      var body: some View {
      Text(state.user?.name ?? "No user")
      }
      }
    • 高级点:分析 SwiftUI 的状态更新机制(diffing 算法)。
  4. 如何分析和优化第三方库(如 Alamofire)的性能?
    answers:

    • 使用 Instruments 分析网络请求和内存使用。
    • 检查源码中的锁机制和异步操作。
    • 高级点:探讨 Alamofire 的 SessionInterceptor 实现。

六、总结

  • Objective-C:深入 Runtime、内存管理(MRC/ARC)、多线程(GCD/NSOperation)、动态特性(KVO/Method Swizzling)。
  • Swift:深入 struct/class、Codable、Optional、多线程(async/await)、内存管理(ARC)、响应式编程(Combine/RxSwift)。
  • iOS 开发:高级 UI(SwiftUI/UIKit)、网络(HTTP/2、断点续传)、数据库(Core Data/ORM)、性能优化(Instruments)、架构设计(模块化/DI)。
支持一下
扫一扫,支持forsigner
  • 微信扫一扫
  • 支付宝扫一扫