ios - 照片编辑扩展 - 将图像还原为原始图像
问题描述
我正在为 iOS 开发一个照片编辑扩展程序,它捆绑在一个提供相同照片编辑功能的容器应用程序中。
为了重用代码,我有一个视图控制器类,它采用了所需的PHContentEditingController
协议,我将它子类化为应用程序扩展的主界面和容器应用程序的“工作屏幕”。
在编辑扩展上,控制器的方法由照片应用程序的编辑会话调用,如 Apple 文档和您可以在网络上找到的各种教程中所述。
另一方面,在容器应用程序上,我首先PHAsset
通过类获取一个实例UIImagePickerController
,然后直接在我的“工作”视图控制器上手动启动编辑会话,如下所示:
// '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...
}
})
})
在编辑会话中,用户可以“清除”作为调整数据传递的先前编辑,从而有效地将图像恢复到其原始状态。我注意到,如果我通过调用作为其参数(而不是有效对象)传递给finishContentEditing(completionHandler:)
的完成处理程序来完成编辑,照片框架将提示用户“恢复”图像而不是“修改”它:nil
PHContentEditingOutput
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...)
但是,这仅在从容器应用程序运行时有效。如果我从扩展程序中尝试相同的技巧(即,加载包含以前编辑的图像,重置它们,然后点击“完成”),我会收到可怕的“无法保存更改”消息......
从照片编辑扩展程序中将以前的编辑恢复到图像的正确方法是什么?
解决方案
几个月后,仍然没有答案,所以我不情愿地采用了这个解决方法(这仍然比错误警报更可取):
当用户从照片扩展 UI 中点击“完成”并且图像没有应用编辑(因为用户重置以前的编辑,或者没有对全新图像应用任何更改),从内部执行以下操作 finishContentEditing(completionHandler:)
:
创建完全没有可见变化的调整数据(“无效效果”)并将其存档为
Data
.PHAdjustmentData
使用上面的“空效果”数据创建一个实例,formatVersion
并formatIdentifier
正确设置。PHContentEditingOutput
从会话开始时传递的编辑输入创建一个实例(像往常一样),并设置上面创建的调整数据。inputURL
从编辑输入的属性中读取未修改的图像,并将其未修改PHContentEditingOutput
地写入实例renderedContentURL
属性指定的 url 。调用
completionHandler
块,传递编辑输出实例(正常)。
结果:图像以其原始状态保存(未应用效果),并且不会出现警报或错误。
缺点:库资源仍处于“已编辑”状态(因为我们传递了非零编辑输出和调整数据,没有其他选择),所以下次用户尝试从 Photos.app 编辑它时,红色将出现“还原”按钮:
但是,选择“还原”会导致图像数据没有可见的变化(呃!),这可能会让用户感到困惑。
——
更新我检查了内置的“标记”扩展做了什么:
...这与我上面的解决方法是一致的,所以我想这是可以做到的最好的。
推荐阅读
- xamarin - PreEmptive Dotfuscator:Xamarin.Android 项目的混淆失败,并带有“对未定义类 'UNKNOWN_OWNER' 的引用”
- vim - Applescript 如果没有添加文件
- java - 控制选择框 JavaFX
- python - 从 pandas 数据框中获取统计信息:按日期划分的唯一字段
- node.js - 通过连接 ArrayBuffers 客户端实时流式传输视频
- r - rvest 疑难解答
- reactjs - 如何在 React 和 Express 之间共享模式?
- mysql - 有没有办法从 rubymotion 连接到 MySQL 8?
- r - R从列中提取多个变量
- javascript - 将数组写入单行