iOS性能优化:OC和Swift实战指南

常见的iOS性能优化点,比如内存管理、UI优化、多线程处理、网络请求优化、启动优化、I/O操作、图像处理、算法优化、工具使用等。

一、内存优化

1. 循环引用处理

  • 原理:对象之间的强引用导致无法释放,内存泄漏。

  • Objective-C

    • 使用 __weak__unsafe_unretained(需谨慎)打破循环:

      ini 复制代码
      __weak typeof(self) weakSelf = self;
      self.block = ^{
          // 弱引用避免循环
          [weakSelf doSomething];
      };
    • NSTimer 使用 NSProxyweak 委托模式。

  • Swift

    • 使用 [weak self][unowned self] 捕获列表:

      swift 复制代码
      self.block = { [weak self] in
          guard let self = self else { return }
          self.doSomething()
      }
    • unowned 适用于生命周期相同或更短的场景(如父子关系)。


2. 自动释放池(Autorelease Pool)

  • 原理:批量创建临时对象时,及时释放内存。

  • Objective-C

    ini 复制代码
    @autoreleasepool {
        for (int i = 0; i < 100000; i++) {
            NSString *temp = [NSString stringWithFormat:@"%d", i];
            // 临时对象会被及时释放
        }
    }
  • Swift

    rust 复制代码
    autoreleasepool {
        for i in 0..<100000 {
            let temp = "(i)"
            // 临时对象在块结束时释放
        }
    }
  • 适用场景:大量临时对象生成(如解析 JSON 数组、图像处理)。


二、UI 性能优化

1. 避免离屏渲染(Offscreen Rendering)

  • 原理:离屏渲染(如圆角、阴影)触发 GPU 额外绘制,导致卡顿。

  • 优化方法

    • 预渲染圆角

      • Objective-C

        ini 复制代码
        // 使用 Core Graphics 提前绘制圆角
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0);
        [[UIBezierPath bezierPathWithRoundedRect:view.bounds cornerRadius:10] addClip];
        [image drawInRect:view.bounds];
        UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        view.layer.contents = (id)roundedImage.CGImage;
      • Swift

        ini 复制代码
        let renderer = UIGraphicsImageRenderer(size: view.bounds.size)
        let roundedImage = renderer.image { context in
            UIBezierPath(roundedRect: view.bounds, cornerRadius: 10).addClip()
            image.draw(in: view.bounds)
        }
        view.layer.contents = roundedImage.cgImage
    • 避免 shouldRasterize:除非复用图层,否则会触发离屏渲染。


2. Cell 复用与轻量化

  • 原理:避免频繁创建/销毁 Cell,减少 CPU 和内存压力。

  • Objective-C

    ini 复制代码
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        // 复用 Cell
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellID"];
        if (!cell) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CellID"];
        }
        // 轻量配置(避免复杂计算)
        cell.textLabel.text = [self.dataArray[indexPath.row] title];
        return cell;
    }
  • Swift

    swift 复制代码
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CellID", for: indexPath)
        cell.textLabel?.text = dataArray[indexPath.row].title
        return cell
    }
  • 优化点

    • 避免在 cellForRow 中执行耗时操作(如网络请求)。
    • 使用 prepareForReuse 清理旧数据。

三、多线程优化

1. 主线程任务最小化

  • 原理:主线程阻塞导致 UI 卡顿(16ms 内未完成一帧绘制)。

  • Objective-C

    ini 复制代码
    // 将耗时操作放到后台线程
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData *data = [NSData dataWithContentsOfURL:url];
        dispatch_async(dispatch_get_main_queue(), ^{
            self.imageView.image = [UIImage imageWithData:data];
        });
    });
  • Swift

    csharp 复制代码
    DispatchQueue.global(qos: .userInitiated).async {
        let data = try? Data(contentsOf: url)
        DispatchQueue.main.async {
            self.imageView.image = UIImage(data: data!)
        }
    }

2. 线程安全与锁优化

  • Objective-C

    • @synchronized 实现简单但性能较低:

      objc

      java 复制代码
      @synchronized(self) {
          // 临界区
      }
    • 高性能场景使用 os_unfair_lock(替代已废弃的 OSSpinLock):

      ini 复制代码
      #include <os/lock.h>
      os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
      os_unfair_lock_lock(&lock);
      // 临界区
      os_unfair_lock_unlock(&lock);
  • Swift

    • 使用 NSLockDispatchQueue 屏障:

      arduino 复制代码
      let queue = DispatchQueue(label: "com.example.threadSafe", attributes: .concurrent)
      queue.async(flags: .barrier) {
          // 写操作(独占访问)
      }

四、网络优化

