本文介绍了在Objective-C中做事情的正确地方的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始玩ObjectiveFlickr框架,目标是创建一个相对简单的iPhone地图应用程序,在当前MKMapView区域内显示带有地理标记的flickr内容。我遇到了线程相关的麻烦,现在我有我的感觉在我的建筑学根本错误。基本上我有的是:

I started toying around with the ObjectiveFlickr framework with the goal of creating a relatively simple iPhone map application showing geotagged flickr content within the current MKMapView region. I ran into threading related trouble before and now I have the feeling I am getting something fundamentally wrong in my architecture. Basically what I have is:


  1. 一个MainViewController创建
    并处理MKMapView对象和
    a按钮

  2. 点击按钮可调用
    a方法,在
    当前地图范围内的地理标记照片中调用Flickr API

  3. 此API调用的回调
    方法通过结果遍历
    ,并将它们放在
    中一个FlickrImage对象的NSMutableArray。 FlickrImage是一个简单的数据类,它将flickr图像位置保存为CLLocation,NSURL指向缩略图和标题NSString。

第2步的代码段:

-(void)actionSearchForTripodPhotos {
    if(currentBoundingBox == nil) {
        // TODO add a messagebox saying we're waiting for location info - or just lock the app until we're sure.
        return; 
    }
    NSString *dateTakenMinimumUNIXTimeStampString = [NSString stringWithFormat:@"%f",[[NSDate dateWithTimeIntervalSinceNow:-100000] timeIntervalSince1970]];
    OFFlickrAPIRequest *flickrAPIRequest = [[OFFlickrAPIRequest alloc] initWithAPIContext:[CloudMadeMap101AppDelegate sharedDelegate].flickrAPIContext];
    [flickrAPIRequest setDelegate:self];
    NSString *flickrAPIMethodToCall = @"flickr.photos.search";
    NSString *bboxString = [NSString stringWithFormat:@"%f,%f,%f,%f",currentBoundingBox.bottomLeftLat ,currentBoundingBox.bottomLeftLon ,currentBoundingBox.topRightLat ,currentBoundingBox.topRightLon];
    NSLog(@"bounding box to be sent to flickr: %@",bboxString);
    NSDictionary *requestArguments = [[NSDictionary alloc] initWithObjectsAndKeys:FLICKR_API_KEY,@"api_key",[NSString stringWithFormat:@"%f",currentLocation.coordinate.latitude],@"lat",[NSString stringWithFormat:@"%f",currentLocation.coordinate.longitude],@"lon",dateTakenMinimumUNIXTimeStampString,@"min_upload_date",nil];
    [flickrAPIRequest callAPIMethodWithGET:flickrAPIMethodToCall arguments:requestArguments];
}

第3步的代码段:

- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest didCompleteWithResponse:(NSDictionary *)inResponseDictionary {
NSDictionary *photosDictionary = [inResponseDictionary valueForKeyPath:@"photos.photo"];
NSDictionary *photoDictionary;
FlickrImage *flickrImage;
for (photoDictionary in photosDictionary) {
  NSLog(@"photodictionary is %@",[photoDictionary description]);
  flickrImage = [[FlickrImage alloc] init];
  flickrImage.thumbnailURL = [[appDelegate sharedDelegate].flickrAPIContext photoSourceURLFromDictionary:photoDictionary size:OFFlickrThumbnailSize];
  flickrImage.hasLocation = TRUE; // TODO this is actually to be determined...
  flickrImage.ID = [NSString stringWithFormat:@"%@",[photoDictionary valueForKeyPath:@"id"]];
  flickrImage.owner = [photoDictionary valueForKeyPath:@"owner"];
  flickrImage.title = [photoDictionary valueForKeyPath:@"title"];
  [flickrImages addObject:flickrImage];
  [photoDictionary release];        
}
}

API恼人地不会为每张照片返回地理位置,因此这需要另一个API调用。我想我可以从FlickrImage类中这样做,但在这里它变得丑陋:

This all goes well. The API annoyingly does not return geolocation for each individual photo, so this requires another API call. I thought I might do this from within the FlickrImage class, but here it gets ugly:


  • MainViewController创建一个FlickrImage的实例,将其存储在NSMutableArray中。

  • FlickrImage实例以非同步方式调用地理位置Flickr API,应存储在适当的成员变量中返回的坐标。

我很确定这不会发生,因为我得到

I am pretty sure that this is not happening because I am getting

malloc: *** error for object 0x451bc04: incorrect checksum for freed object - object was probably modified after being freed.

在我的调试输出附近,几乎总是一个 EXC_BAD_ACCESS 但不是一致的。

sprinkled around my debugging output, and almost always a EXC_BAD_ACCESS but not consistently at the same point.

我显然在这里做一些根本错误,但是什么?

I am clearly doing something fundamentally wrong here, but what?

推荐答案

当你迭代字典时,不需要调用 [photoDictionary release]

When you iterate over dictionary there is no need to call [photoDictionary release]:

NSDictionary *photosDictionary =
      [inResponseDictionary valueForKeyPath:@"photos.photo"];
NSDictionary *photoDictionary;
FlickrImage *flickrImage;
for (photoDictionary in photosDictionary) {
  ... 
  [photoDictionary release];            

我认为这是你的问题所在。

I think this is where your problem is.

当调用 release 并且对象到达 ref count 0 时会被释放。

When calling release and the object reaches ref count 0 it gets deallocated.

因为你不应该这样做,后来当字典被释放时,它会发送 release 到它的每个元素,但你可能已经

Because you were not supposed to do that, later on when the dictionary is released it sends release to each of its elements but you have possibly already deallocated them.

这是objective-c 的基本内存管理。有关内存管理和 retain / release / autorelease 的更多说明。

This is basic memory management in objective-c. Have a look at memory management and retain/release/autorelease stuff for more explanation.

这篇关于在Objective-C中做事情的正确地方的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-02 17:37