我已经开始编写我第一次认真尝试为 iOS 混合的 Cordova/Objective-C 程序,我目前遇到了一些关于内存分配的绊脚石。我需要让用户的专辑封面显示在 WebView 中。我让艺术作品成功展示,但现在分配了大量内存。
使用“工具”工具并比较世代快照,我将我的罪魁祸首缩小到这些方法——我都是从头开始写的。但我很困惑——因为我使用的是自动引用计数,并且我在自动释放池中拥有所有东西,所以不应该有任何浪费的内存。有趣的是,我没有看到任何“泄漏”的报告——只是堆越来越大,分配的内存越来越多。
我附上了 Instruments 工具的一些截图:
由于文字太多,这里是图片的直接链接:
http://i.imgur.com/rkc5dhA.png
http://i.imgur.com/U2esgBT.png
http://i.imgur.com/fmt3Mv4.png
这是我制作的“BukketHelper.M”类的内容(匹配标题,没有强属性或任何其他任何类型的定义):
-(NSString *) convertULLToNSString:(NSNumber* )guid
{
return [NSString stringWithFormat:@"%llu", [guid unsignedLongLongValue]];
}
-(NSNumber *) convertStringToULL:(NSString *) guid
{
//get string to number
//this causes memory to not be released
unsigned long long ullvalue = strtoull([guid UTF8String], NULL, 10);
NSNumber *numberID = [[NSNumber alloc] initWithUnsignedLongLong:ullvalue];
return numberID;
}
这是我制作的“MediaQuery.M”类的内容(这与标题完全匹配,没有强属性或其他定义):
-(MPMediaItem*) getMediaItemULL:(NSNumber*)guid
{
@autoreleasepool {
//run the query on
MPMediaQuery *query = [[MPMediaQuery alloc] init];
[query addFilterPredicate:[MPMediaPropertyPredicate predicateWithValue:guid forProperty:MPMediaItemPropertyPersistentID]];
//get and return the item
NSArray *mediaResults = [query items];
return [mediaResults firstObject];
}
}
-(MPMediaItem*) getMediaItem:(NSString*)guid
{
@autoreleasepool {
BukketHelper* bh = [[BukketHelper alloc] init];
return [self getMediaItemULL:[bh convertStringToULL:guid]];
}
}
-(UIImage*) getMediaAlbumArtAsUIImage:(NSString*)guid withQuality:(NSNumber*)quality withLength:(NSNumber*)length subsituteImageName:(NSString* )filename
{
return [self getMediaAlbumArtFromMediaItemAsUIImage:[self getMediaItem:guid] withQuality:quality withLength:length subsituteImageName:filename];
}
-(NSString*) getMediaAlbumArtAsBase64:(NSString*)guid withQuality:(NSNumber*)quality withLength:(NSNumber*)length subsituteImageName:(NSString* )filename
{
NSString *base64 = nil;
@autoreleasepool {
UIImage* rawImage = [self getMediaAlbumArtAsUIImage:guid withQuality:quality withLength:length subsituteImageName:filename];
NSData *imageData = nil;
if (rawImage != nil)
{
@autoreleasepool {
//this causes memory to not be released
imageData = UIImageJPEGRepresentation(rawImage, [quality floatValue]);
base64 = [imageData base64EncodedStringWithOptions:0];
}
}
}
return base64;
}
-(UIImage*) getMediaAlbumArtFromMediaItemAsUIImage:(MPMediaItem*)item withQuality:(NSNumber*)quality withLength:(NSNumber*)length subsituteImageName:(NSString* )filename
{
UIImage *rawImage = nil;
@autoreleasepool {
bool successfulArt = NO;
if (item != nil)
{
MPMediaItemArtwork *albumArt = [item valueForProperty:MPMediaItemPropertyArtwork];
if (albumArt != nil) {
@autoreleasepool {
//this causes memory to not be released
rawImage = [albumArt imageWithSize:CGSizeMake([length doubleValue], [length doubleValue])];
successfulArt = YES;
}
}
}
if (successfulArt == NO)
{
rawImage = [UIImage imageNamed:filename];
}
}
return rawImage;
}
所以是的 - 我的问题是:在内存分配和泄漏方面我做错了什么?我目前的测试只使用专辑封面 - 所以“UIImage imageNamed”不应该是问题(来自它的缓存)。此外,我读到 ARC 无法释放 CoreGraphics 对象,这也可能是问题所在。
我真的可以在这方面使用一些帮助!谢谢!
最佳答案
我遇到了同样的问题。我认为框架中有一个错误不会释放内存。基本上每次分配的内存都有一个巨大的峰值func imageWithSize(size: CGSize) -> UIImage?
叫做。
如果它对你有任何帮助,我注意到如果你调用这个函数传入 artifact.bounds.size (而不是每次都创建一个新的图像大小),那么内存只会分配一次并再次调用 imageWithSize (具有相同的尺寸)不会重新分配新内存。仅当您传入原始艺术品图像的大小并且不返回自定义大小时,这似乎才是正确的。如果您需要自定义大小,也许您可以自己调整 UIImage 的大小,而不是依赖这种错误的方法。
关于ios - 使用 ARC 进行内存分配 - 没有泄漏,但会慢慢堆积内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31372597/