1. 请求合并与缓存

  • Objective-C

    objectivec 复制代码
    // 使用 NSURLSession 的缓存策略
    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:10];
  • Swift

    less 复制代码
    let request = URLRequest(url: url, cachePolicy: .returnCacheDataElseLoad, timeoutInterval: 10)
  • 优化点

    • 减少重复请求(如短时间内多次刷新)。
    • 使用 HTTP/2 多路复用降低连接开销。

五、启动时间优化

1. 冷启动阶段优化

  • 原理 :减少 main() 函数之前的加载时间(T1)和首帧渲染时间(T2)。

  • Objective-C

    • 减少动态库数量,合并 Category。
    • 避免在 +load 方法中执行代码。
  • Swift

    • 使用 @UIApplicationMain 减少启动代码。

    • 延迟非必要初始化:

      javascript 复制代码
      DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
          // 延迟初始化第三方 SDK
      }

六、I/O 优化

1. 文件读写异步化

  • Objective-C

    arduino 复制代码
    dispatch_io_t channel = dispatch_io_create_with_path(DISPATCH_IO_STREAM, [path UTF8String], O_RDONLY, 0, queue, ^(int error) {});
    dispatch_io_read(channel, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t data, int error) {});
  • Swift

    arduino 复制代码
    let queue = DispatchQueue.global(qos: .background)
    DispatchIO.read(fromFileDescriptor: fd, queue: queue) { data, _ in
        // 处理数据
    }

七、图像处理优化

1. 异步解码与降采样

  • Objective-C

    objectivec 复制代码
    // 使用 ImageIO 进行降采样
    CGImageSourceRef source = CGImageSourceCreateWithURL((__bridge CFURLRef)url, NULL);
    CGImageRef imageRef = CGImageSourceCreateImageAtIndex(source, 0, (__bridge CFDictionaryRef)@{(id)kCGImageSourceThumbnailMaxPixelSize: @(300)});
    UIImage *image = [UIImage imageWithCGImage:imageRef];
  • Swift

    swift 复制代码
    let source = CGImageSourceCreateWithURL(url as CFURL, nil)!
    let options: [CFString: Any] = [kCGImageSourceThumbnailMaxPixelSize: 300]
    let imageRef = CGImageSourceCreateThumbnailAtIndex(source, 0, options as CFDictionary)!
    let image = UIImage(cgImage: imageRef)

八、算法与数据结构

1. 高效遍历与查询

  • Objective-C

    • 使用 NSDictionary 替代 NSArray 快速查找(O(1) vs O(n))。
  • Swift

    • 使用 lazy 延迟计算集合:

      ini 复制代码
      let filteredData = data.lazy.filter { $0.isValid }.map { $0.value }
    • 使用 ContiguousArray 提升性能(连续内存布局)。


九、工具使用

1. Instruments 分析

  • Time Profiler:定位 CPU 热点函数。
  • Allocations:分析内存分配类型和泄漏。
  • Core Animation:检测离屏渲染和帧率。

十、Swift 特有优化

1. 减少动态派发

  • 使用 finalprivate 修饰类或方法:

    swift 复制代码
    final class NetworkManager {
        private func fetchData() { ... }
    }

2. 值类型优先

  • 使用结构体(struct)替代类(class)减少引用计数开销:

    kotlin 复制代码
    struct Point {
        var x: Double
        var y: Double
    }

总结

  • Objective-C 优化重点:手动内存管理、@autoreleasepool、避免 performSelector 潜在泄漏。
  • Swift 优化重点:值类型、协议扩展、DispatchQueue 和现代语法(如 Result 类型)。
  • 通用原则:减少主线程阻塞、复用资源、异步化耗时操作、利用工具分析瓶颈。
相关推荐
我有医保我先冲2 小时前
SQL复杂查询与性能优化:医药行业ERP系统实战指南
数据库·sql·性能优化
anda01093 小时前
11-leveldb compact原理和性能优化
java·开发语言·性能优化
爱吃馒头爱吃鱼3 小时前
QML编程中的性能优化二
开发语言·qt·学习·性能优化
桂月二二7 小时前
Vue3服务端渲染深度解析:从Nuxt3架构到性能优化实战
性能优化·架构
清晨細雨7 小时前
UniApp集成极光推送详细教程
android·ios·uni-app·极光推送
我有医保我先冲7 小时前
SQL复杂查询与性能优化全攻略
数据库·sql·性能优化
庸俗今天不摸鱼8 小时前
【万字总结】前端全方位性能优化指南(九)——FSP(First Screen Paint)像素级分析、RUM+合成监控、Lighthouse CI
前端·性能优化
Light609 小时前
深入剖析JavaScript多态:从原理到高性能实践
javascript·性能优化·多态·类型推断·代码复用·v8引擎
ii_best12 小时前
iOS 按键越狱脚本支持一键新机软件教程
ios
写代码写到手抽筋13 小时前
C++多线程的性能优化
java·c++·性能优化