照片编辑扩展 - 将图像还原为原始图像
Photo Editing Extension - Revert Image to Original
我正在为 iOS 开发照片编辑扩展程序,捆绑在提供相同照片编辑功能的容器应用程序中。
为了重用代码,我有一个视图控制器 class 采用了所需的 PHContentEditingController
协议,我将其子class编辑为同时用作应用程序扩展,以及作为容器应用程序的 "working screen"。
在编辑扩展中, 控制器的方法由照片应用程序的编辑会话调用,如 Apple 文档和各种教程中所述可以在网上找到。
在容器应用上,另一方面,我首先通过UIImagePickerController
class,然后直接在我的 "work" 视图控制器上手动启动编辑会话,如下所示:
// 'work' is my view controller which adopts
// `PHContentEditingController`. 'workNavigation'
// embeds it.
let options = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = { (adjustmentData) in
return work.canHandle(adjustmentData)
}
asset.requestContentEditingInput(with: options, completionHandler: { [weak self] (input, options) in
// (Called on the Main thread on iOS 10.0 and above)
guard let this = self else {
return
}
guard let editingInput = input else {
return
}
work.asset = asset
work.startContentEditing(with: editingInput, placeholderImage: editingInput.displaySizeImage!)
this.present(workNavigation, animated: true, completion: nil)
})
当用户完成编辑时,工作视图控制器调用finishContentEditing(completionHandler:
自身来完成会话:
self.finishContentEditing(completionHandler: {(output) in
// nil output results in "Revert" prompt.
// non-nil output results in "Modify" prompt.
let library = PHPhotoLibrary.shared()
library.performChanges({
let request = PHAssetChangeRequest(for: self.asset)
request.contentEditingOutput = output
}, completionHandler: {(didSave, error) in
if let error = error {
// handle error...
} else if didSave {
// proceed after saving...
} else {
// proceed after cancellation...
}
})
})
在编辑会话中,用户可以 'clear' 以前的编辑作为 调整数据 传递,有效地将图像恢复到其原始状态。
我注意到,如果我通过使用 nil
作为参数(而不是有效的 PHContentEditingOutput
对象)调用传递给 finishContentEditing(completionHandler:)
的完成处理程序来完成编辑,照片框架将提示用户 "revert" 图像而不是 "modifying" 它:
func finishContentEditing(completionHandler: @escaping (PHContentEditingOutput?) -> Void) {
guard let editingInput = self.editingInput, let inputURL = editingInput.fullSizeImageURL else {
return completionHandler(nil)
}
if editingInput.adjustmentData != nil && hasUnsavedEdits == false {
// We began with non-nil adjustment data but now have
// no outstanding edits - means REVERT:
return completionHandler(nil)
}
// (...proceed with writing output to url...)
但是,这仅在容器应用程序 运行 时有效。 如果我在 扩展 中尝试相同的技巧(即加载包含先前编辑的图像,重置它们,然后点击 'Done')我收到可怕的 "Unable to Save Changes" 消息...
从照片编辑扩展程序中恢复以前对图像的编辑的正确方法是什么?
几个月后,仍然没有答案,所以我不情愿地采用了这个解决方法(这仍然比错误警报更可取):
当用户从照片扩展 UI 中点击 "Done" 并且图像没有应用任何编辑时(因为用户重置了以前的编辑,或者没有对图像应用任何更改)全新图像),从 finishContentEditing(completionHandler:)
:
中执行以下操作
创建完全没有可见变化的调整数据 ("null effect") 并将其存档为 Data
.
使用上面的 "null effect" 数据创建一个 PHAdjustmentData
实例,正确设置 formatVersion
和 formatIdentifier
。
从会话开始时传递的编辑输入创建一个PHContentEditingOutput
实例(像往常一样),并设置上面创建的调整数据。
从编辑输入inputURL
属性中读取未修改的图片,未修改写入[=84] =] 由 PHContentEditingOutput
实例的 renderedContentURL
属性.
指定
调用 completionHandler
块,传递编辑输出实例(正常)。
结果:图像以原始状态保存(未应用任何效果),未出现任何警报或错误。
缺点:库资源保持在'edited'状态(因为我们通过了非nil编辑输出和调整数据,没有其他选择),所以下次用户尝试从 Photos.app 编辑它时,红色的 'Revert' 按钮将会出现:
然而,选择 'revert' 导致图像数据 无可见变化 (呃!),这可以是让用户感到困惑。
——
更新
我检查了内置“标记”扩展的功能:
...这与我上面的解决方法一致,所以我想这是最好的办法了。
我正在为 iOS 开发照片编辑扩展程序,捆绑在提供相同照片编辑功能的容器应用程序中。
为了重用代码,我有一个视图控制器 class 采用了所需的 PHContentEditingController
协议,我将其子class编辑为同时用作应用程序扩展,以及作为容器应用程序的 "working screen"。
在编辑扩展中, 控制器的方法由照片应用程序的编辑会话调用,如 Apple 文档和各种教程中所述可以在网上找到。
在容器应用上,另一方面,我首先通过UIImagePickerController
class,然后直接在我的 "work" 视图控制器上手动启动编辑会话,如下所示:
// 'work' is my view controller which adopts
// `PHContentEditingController`. 'workNavigation'
// embeds it.
let options = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = { (adjustmentData) in
return work.canHandle(adjustmentData)
}
asset.requestContentEditingInput(with: options, completionHandler: { [weak self] (input, options) in
// (Called on the Main thread on iOS 10.0 and above)
guard let this = self else {
return
}
guard let editingInput = input else {
return
}
work.asset = asset
work.startContentEditing(with: editingInput, placeholderImage: editingInput.displaySizeImage!)
this.present(workNavigation, animated: true, completion: nil)
})
当用户完成编辑时,工作视图控制器调用finishContentEditing(completionHandler:
自身来完成会话:
self.finishContentEditing(completionHandler: {(output) in
// nil output results in "Revert" prompt.
// non-nil output results in "Modify" prompt.
let library = PHPhotoLibrary.shared()
library.performChanges({
let request = PHAssetChangeRequest(for: self.asset)
request.contentEditingOutput = output
}, completionHandler: {(didSave, error) in
if let error = error {
// handle error...
} else if didSave {
// proceed after saving...
} else {
// proceed after cancellation...
}
})
})
在编辑会话中,用户可以 'clear' 以前的编辑作为 调整数据 传递,有效地将图像恢复到其原始状态。
我注意到,如果我通过使用 nil
作为参数(而不是有效的 PHContentEditingOutput
对象)调用传递给 finishContentEditing(completionHandler:)
的完成处理程序来完成编辑,照片框架将提示用户 "revert" 图像而不是 "modifying" 它:
func finishContentEditing(completionHandler: @escaping (PHContentEditingOutput?) -> Void) {
guard let editingInput = self.editingInput, let inputURL = editingInput.fullSizeImageURL else {
return completionHandler(nil)
}
if editingInput.adjustmentData != nil && hasUnsavedEdits == false {
// We began with non-nil adjustment data but now have
// no outstanding edits - means REVERT:
return completionHandler(nil)
}
// (...proceed with writing output to url...)
但是,这仅在容器应用程序 运行 时有效。 如果我在 扩展 中尝试相同的技巧(即加载包含先前编辑的图像,重置它们,然后点击 'Done')我收到可怕的 "Unable to Save Changes" 消息...
从照片编辑扩展程序中恢复以前对图像的编辑的正确方法是什么?
几个月后,仍然没有答案,所以我不情愿地采用了这个解决方法(这仍然比错误警报更可取):
当用户从照片扩展 UI 中点击 "Done" 并且图像没有应用任何编辑时(因为用户重置了以前的编辑,或者没有对图像应用任何更改)全新图像),从 finishContentEditing(completionHandler:)
:
创建完全没有可见变化的调整数据 ("null effect") 并将其存档为
Data
.使用上面的 "null effect" 数据创建一个
PHAdjustmentData
实例,正确设置formatVersion
和formatIdentifier
。从会话开始时传递的编辑输入创建一个
PHContentEditingOutput
实例(像往常一样),并设置上面创建的调整数据。从编辑输入
inputURL
属性中读取未修改的图片,未修改写入[=84] =] 由PHContentEditingOutput
实例的renderedContentURL
属性. 指定
调用
completionHandler
块,传递编辑输出实例(正常)。
结果:图像以原始状态保存(未应用任何效果),未出现任何警报或错误。
缺点:库资源保持在'edited'状态(因为我们通过了非nil编辑输出和调整数据,没有其他选择),所以下次用户尝试从 Photos.app 编辑它时,红色的 'Revert' 按钮将会出现:
然而,选择 'revert' 导致图像数据 无可见变化 (呃!),这可以是让用户感到困惑。
——
更新我检查了内置“标记”扩展的功能:
...这与我上面的解决方法一致,所以我想这是最好的办法了。