我正在使用CocoaLibSpotify库为Spotify搜索结果加载专辑封面。
仪器报告没有泄漏,静态分析也没有帮助,我已经手动审查了所有处理跟踪加载专辑封面的代码,但是,在加载了几百个结果之后,应用程序消耗超过100mb的内存和崩溃。
我相信CocoaLibSpotify会在内存中保留图像的缓存,但是我找不到禁用缓存的方法。有一个“flushCaches”方法,我每次收到内存警告时都会调用它,但它无效。
这是我用来加载专辑封面的内容,我保留了对数组中所有SPImage对象的引用,以便在提供表视图行时可以使用它们。
[self sendRequestToURL: @"http://ws.spotify.com/search/1/track.json" withParams: @{@"q": spotifySearchBar.text} usingMethod: @"GET" completionHandler: ^(id result, NSError *error) {
//after the search completes, re-enable the search button, replace the searchResults, and
// request the result table to reload the data
spotifySearchBar.userInteractionEnabled = YES;
[searchBar endEditing: YES];
[searchResults release];
int resultLength = [[result objectForKey: @"tracks"] count] < 100 ? [[result objectForKey: @"tracks"] count] : 100;
searchResults = [[[result objectForKey: @"tracks"] subarrayWithRange: NSMakeRange(0, resultLength)] retain];
for(int i = 0; i < 100; i++) {
[albumArtCache replaceObjectAtIndex: i withObject: [NSNull null]];
}
for(NSDictionary *trackDict in searchResults) {
NSString *trackURI = [trackDict objectForKey: @"href"];
[SPTrack trackForTrackURL: [NSURL URLWithString: trackURI] inSession: session callback: ^(SPTrack *track) {
[SPAsyncLoading waitUntilLoaded: track timeout: kSPAsyncLoadingDefaultTimeout then:^(NSArray *loadedItems, NSArray *notLoadedItems) {
if(track == nil) return;
[SPAsyncLoading waitUntilLoaded: track.album timeout: kSPAsyncLoadingDefaultTimeout then:^(NSArray *loadedItems, NSArray *notLoadedItems) {
if(track.album == nil) return;
[SPAsyncLoading waitUntilLoaded: track.album.largeCover timeout: kSPAsyncLoadingDefaultTimeout then:^(NSArray *loadedItems, NSArray *notLoadedItems) {
if(track.album.largeCover == nil) return;
if(![searchResults containsObject: trackDict]) {
NSLog(@"new search was performed, discarding loaded result");
return;
} else{
[albumArtCache replaceObjectAtIndex: [searchResults indexOfObject: trackDict] withObject: track.album.largeCover];
[resultTableView reloadRowsAtIndexPaths: @[[NSIndexPath indexPathForRow: [searchResults indexOfObject: trackDict] inSection: 0]] withRowAnimation: UITableViewRowAnimationAutomatic];
}
}];
}];
}];
}];
}
[resultTableView reloadData];
}];
以下是处理加载表格视图单元格的代码。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: @"artistCell"];
if(cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier: @"artistCell"] autorelease];
}
cell.textLabel.text = [[searchResults objectAtIndex: indexPath.row] objectForKey: @"name"];
cell.detailTextLabel.text = [[[[searchResults objectAtIndex: indexPath.row] objectForKey: @"artists"] objectAtIndex: 0] objectForKey: @"name"];
if([albumArtCache objectAtIndex: indexPath.row] != [NSNull null]) {
cell.imageView.image = ((SPImage *)[albumArtCache objectAtIndex: indexPath.row]).image;
} else{
cell.imageView.image = nil;
}
return cell;
}
我真的不知道出了什么问题。非常感谢任何帮助。
答案 0 :(得分:1)
首先,您应该使用SPSearch
而不是网络API进行搜索。
Instruments没有显示内存泄漏的原因是因为没有 - CocoaLibSpotify因内部性能原因在内部缓存了专辑和图像。因此,加载的专辑封面也会留下来。
现在,将数百个1024x1024图像加载到内存中显然会很糟糕。缓解问题的一种简单方法是不加载最大尺寸的图像 - 对于1024x1024像素的表格视图通常不需要。
否则,您可以修改CocoaLibSpotify以便能够卸载图像。最简单的方法是向SPImage
添加一个基本与-startLoading
相反的方法 - 即将image
属性设置为nil
,{{在将hasStartedLoading
设置为loaded
之前,将{}}和NO
属性设置为sp_image_release
并在spImage
属性上调用NULL
。