J'utilise UIImagePickerController dans deux cas
Dans le premier cas, lorsque je choisis une image dans la bibliothèque, je peux facilement obtenir l'URL dans la méthode déléguée:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// Get the URL
NSURL *url = [info valueForKey:UIImagePickerControllerReferenceURL];
...
}
Mais lorsque je prends une nouvelle photo, celle-ci ne figure pas encore dans la photothèque et ne contient pas encore d'URL. Donc, je dois d'abord ajouter l'image dans la bibliothèque. Mais alors, comment obtenir l'URL du nouvel actif?
Voici mon code pour ajouter l'image dans la photothèque
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// Get the image
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
// Add the image in the library
[[PHPhotoLibrary sharedPhotoLibrary]
performChanges:^
{
// Request creating an asset from the image.
PHAssetChangeRequest *createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
// Get the URL of the new asset here ?
...
}
completionHandler:^(BOOL success, NSError *error)
{
if (!success) { ...; return; }
// Get the URL of the new asset here ?
...
}
];
}
Je n'ai pas trouvé le moyen d'obtenir l'URL, mais peut-être que localIdentifier peut vous aider à faire le même travail.
utilisation
NSString* localId = [[assetChangeRequest placeholderForCreatedAsset] localIdentifier];
pour obtenir l'ID local et obtenir l'image plus tard.
__block NSString* localId;
// Add it to the photo library
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
if (self.assetCollection) {
PHAssetCollectionChangeRequest *assetCollectionChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:self.assetCollection];
[assetCollectionChangeRequest addAssets:@[[assetChangeRequest placeholderForCreatedAsset]]];
}
localId = [[assetChangeRequest placeholderForCreatedAsset] localIdentifier];
} completionHandler:^(BOOL success, NSError *error) {
PHFetchResult* assetResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[localId] options:nil];
if (!success) {
NSLog(@"Error creating asset: %@", error);
} else {
PHFetchResult* assetResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[localId] options:nil];
PHAsset *asset = [assetResult firstObject];
[[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
UIImage* newImage = [UIImage imageWithData:imageData];
self.imageView.image = newImage;
}];
}
}];
Je n'aime pas ce correctif, car cela pourrait entraîner une situation de concurrence critique. Jusqu'à présent, je ne peux pas penser à une meilleure solution. Si quelqu'un le faisait, j'aimerais l'entendre :) Quoi qu'il en soit, voici une version rapide de la réponse de Rigel Chen
import Photos
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
var localId:String?
let imageManager = PHPhotoLibrary.sharedPhotoLibrary()
imageManager.performChanges({ () -> Void in
let request = PHAssetChangeRequest.creationRequestForAssetFromImage(image)
localId = request.placeholderForCreatedAsset?.localIdentifier
}, completionHandler: { (success, error) -> Void in
dispatch_async(dispatch_get_main_queue(), { () -> Void in
if let localId = localId {
let result = PHAsset.fetchAssetsWithLocalIdentifiers([localId], options: nil)
let assets = result.objectsAtIndexes(NSIndexSet(indexesInRange: NSRange(location: 0, length: result.count))) as? [PHAsset] ?? []
if let asset = assets.first {
// Do something with result
}
}
})
})
}
}
Si nous utilisons ALAssetsLibrary, il est très simple d’enregistrer une photo dans l’Album photo et d’obtenir son URL:
// Get the image
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
// Add the image in the Photo Library
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeImageToSavedPhotosAlbum: [image CGImage]
orientation: (ALAssetOrientation)[image imageOrientation]
completionBlock: ^(NSURL *assetURL, NSError *error)
{
if (error)
{
NSLog( @"error: %@", error );
}
else
{
NSLog( @"assetURL = %@", assetURL );
}
}];
Mais étonnamment, il ne semble pas possible de faire la même chose avec la nouvelle PHPhotoLibrary!
Une solution pour obtenir le même résultat avec PHPhotoLibrary est toujours la bienvenue.
[Swift 4] Cette méthode peut gérer à la fois l'image et la vidéo, profitez-en :)
func getURL(of asset: PHAsset, completionHandler : @escaping ((_ responseURL : URL?) -> Void)) {
if asset.mediaType == .image {
let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
return true
}
asset.requestContentEditingInput(with: options, completionHandler: { (contentEditingInput, info) in
completionHandler(contentEditingInput!.fullSizeImageURL)
})
} else if asset.mediaType == .video {
let options: PHVideoRequestOptions = PHVideoRequestOptions()
options.version = .original
PHImageManager.default().requestAVAsset(forVideo: asset, options: options, resultHandler: { (asset, audioMix, info) in
if let urlAsset = asset as? AVURLAsset {
let localVideoUrl = urlAsset.url
completionHandler(localVideoUrl)
} else {
completionHandler(nil)
}
})
}
}
Récupérer l'URL de l'image:
- (void)processImage:(UIImage*)image type:(NSString*)mimeType forCallbackId:(NSString*)callbackId
{
__block NSString* localId;
// Add it to the photo library
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
localId = [[assetChangeRequest placeholderForCreatedAsset] localIdentifier];
} completionHandler:^(BOOL success, NSError *err) {
if (!success) {
NSLog(@"Error saving image: %@", [err localizedDescription]);
} else {
PHFetchResult* assetResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[localId] options:nil];
PHAsset *asset = [assetResult firstObject];
[[PHImageManager defaultManager] requestImageDataForAsset:asset
options:nil
resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
NSURL *fileUrl = [info objectForKey:@"PHImageFileURLKey"];
if (fileUrl) {
NSLog(@"Image path: %@", [fileUrl relativePath]);
} else {
NSLog(@"Error retrieving image filePath, heres whats available: %@", info);
}
}];
}
}];
}
Swift 4 solution qui fonctionne pour moi pour obtenir l'URL de la dernière image dans la photothèque :
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
let fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions).lastObject
PHImageManager().requestAVAsset(forVideo: fetchResult!, options: nil, resultHandler { (avurlAsset, _, _) in
if let newObj = avurlAsset as? AVURLAsset {
print(newObj.url)
}
})
J'espère que ça aide!