и это тоже не работает, гениально!
ющая функция загружает фотографию, редактирует прикрепленные к ней метаданные exif и сохраняет ее обратно. Кажется, что эта функция работает только для фотографий, к которым уже прикреплены данные PHAdjustmentData, т.е. фотографий, которые были отредактированы ранее с помощью другого приложения. Если фотография не была отредактирована, она завершается ошибкой в блоке executeChanges () и печатает
Failed to save. Error: Optional(Error Domain=NSCocoaErrorDomain Code=-1 "(null)").
Почему это терпит неудачу в этой ситуации? Просматривая переполнение стека, я видел несколько других версий этого вопроса, но ни одна из них, похоже, не была решена. Я знаю, что это не получится, если сохраненное изображение будет в формате PNG, но мое исходное изображение имеет формат JPEG, поэтому сохраненное изображение также является JPEG.
func editPhotoProperties(_ asset: PHAsset) {
let options = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = { data in
return false
}
asset.requestContentEditingInput(with: options) { input, info in
if let input = input {
let adjustmentData = PHAdjustmentData(formatIdentifier:"viewfinder", formatVersion:"1.0", data:"viewfinder".data(using:.utf8)!)
let output = PHContentEditingOutput(contentEditingInput:input)
output.adjustmentData = adjustmentData
do {
let imageData = try Data(contentsOf:input.fullSizeImageURL!)
} catch {
print("Failed to load data")
return
}
let properties = getImageDataProperties(imageData)!
let properties2 = properties.mutableCopy() as! NSMutableDictionary
// edit properties2
...
let newImageData = addImageProperties(imageData: imageData, properties: properties2)
do {
try newImageData!.write(to: output.renderedContentURL, options: .atomic)
} catch {
print("Failed to write to disk")
return
}
PHPhotoLibrary.shared().performChanges({
let changeRequest = PHAssetChangeRequest(for:asset)
changeRequest.contentEditingOutput = output
}) { success, error in
if !success {
print("Failed to save. Error: \(String(describing:error))")
}
}
}
}
}
func getImageDataProperties(_ data: Data) -> NSDictionary? {
if let imageSource = CGImageSourceCreateWithData(data as CFData, nil) {
if let dictionary = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) {
return dictionary
}
}
return nil
}
// add image properties (exif, gps etc) to image
func addImageProperties(imageData: Data, properties: NSDictionary?) -> Data? {
// create an imagesourceref
if let source = CGImageSourceCreateWithData(imageData as CFData, nil) {
// this is of type image
if let uti = CGImageSourceGetType(source) {
// create a new data object and write the new image into it
let destinationData = NSMutableData()
if let destination = CGImageDestinationCreateWithData(destinationData, uti, 1, nil) {
// add the image contained in the image source to the destination, overidding the old metadata with our modified metadata
CGImageDestinationAddImageFromSource(destination, source, 0, properties)
if CGImageDestinationFinalize(destination) == false {
return nil
}
return destinationData as Data
}
}
}
return nil
}