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:
- A MainViewController that creates and handles the MKMapView object and a button
- Tapping the button calls a method that calls the Flickr API for geotagged photos within the current map extent.
- The callback method for this API call iterates through the results and puts them in an NSMutableArray of FlickrImage objects. FlickrImage is a simple data class holding the flickr image location as a CLLocation, a NSURL pointing to the thumbnail, and a title NSString.
Code snippet for step 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];
}
Code snippet for step 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];
}
}
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:
- The MainViewController creates an instance of FlickrImage each iteration and stores it in the NSMutableArray.
- The FlickrImage instance calls the geolocation Flickr API asunchronously and should store the coordinate returned in the appropriate member variable.
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.
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?