面试题答案
一键面试管理内存避免内存泄漏和提高性能
- 设置合适的容量限制:
- 使用
NSCache
的countLimit
属性来设置缓存中对象的最大数量。例如:
NSCache *cache = [[NSCache alloc] init]; cache.countLimit = 100; // 设置缓存最多容纳100个对象
- 这样当缓存中的对象数量达到限制时,
NSCache
会自动释放一些对象,有助于控制内存占用。
- 使用
- 设置合适的成本限制:
NSCache
还有totalCostLimit
属性,通过为每个缓存对象设置成本值,可以根据总成本来管理缓存。比如,对于图片缓存,大图片可以设置较高的成本值。- 给缓存对象设置成本值,假设缓存对象是
UIImage
,可以这样做:
UIImage *image = [UIImage imageNamed:@"bigImage"]; [cache setObject:image forKey:@"bigImageKey" cost:image.size.width * image.size.height];
- 当缓存的总成本超过
totalCostLimit
时,NSCache
会释放对象。
- 避免强引用循环:
- 确保缓存对象和其键之间不存在强引用循环。例如,如果键是自定义对象,要保证自定义对象不会强引用缓存对象。
- 及时清理缓存:
- 当某些数据不再需要缓存时,手动从缓存中移除。比如在视图控制器销毁时,移除相关的缓存数据:
- (void)dealloc { [cache removeObjectForKey:@"specificKey"]; }
- 使用自动释放池:
- 如果在缓存操作中有大量临时对象创建,可以使用自动释放池来及时释放这些对象,减少内存峰值。例如:
@autoreleasepool { for (int i = 0; i < 1000; i++) { NSString *key = [NSString stringWithFormat:@"key%d", i]; NSString *value = [NSString stringWithFormat:@"value%d", i]; [cache setObject:value forKey:key]; } }
多线程环境下使用NSCache的问题及解决办法
- 问题:
- 数据竞争:多个线程同时访问和修改
NSCache
可能导致数据不一致。例如,一个线程正在读取缓存对象,另一个线程同时移除该对象,可能会导致读取到已移除或不完整的数据。 - 内存管理问题:多线程并发操作可能会破坏
NSCache
内部的内存管理机制,导致意外的内存泄漏或过度释放。
- 数据竞争:多个线程同时访问和修改
- 解决办法:
- 使用锁:可以使用
NSLock
或@synchronized
来同步对NSCache
的访问。例如,使用NSLock
:
NSLock *cacheLock = [[NSLock alloc] init]; NSCache *cache = [[NSCache alloc] init]; - (void)setObject:(id)object forKey:(id<NSCopying>)key { [cacheLock lock]; [cache setObject:object forKey:key]; [cacheLock unlock]; } - (id)objectForKey:(id)key { [cacheLock lock]; id result = [cache objectForKey:key]; [cacheLock unlock]; return result; }
- 使用队列:使用
dispatch_queue_t
来串行化对NSCache
的操作。例如:
dispatch_queue_t cacheQueue = dispatch_queue_create("com.example.cacheQueue", DISPATCH_QUEUE_SERIAL); NSCache *cache = [[NSCache alloc] init]; dispatch_async(cacheQueue, ^{ [cache setObject:object forKey:key]; }); dispatch_sync(cacheQueue, ^{ id result = [cache objectForKey:key]; });
- 使用
NSCache
的线程安全替代品:在某些情况下,可以考虑使用线程安全的集合类,如NSMutableDictionary
结合锁来实现类似缓存功能,不过需要自行处理内存管理等方面与NSCache
的差异。
- 使用锁:可以使用