首页 > 移动开发 > IOS > iOS应用性能优化全面指南:从内存管理到工具使用
常见的iOS性能优化点,比如内存管理、UI优化、多线程处理、网络请求优化、启动优化、I/O操作、图像处理、算法优化、工具使用等。
原理:对象之间的强引用导致无法释放,内存泄漏。
Objective-C:
使用
__weak 或
__unsafe_unretained(需谨慎)打破循环:
__weak typeof(self) weakSelf = self;
self.block = ^{
// 弱引用避免循环
[weakSelf doSomething];
};对
NSTimer 使用
NSProxy 或
weak 委托模式。
Swift:
使用
[weak self] 或
[unowned self] 捕获列表:
self.block = { [weak self] in
guard let self = self else { return }
self.doSomething()
}
unowned 适用于生命周期相同或更短的场景(如父子关系)。
原理:批量创建临时对象时,及时释放内存。
Objective-C:
@autoreleasepool {
for (int i = 0; i < 100000; i++) {
NSString *temp = [NSString stringWithFormat:@"%d", i];
// 临时对象会被及时释放
}
}
autoreleasepool {
for i in 0..<100000 {
let temp = "(i)"
// 临时对象在块结束时释放
}
}
原理:离屏渲染(如圆角、阴影)触发 GPU 额外绘制,导致卡顿。
优化方法:
Objective-C:
// 使用 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:
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.cgImageshouldRasterize:除非复用图层,否则会触发离屏渲染。原理:避免频繁创建/销毁 Cell,减少 CPU 和内存压力。
Objective-C:
- (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;
}
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 清理旧数据。原理:主线程阻塞导致 UI 卡顿(16ms 内未完成一帧绘制)。
Objective-C:
// 将耗时操作放到后台线程
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];
});
});
DispatchQueue.global(qos: .userInitiated).async {
let data = try? Data(contentsOf: url)
DispatchQueue.main.async {
self.imageView.image = UIImage(data: data!)
}
}
@synchronized 实现简单但性能较低:
@synchronized(self) {
// 临界区
}高性能场景使用
os_unfair_lock(替代已废弃的
OSSpinLock):
#include <os/lock.h> os_unfair_lock lock = OS_UNFAIR_LOCK_INIT; os_unfair_lock_lock(&lock); // 临界区 os_unfair_lock_unlock(&lock);
使用
NSLock 或
DispatchQueue 屏障:
let queue = DispatchQueue(label: "com.example.threadSafe", attributes: .concurrent)
queue.async(flags: .barrier) {
// 写操作(独占访问)
}// 使用 NSURLSession 的缓存策略 NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:10];
let request = URLRequest(url: url, cachePolicy: .returnCacheDataElseLoad, timeoutInterval: 10)
原理:减少
main() 函数之前的加载时间(T1)和首帧渲染时间(T2)。
Objective-C:
+load 方法中执行代码。Swift:
使用
@UIApplicationMain 减少启动代码。
延迟非必要初始化:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
// 延迟初始化第三方 SDK
}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) {});
let queue = DispatchQueue.global(qos: .background)
DispatchIO.read(fromFileDescriptor: fd, queue: queue) { data, _ in
// 处理数据
}
// 使用 ImageIO 进行降采样
CGImageSourceRef source = CGImageSourceCreateWithURL((__bridge CFURLRef)url, NULL);
CGImageRef imageRef = CGImageSourceCreateImageAtIndex(source, 0, (__bridge CFDictionaryRef)@{(id)kCGImageSourceThumbnailMaxPixelSize: @(300)});
UIImage *image = [UIImage imageWithCGImage:imageRef];
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)
NSDictionary 替代
NSArray 快速查找(O(1) vs O(n))。使用
lazy 延迟计算集合:
let filteredData = data.lazy.filter { $0.isValid }.map { $0.value }使用
ContiguousArray 提升性能(连续内存布局)。
此外,克魔助手(KeyMob)也是一款专为iOS开发设计的综合工具,提供性能监控、文件管理、日志分析等功能。KeyMob可以实时监控CPU、GPU、内存、FPS、网络、能耗等性能指标,支持分应用和小程序监控,并通过图表展示数据,帮助开发者更便捷地分析和优化应用性能。
final 和
private 修饰类或方法:final class NetworkManager {
private func fetchData() { ... }
}
struct)替代类(
class)减少引用计数开销:struct Point {
var x: Double
var y: Double
}
@autoreleasepool、避免
performSelector 潜在泄漏。DispatchQueue 和现代语法(如
Result 类型)。来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70047439/viewspace-3172516/ ,如需转载,请注明出处,否则将追究法律责任。