在Objective-C中做正确的事情

mve*_*xel 2 cocoa-touch objective-c

我开始研究ObjectiveFlickr框架,目的是创建一个相对简单的iPhone地图应用程序,显示当前MKMapView区域内的地理标记flickr内容.我跑进线程相关的麻烦之前,现在我有我得到某种根本性错误在我的建筑感觉.基本上我所拥有的是:

  1. 一个MainViewController,用于创建和处理MKMapView对象和一个按钮
  2. 点击该按钮会调用一种方法,该方法在当前地图范围内调用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];
}
Run Code Online (Sandbox Code Playgroud)

第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];        
}
}
Run Code Online (Sandbox Code Playgroud)

一切顺利.API烦人地不会为每张照片返回地理位置,因此这需要另一个API调用.我想我可以在FlickrImage类中做到这一点,但是这里变得丑陋:

  • MainViewController每次迭代都会创建一个FlickrImage实例,并将其存储在NSMutableArray中.
  • FlickrImage实例非常响应地调用地理定位Flickr API,并且应该在适当的成员变量中存储返回的坐标.

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

malloc: *** error for object 0x451bc04: incorrect checksum for freed object - object was probably modified after being freed.
Run Code Online (Sandbox Code Playgroud)

洒在我的调试输出周围,几乎总是一个EXC_BAD_ACCESS但不是始终如一.

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

enn*_*ler 6

该错误意味着它所说的内容:您可能在释放后修改了内存,而EXC_BAD_ACCESS表示您正在尝试访问不存在的数组元素.当你试图调用地理定位方法时,我会检查你的FlickrImage对象是不是被释放了.

你的设计中没有任何东西可以脱颖而出,因为它存在根本缺陷

  • +1.并使用NSZombieEnabled找出哪个对象是罪魁祸首. (3认同)