How to move an image from asset library to an appl

2019-04-29 10:41发布

问题:

Here is the code snippet i tried:

[library    writeImageToSavedPhotosAlbum:self.checkInImage.CGImage metadata:self.metadata
            completionBlock             :^(NSURL * assetURL, NSError * error) {
        NSLog (@"Asset url = %@", assetURL);
         NSError *err;
        NSString *docDir = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
        NSString *jpgFilePath = [NSString stringWithFormat:@"%@/test.jpg", docDir];
        NSFileManager *fileManager = [NSFileManager defaultManager];
                [fileManager moveItemAtURL:assetURL toURL:[NSURL URLWithString:jpgFilePath] error:&err];
                NSLog(@"error is %@", err);
    }];

I get the error as Error Domain=NSCocoaErrorDomain Code=262 "The operation couldn’t be completed. (Cocoa error 262.)" UserInfo=0xb49a680 {NSURL=assets-library://asset/asset.JPG?id=6FAC823A-33CB-489B-A125-714FBA5F0EE8&ext=JPG}

Any ideas?

回答1:

Docs (and Google). This error code corresponds to the NSFileReadUnsupportedSchemeError constant - i. e. you can't just use an assets-library:// URL to move a file using NSFileManager. (The same is the case regarding ipod-library:// URLs.) You have to use the AssetsLibrary framework to get the data of the file and then write it to a file using - [NSData writeToFile:atomically:].

ALAssetsLibrary *lib = [ALAssetsLibrary new];
[lib assetForUrl:theURL // the asset URL you have obtained, NSURL object
    resultBlock:^(ALAsset *asset) {
        // get data
        ALAssetRepresentation *repr = [asset defaultRepresentation];
        CGImageRef cgImg = [repr fullResolutionImage];
        NSString *fname = [repr fileName];
        UIImage *img = [UIImage imageWithCGImage:cgImg];
        NSData *data = UIImagePNGRepresentation(img);
        [data writeToFile:[@"BaseDirectory/" stringByAppendingPathComponent:fname]
            atomically:YES];
        [lib release];
    }
    failureBlock:^(NSError *error) {
        // recover from error, then
        [lib release];
    }];


回答2:

This is how I solved the issue:

1) I saved the file without metadata in some location, and stored its urlpath.

2) Then used the following piece of code to save the same file with metadata. Here fileURL is the urlpath obtained from step 1.

CFURLRef url = CFURLCreateFilePathURL(NULL, (CFURLRef)fileURL, NULL);
// Creating Image source from image url
CGImageSourceRef imageSource = CGImageSourceCreateWithURL(url, NULL);

// This will be the data CGImageDestinationRef will write into
CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData(data, CFSTR("public.jpeg"), 1, NULL);

BOOL success = (imageSource != NULL);

require(success, cleanup);

success = (imageDestination != NULL);
require(success, cleanup);

// Add the image contained in the image source to the destination, overidding the old metadata with our modified metadata
NSDictionary *metadata = someObj.metadata;
CGImageDestinationAddImageFromSource(imageDestination, imageSource, 0, (CFDictionaryRef)metadata);

// Tell the destination to write the image data and metadata into our data object.
success = CGImageDestinationFinalize(imageDestination);

require(success, cleanup);

// Write the data into the url
[(NSMutableData *) data writeToURL:fileURL atomically:YES];

cleanup:

if (data) {
    CFRelease(data);
    data = NULL;
}

if (imageSource) {
    CFRelease(imageSource);
    imageSource = NULL;
}

if (imageDestination) {
    CFRelease(imageDestination);
    imageDestination = NULL;
}

return success;

Hope this helps. But I would like to upvote H2C03 for very helpful suggestions, which helped to arrive at this solution. Please help me how to do it. Thanks.