0
votes

I have an app that is adding a view that is used to call UIImagePickerController. When the use hits the add image button, the following code executes:

'- (IBAction)addPhoto:(id)sender {

// Call background tap in case any keyboards are still up
[self backgroundTap:sender];

if (jpegData) {

    // If we already chose an image, don't allow to choose another.
    // Have to cancel out and come back!
    return;
}

// Shows the photo picker so the user can take or select an image
photoPickerViewController = [[PhotoPickerViewController alloc] initWithNibName:@"PhotoPicker" bundle:nil];
photoPickerViewController.delegate = self;

// Add it to the subview - it will auto animate in/out
[self.view addSubview:photoPickerViewController.view];

}

This presents the user with a view that I created that has 3 buttons: Take photo, choose existing photo, and cancel. Cancel just cancels back to the main view. If take photo or choose existing is called, this code is executed:

'- (IBAction)choosePhoto:(id)sender {

// Show an image picker to allow the user to choose a new photo.
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;

if((UIButton*)sender == chooseExistingButton) {
    imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
} else {
    imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
    imagePicker.showsCameraControls = YES;
}

[self presentModalViewController:imagePicker animated:YES];
[imagePicker release];

}

When if the user cancels out from the image picker, we go back to the main view. No problem. If however they complete image selection (either through taking a photo or choosing an existing one) then we call:

'- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

// Ok, dismiss the modal picker, bring up the activity indicator and dispatch a thread
// that will do all the photo processing ...
BOOL isFromCamera = picker.sourceType == UIImagePickerControllerSourceTypeCamera;

// Dismiss the picker view controller
[picker dismissModalViewControllerAnimated:NO];

// And remove our view from the list of views
[self.view removeFromSuperview];

if (isFromCamera)
{       
        // Declare the completion block to use
    ALAssetsLibraryWriteImageCompletionBlock compBlock = ^(NSURL *assetURL, NSError *error) {

        if (error != nil || assetURL == nil) {

            NSLog(@"Failed to save photo: %@", error);
            [delegate photoSetURLForImage:nil];
        }

        else {

            NSLog(@"URL is : %@", [assetURL absoluteString]);
            [delegate photoSetURLForImage:assetURL];
        }
    };

    ALAssetsLibrary* library = [[[ALAssetsLibrary alloc] init] autorelease];
    [library writeImageToSavedPhotosAlbum:cgimage
                                 metadata:meta
                          completionBlock:compBlock];
    return;
}
else {
    // Use the URL to get the metadata for the image that was picked ...
    NSURL* url = [(NSDictionary*)info objectForKey:@"UIImagePickerControllerReferenceURL"];

    if (url) {

        // Define a result and failure block for fetching from the ALAsset
        ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset* myasset)
        {
            ALAssetRepresentation *rep = [myasset defaultRepresentation];

            NSLog(@"URL is : %@", [[rep url] absoluteString]);
            [delegate photoSetURLForImage:[rep url]];
        };

        // And also define a failure block
        ALAssetsLibraryAccessFailureBlock failureblock  = ^(NSError *myerror)
        {
            [delegate photoSetURLForImage:nil];
        };

        ALAssetsLibrary* assetslibrary = [[[ALAssetsLibrary alloc] init] autorelease];
        [assetslibrary assetForURL:url 
                       resultBlock:resultblock
                      failureBlock:failureblock];
        return;
    }
}

// If we get here, something went very wrong
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"Error" message:@"An error occured while retrieving the image" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil] autorelease];
[alert show];

}

Now, the first time I run through this code, all works great. As soon as I hit "use" on the image I took with the camera, or I select an image from the camera roll, the UIImagePicker view and the view that launches it go away and I'm back at the main view while I wait for the ALAsset calls to do their thing.

The problem starts when I try to repeat this process a second time. After selecting an image or taking one, the processing begins, but the views do not go away, until all of the processing by the ALAsset calls has completed. I can't figure out why this is. Why it works the first time, but not anytime after. Is there some caching mechanism I have to clear? Anyways, if anybody can offer up some advice, I'd be very grateful.

Thanks,

J

1

1 Answers

0
votes

Yet again it appears I'll be answering my own question. This is starting to become a habit lol.

So it appears that the ALAsset calls aren't spinning off a new thread which is what I thought they were supposed to do. My bad. So to resolve, it was just a matter of spawning a new thread to do all the ALAsset stuff, and in the main thread dismissing my picker and what not.

Problem solved, yay!