Получение URL-адреса снимка, сделанного камерой с помощью Photos Framework
У меня есть приложение, которое использует UIImagePickerController для получения изображений как с камеры, так и из библиотеки фотографий. В делегате выбора изображений я хочу только сохранить NSURL (UIImagePickerControllerReferenceURL) выбранного изображения для экономии памяти. Когда пользователю необходимо увидеть изображение позже, я загружаю его с помощью PHCachingImageManager прямо из библиотеки фотографий.
Теперь - все это прекрасно работает с изображениями, которые пользователь выбирает из библиотеки, но не с изображениями, снятыми непосредственно камерой (так как URL отсутствует). В настоящее время я пытаюсь сохранить изображение с помощью PHAsset, но я не знаю, как получить NSURL для сохраненного изображения.
Вот чем я занимался:
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
{
picker.dismissViewControllerAnimated(true, completion: nil)
let pickedImage = info[UIImagePickerControllerOriginalImage] as! UIImage
if picker.sourceType == .Camera
{
// When taking a picture with the camera, store it in the user roll
PHPhotoLibrary.sharedPhotoLibrary().performChanges(
{ () -> Void in
// save the image
PHAssetCreationRequest.creationRequestForAssetFromImage(pickedImage)
// TODO how to get the asset url
}, completionHandler:
{ (finished, error) -> Void in
if (finished)
{
}
}
)
}
else
{
let pickedImageUrl: NSURL? = info[UIImagePickerControllerReferenceURL] as? NSURL
currentImageUrl = pickedImageUrl
currentImage = pickedImage
toggleImageInfoView(true)
toggleMapState(true)
}
}
Любые идеи, как получить URL сохраненного изображения?
Бест, Георг
2 ответа
ОБНОВЛЕНИЕ: Похоже, я нашел ответ на эту проблему.
Шаг 1: я сохраняю изображение на камеру
UIImageWriteToSavedPhotosAlbum(image.image, self, #selector(cameraImageSavedAsynchronously), nil)
это делается асинхронно, поэтому убедитесь, что селектор установлен после завершения операции.
Шаг 2: После завершения операции я делаю следующее:
func fetchLastImage(completion: (localIdentifier: String?) -> Void)
{
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
fetchOptions.fetchLimit = 1
let fetchResult = PHAsset.fetchAssetsWithMediaType(.Image, options: fetchOptions)
if (fetchResult.firstObject != nil)
{
let lastImageAsset: PHAsset = fetchResult.firstObject as! PHAsset
completion(localIdentifier: lastImageAsset.localIdentifier)
}
else
{
completion(localIdentifier: nil)
}
}
Я извлекаю последнее изображение в рулоне камеры с помощью PHAsset и сохраняю локальный идентификатор изображения. Это не URL, а уникальный идентификатор, который не изменяется. Таким образом, вы можете получить доступ к сохраненному изображению идеально.
Надеюсь, что это помогает другим!
Я с тобой согласен.
но, если Exif изображения имеет дату более раннюю.
let fetchResult = PHAsset.fetchAssetsWithMediaType(.Image, options: fetchOptions)
fetchResult.firstObject
fetchResult.firstObject - это не тот, который вы только что сохранили.
может быть, вы можете изменить fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)
в key: "modificationDate"
Кстати, я нашел другой способ:
__block PHObjectPlaceholder *placeholderAsset = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *newAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url];
newAssetRequest.location = location;
newAssetRequest.creationDate = [NSDate date];
placeholderAsset = newAssetRequest.placeholderForCreatedAsset;
} completionHandler:^(BOOL success, NSError *error) {
if(success){
PHAsset *asset = [self getAssetFromlocalIdentifier:placeholderAsset.localIdentifier];
completionBlock(asset, YES);
} else {
completionBlock(nil, NO);
}
}];
можно получить новый PHAsset.
Я обновил ответ, включив в него возврат любого типа актива, а также более простой / чистый способ возврата актива.
Нет необходимости в проводнике соревнований.
func fetchLastAsset() -> PHAsset? {
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
fetchOptions.fetchLimit = 1
let fetchResult = PHAsset.fetchAssets(with: fetchOptions)
return fetchResult.firstObject
}