我有一些使用NSPurgeableData
的代码正常工作,直到我的机器的内存使用量开始变高,此时我开始抛出异常。这是例外中的消息:
***由于未捕获的异常'NSGenericException'终止应用程序,原因:'*** - [NSPurgeableData length]:在成功的-beginContentAccess和-endContentAccess调用之外访问。'
这是我的代码的本质:
- (NSImage *)imageProperty {
if (!self.purgeableImage || ![self.purgeableImage beginContentAccess]) {
if (!self.purgeableImage) {
self.purgeableImage = [NSPurgeableData data];
}
NSImage *image = // Get the image
// THIS LINE CAUSES THE EXCEPTION
[self.purgeableImage setData: image.TIFFRepresentation];
}
}
- (void)clearImage {
[self.purgeableImage endContentAccess];
// Putting in this line works, but shouldn't be necessary, should it?
//self.purgeableImage = nil
}
clearImage
与对imageProperty的调用保持平衡。我可以用这个测试用例重现异常:
- (void)testImageProperty_CallTwiceWithMemoryPressure {
MyClass *instance = // Initialize the sucker
NSImage *image = instance.imageProperty;
NSPurgeableData *purgeableData = image.purgeableImage;
XCTAssertNotNil(image, @"Image not loaded");
XCTAssertEqual(image.size.width, (CGFloat)988, @"Image loaded with incorrect width");
XCTAssertEqual(image.size.height, (CGFloat)1500, @"Image loaded with incorrect height");
[instance clearImage];
// Discard, as if there were memory pressure
[purgeableData discardContentIfPossible];
XCTAssertTrue(purgeableData.isContentDiscarded, @"Failed to simulate memory pressure");
// TRIGGERS THE EXCEPTION
image = instance.imageProperty;
XCTAssertNotNil(image, @"Image not loaded on second attempt");
}
我可以通过取消注释-clearImage
中的第二行来消除异常,但我不认为这是必要的。在原始数据被丢弃后,我不能继续使用NSPurgeableData
对象吗?
更新:其他解决方法
调用-endContentAccess
后将其缩小的问题是该类有效地不提供缓存。我找到的另一个解决方案是更新前导if
语句,如下所示:
if (!self.purgeableImage || self.purgeableImage.isContentDiscarded || ![self.purgeableImage beginContentAccess]) {
if (!self.purgeableImage || self.purgeableImage.isContentDiscarded) {