Выбор изображения приводит к восстановлению в кадре камеры
У меня есть программа, в которой пользователь выбирает фотографию для показа на экране, а код автоматически помещает ее в пользовательский альбом. Но всякий раз, когда они выбирают картинку, она снова копирует ее в камеру, создавая дубликаты. Как я могу заставить это прекратить делать это?
func fetchAssetCollectionForAlbum() -> PHAssetCollection? {
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %@", albumName)
// fetch the asset for the album
let collection = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
var picturePlaceHolder: PHObjectPlaceholder? = nil
if let _: AnyObject = collection.firstObject {
return collection.firstObject
}
return nil
}
func save(image: UIImage) {
if assetCollection == nil {
return
}
PHPhotoLibrary.shared().performChanges({
let assetChangeRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
let assetPlaceHolder = assetChangeRequest.placeholderForCreatedAsset
let albumChangeRequest = PHAssetCollectionChangeRequest(for: self.assetCollection)
let enumeration: NSArray = [assetPlaceHolder!]
albumChangeRequest!.addAssets(enumeration)
}, completionHandler: nil)
}
1 ответ
Я разместил похожий вопрос: Swift 3 или 4 Сохранение в пользовательский альбом создает дубликаты изображений
Но я получил только сверчков. К счастью, я думаю, что нашел ответ. Я также отвечу на свой вопрос.
Код, который у вас есть (это был тот же код, что и у меня), - СОЗДАТЬ НОВЫЙ АКТИВ. Это полезно только для сохранения изображения в ваш пользовательский альбом после того, как пользователь сделал снимок с помощью камеры. Это для новых активов.
Однако для существующих активов вы не хотите создавать новый актив. Вместо этого вы хотите добавить существующий ресурс в пользовательский альбом. Для этого вам нужен другой метод. Вот код, который я создал, и он, кажется, работает. Имейте в виду, что вы должны будете сначала получить идентификатор ресурса, чтобы вы могли отправить его своему методу и получить доступ к существующему активу.
Итак, в вашем imagePickerController вы должны определить, выбрал ли пользователь существующее изображение или метод вызывается из нового действия камеры.
let pickerSource = picker.sourceType;
switch(pickerSource){
case .savedPhotosAlbum, .photoLibrary:
if(let url = info[UIIMagePickerControllerReferenceURL] as? NSURL{
let refURLString = refURL?.absoluteString;
/* value for refURLString looks something like assets-library://asset/asset.JPG?id=82A6E75C-EA55-4C3A-A988-4BF8C7F3F8F5&ext=JPG */
let refID = {function here to extract the id query param from the url string}
/*above gets you the asset ID, you can get the asset directly, but it is only
available in ios 11+.
*/
MYPHOTOHELPERCLASS.transferImage(toAlbum: "myalbumname", withID: refID!, ...)
}
break;
case .camera:
...
break;
}
Теперь, в вашем классе фотопомощи (или в любой функции где угодно, независимо от того), чтобы РЕДАКТИРОВАТЬ актив вместо создания нового, это то, что у меня есть. Я предполагаю, что переменная changeRequest может быть опущена. Я просто играл, пока не понял это правильно. Просматривая совершенно нелепые документы Apple, я смог, по крайней мере, заметить, что есть и другие способы игры. Я обнаружил, что параметр NSFastEnumeration может быть NSArray из PHAssets, а не просто заполнителем объектов PHObjectPlaceholder.
public static func transferImage(toAlbum albumName:String, withID imageID:String, onSuccess success:@escaping(String)->Void, onFailure failure:@escaping(Error?)->Void){
guard let album = self.getAlbum(withName: albumName) else{
... failure here, albumNotFoundError
return;
}
if(self.hasImageInAlbum(withIdentifier: imageID, fromAlbum: albunName)){
... failure here, image already exists in the album, do not make another
return;
}
let theAsset = self.getExistingAsset(withLocalIdentifier: imageID);
if(theAsset == nil){
... failure, no asset for asset id
return;
}
PHPhotoLibrary.shared().performChanges({
let albumChangeRequest = PHAssetCollectionChangeRequest(for: album);
let changeRequest = PHAssetChangeRequest.init(for: theAsset!);
let enumeration:NSArray = [theAsset!];
let cnt = album.estimatedAssetCount;
if(cnt == 0){
albumChangeRequest?.addAssets(enumeration);
}else{
albumChangeRequest?.inserAssets(enumeration, at: [0]);
}
}){didSucceed, error) in
OperationQueue.main.addOperation({
didSucceed ? success(imageID) : failure(error);
})
}
}
Таким образом, это почти то же самое, за исключением того, что вместо создания запроса на создание актива и создания заполнителя для созданного актива, вместо этого вы просто используете существующий идентификатор актива для извлечения существующего актива и добавления существующего актива в NSasray addasset / insertasset. параметр вместо недавно созданного объекта-заполнителя.