在地图上使用 json-data 时出现内存泄漏
我遇到以下问题:
我正在访问 foursquares Venue API 并返回 JSON 字符串。我用 这个 json-framework 解析这个字符串。之后,我保存字典和数组以访问有关场地的更多信息(特别是我使用explore API)。因此,场地信息(根据我的经验)被深深保存在 json 结构树中。获得所需的信息(场地名称和坐标)后,我在地图上放置了相应的图钉,具有相同的坐标,并将场地名称作为图钉的名称。
就在我想要设置引脚名称的地方,我遇到了内存泄漏。所以这里出了问题。如果我不设置任何标题,一切正常。因此,仅当我将场地名称设置为引脚时,才会发生内存泄漏。
这是相应的代码片段:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//Parse JSON string
// Store incoming data into a string
NSString *jsonString = [[NSString alloc] initWithData:self.fetchedJSONData encoding:NSUTF8StringEncoding];
[self.fetchedJSONData setLength:0];
// Create a dictionary from the JSON string
NSDictionary *results = [NSDictionary dictionaryWithDictionary:[jsonString JSONValue]];
[jsonString release];
NSDictionary *response = [NSDictionary dictionaryWithDictionary:[results objectForKey:@"response"]];
NSArray *groups = [NSArray arrayWithArray:[response objectForKey:@"groups"]];
NSDictionary *groupsDic = [groups lastObject];
NSArray *items = [NSArray arrayWithArray:[groupsDic objectForKey:@"items"]];
for (int i=0; i<[items count]; i++)
{
CLLocationCoordinate2D annotationCoord;
MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init];
NSDictionary* oneItemDoc = [NSDictionary dictionaryWithDictionary:[items objectAtIndex:i]];
NSDictionary *singleVenue = [NSDictionary dictionaryWithDictionary:[oneItemDoc objectForKey:@"venue"]];
/*
* Leak here in the next two lines!
*
*/
NSString *titleName = [[[singleVenue objectForKey:@"name"] copy] autorelease];
annotationPoint.title = titleName;
NSDictionary *locationOfVenue = [NSDictionary dictionaryWithDictionary:[singleVenue objectForKey:@"location"]];
annotationCoord.latitude = [[locationOfVenue objectForKey:@"lat"] doubleValue];
annotationCoord.longitude = [[locationOfVenue objectForKey:@"lng"] doubleValue];
annotationPoint.coordinate = annotationCoord;
[self.mapView addAnnotation:annotationPoint];
[self.annotationsArray addObject:annotationPoint];
[annotationPoint release];
}
}
因此,当我想为annotationPoint设置标题时,就会发生泄漏。
对于使用 JSON 获取的每个场所,我得到以下泄漏跟踪(模糊的库是我自己的库):
有人建议如何解决这个问题吗?我尝试了很多很多事情。所以关键问题似乎是如何正确地“移交”[singleVenue objectForKey:@"name"]
。我首先尝试在没有副本和自动释放的情况下设置它,但后来我得到了一个僵尸对象。所以我不知道该怎么做。我认为问题不在于这两行,而在于它们上面的一些行。我说得对吗?我也有建议,我的第 3 方 json 解析器正在强制解决这个问题(参见泄漏跟踪)。
所以我希望有人可以帮助我解决这个问题。真的会很棒!
更新:问题似乎与相应的 JSON 解析器无关。我已经用另一个解析器测试了我的代码,也有同样的问题。所以它必须对我的代码本身做一些事情。
我想我知道问题出在哪里。所以泄漏是在关闭地图后发生的。所以在dealloc之后。所以可能是我错过了一些东西。我有一个mapview,我也在dealloc中释放它并在viewDidUnload中将其设置为nil。我还在 dealloc 中释放了所有其他数组等。我还需要发布其他内容(特定于地图和视图)吗?我想这可能就是问题所在!
更新:解决了问题:我必须在 dealloc 方法中将所有 Foursquare 引脚的标题和副标题设置为 nil,因为地图视图以某种方式保留了一个值(通过 JSON 解析器访问)。现在一切正常!
I've the following problem:
I'm accessing foursquares Venue API and get a JSON string back. I parse this string with this json-framework. After that I'm saving the dictionaries and arrays for accessing further information about the venues (in special I'm using the explore API). So the venue information is saved deeply (for my experience) in the json-structure tree. And after getting the needed information (venue name & coordinates) I put a corresponding pin on a map with the same coordinates and with the venue's name as the pin's name.
And exactly at the point where I want to set the pin's name, I get a memory leak. So something get's wrong here. If I don't set any title, all works fine. So the memory leak occurs only when I'm setting the name of the venue to the pin.
Here is the corresponding code fragment:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//Parse JSON string
// Store incoming data into a string
NSString *jsonString = [[NSString alloc] initWithData:self.fetchedJSONData encoding:NSUTF8StringEncoding];
[self.fetchedJSONData setLength:0];
// Create a dictionary from the JSON string
NSDictionary *results = [NSDictionary dictionaryWithDictionary:[jsonString JSONValue]];
[jsonString release];
NSDictionary *response = [NSDictionary dictionaryWithDictionary:[results objectForKey:@"response"]];
NSArray *groups = [NSArray arrayWithArray:[response objectForKey:@"groups"]];
NSDictionary *groupsDic = [groups lastObject];
NSArray *items = [NSArray arrayWithArray:[groupsDic objectForKey:@"items"]];
for (int i=0; i<[items count]; i++)
{
CLLocationCoordinate2D annotationCoord;
MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init];
NSDictionary* oneItemDoc = [NSDictionary dictionaryWithDictionary:[items objectAtIndex:i]];
NSDictionary *singleVenue = [NSDictionary dictionaryWithDictionary:[oneItemDoc objectForKey:@"venue"]];
/*
* Leak here in the next two lines!
*
*/
NSString *titleName = [[[singleVenue objectForKey:@"name"] copy] autorelease];
annotationPoint.title = titleName;
NSDictionary *locationOfVenue = [NSDictionary dictionaryWithDictionary:[singleVenue objectForKey:@"location"]];
annotationCoord.latitude = [[locationOfVenue objectForKey:@"lat"] doubleValue];
annotationCoord.longitude = [[locationOfVenue objectForKey:@"lng"] doubleValue];
annotationPoint.coordinate = annotationCoord;
[self.mapView addAnnotation:annotationPoint];
[self.annotationsArray addObject:annotationPoint];
[annotationPoint release];
}
}
So the leak occurs when I want to set the title for the annotationPoint.
For each venue fetched with JSON I get the following leak trace (blurred libraries are my own libraries):
Has anybody a suggestion how to solve this problem? I tried many, many things. So the key issue seems to be how to "hand over" the [singleVenue objectForKey:@"name"]
correctly. I first tried to set it without a copy and an autorelease, but then I get a zombie object. So I don't know how to do this. I think the problem are not these two lines, but some lines above them. Am I right? I also have the suggestion, that my 3rd party json parser is forcing this problem (cf. leak trace).
So I hope someone can help me to fix this problem. Would be really great!
Update: The problem seems to be independent of the corresponding JSON parser. I've testet my code with another parser, same problem there. So it has to do something with my code itself.
I think I know what's the problem. So the leak occurs after closing the map. So after dealloc. So it might be, that I've missed something there. I have a mapview and I also release it in dealloc and set it to nil in viewDidUnload. I also release all the other Arrays etc. in dealloc. Is there something else (specific about the map and view) which I need to release? I think this might be the problem!
Update: Solved the problem: I had to set all Foursquare pins' title and subtitle to nil in the dealloc method, because a value (accessed via a JSON parser) was retained by the map view somehow. Now all works fine!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
解决了问题:我必须在 dealloc 方法中将所有 Foursquare 引脚的标题和副标题设置为 nil,因为地图视图以某种方式保留了一个值(通过 JSON 解析器访问)。现在一切正常!
Solved the problem: I had to set all Foursquare pins' title and subtitle to nil in the dealloc method, because a value (accessed via a JSON parser) was retained by the map view somehow. Now all works fine!
有类似的情况,注释的(MKPointAnnotation)标题没有正确发布。只需在释放之前将 mapView 设置为 nil 即可解决此问题。
我认为这比调用额外的 [title release] 更安全,这也确实有效,但如果 mapView 在内部修复,则会导致问题。
Had a similar situation, annotation's (MKPointAnnotation) title not being released properly. Solved it by simply setting mapView to nil just before releasing it.
I think this is quite safer than calling an extra [title release], which also does work, but if mapView is fixed internally it would cause a problem.