Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

pan17

macrumors newbie
Original poster
Jul 9, 2012
11
0
I implement a UIViewController which shows the MapView delegate method in another UIViewController, I'm trying to get the image from Internet when a pin is clicked by user in that MapView by returning the image for that method, but it blocked the main thread so that the whole MapView is blocked by that method. I'm just wondering if there is a way to solve this problem. The following is my method:

Code:
// PhotoMapViewControllerDelegate method to get the clicked thumbnail image
- (UIImage *)photoMapViewController:(PhotoMapViewController *)sender imageForAnnotation:(id<MKAnnotation>)annotation
{   
    SinglePlacePhotosAnnotations *sppa = (SinglePlacePhotosAnnotations *)annotation;
    // check out the folder if the photo already exists
    NSFileManager *filemanager = [NSFileManager defaultManager];
    NSURL *libraryURL = [[filemanager URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject];
    NSURL *photosURL = [libraryURL URLByAppendingPathComponent:@"Viewd Photos"];
    NSString *photoID = [sppa.photo objectForKey:FLICKR_PHOTO_ID];
    NSURL *singlePhotoURL = [photosURL URLByAppendingPathComponent:photoID];
    dispatch_queue_t getImage = dispatch_queue_create("getImage", NULL);
    // local variables in a block is read-only!!!!!!!!!!!
    __block UIImage *image = nil;
    // use a variable to check if the block is done
    __block BOOL blockIsDone = NO;
    dispatch_async(getImage, ^ { 
        if ([filemanager fileExistsAtPath:singlePhotoURL.path]) { 
            image = [UIImage imageWithContentsOfFile:singlePhotoURL.path];
            blockIsDone = YES;
        }
        else {
            NSURL *url = [FlickrFetcher urlForPhoto:sppa.photo format:FlickrPhotoFormatSquare];
            NSData *data = [NSData dataWithContentsOfURL:url];
            image = [UIImage imageWithData:data]; 
            blockIsDone = YES;
        }
    });
    // block makes it asynchronous like the completion handler, this function returns image before the block
    // is done, so have to wait until the block got executed!
    while (!blockIsDone) {
        usleep(USEC_PER_SEC/10);
    }
    return image;
}
Thanks in advance.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
Your dispatch async is essentially useless as you then implement your own blocking until it is complete. You need to use a callback or similar once the data is complete to display it.
 

pan17

macrumors newbie
Original poster
Jul 9, 2012
11
0
Your dispatch async is essentially useless as you then implement your own blocking until it is complete. You need to use a callback or similar once the data is complete to display it.

When i scroll down, some new cells still showed the previous cells' corresponding image, then later it will change into the new images. I think this is because when i scroll down showing new table cells, the previous get image data lines which are called in the dispatch block just got the data when i didn't scroll down and set the image.
I'm looking for some methods which could let me scroll down and when the previous image data returned, set the image to the specific old one.
So, as you said, i need a callback function to get the old image data for the previous table cells it showed,right?
Thank you for your time.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
I am struggling to understand what you mean. You probably need to break this down:

1) Get the view working correctly so no cell ever shows the incorrect data. When you are asked to provide a cell for a table row then it's up to you to reset the image etc. Cells get re-used so if you set the image to X and don't ever unset it then it will still display this when that's not correct

2) Have some sort of model class that does the loading of images and sends notifications to the delegate/caller class when images that were not immediately available get downloaded

3) Have the table view controller use 2) and update/refresh the cells when images become available

There are no pre-built methods: you do this yourself.
 

pan17

macrumors newbie
Original poster
Jul 9, 2012
11
0
I am struggling to understand what you mean. You probably need to break this down:

1) Get the view working correctly so no cell ever shows the incorrect data. When you are asked to provide a cell for a table row then it's up to you to reset the image etc. Cells get re-used so if you set the image to X and don't ever unset it then it will still display this when that's not correct

2) Have some sort of model class that does the loading of images and sends notifications to the delegate/caller class when images that were not immediately available get downloaded

3) Have the table view controller use 2) and update/refresh the cells when images become available

There are no pre-built methods: you do this yourself.

Sorry about that. This is clear and helpful.
Thank you
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.