文档章节

iOS 应用扩展开发 - Photo Editing Extension

RDeveloper
 RDeveloper
发布于 2017/01/03 10:23
字数 1493
阅读 29
收藏 0
iOS

概述

应用扩展 (App Extension) 是 iOS 8 和 OS X 10.0 开始加入的一个非常重要的特性。它可以使应用与应用,应用与系统之间能够方便地进行数据交换和处理,而不需要打开这个应用。我们把支持扩展的系统区域称为扩展接入点 (Extension Point)。对于 iOS 来说,目前共有8种应用扩展类型,如下所示:

  • Action - 动作扩展,可以对上下文内容进行判断,然后发送到应用
  • Custom Keyboard - 自定义键盘,开发者可以开发一个键盘来替代系统默认键盘
  • Document Provider - 文档提供者,可以直至在多个文件存储服务之间管理文件,而不需要创建和拷贝
  • Photo Editing - 照片编辑扩展,可以在系统的照片应用中加入第三方的图片编辑功能
  • Share - 分享扩展,可以自定义分享选项
  • Today - 可以在下拉菜单中加入一个自定义的 Widget
  • Audio Unit - 允许应用提供类似于 GarageBand 或 Logic Pro X 的声音处理功能
  • Content Block - 可以为 Safari 提供一个屏蔽列表

应用扩展不能单独提交审核,它必须依附于你的某个应用一起提交,这个应用称为该扩展的容器 app (container app) 。但扩展和它的容器 app 是2个独立的进程,可以各自独立运行,互不相关。 而调用扩展的应用我们称为宿主 app (host app),扩展的生命周期依赖于其宿主 app,从宿主 app调用该扩展,到扩展完成任务返回到宿主 app而结束。

Photo Editing Extension

接下来,为了加深对扩展的了解,我为我的应用 Color Tint 加入了照片编辑扩展的功能。通过这个扩展,用户可以在系统的照片应用中对图片加上不同的颜色的处理。

添加扩展 Target

扩展是项目中单独的一个 Target。打开项目工程 Color Tint, 创建一个新的 Target,选择"Photo Editing Extension",如图 :

输入图片说明

点击下一步,为扩展起个名字: PhotoEditingExtension,点击"Finish ",如图:

输入图片说明

Xcode 会提示已经创建了一个 "PhotoEditingExtension" 的 scheme,点击"Activate"激活即可。

输入图片说明

扩展支持的类型

"Photo Editing Extension" 支持3中类型的数据: Image, Video, LivePhoto,我的应用 Color Tint 只支持 Image类型。可在 Info.plist 中配置,如图:

输入图片说明

扩展的 UI 设计

工程创建后会默认创建一个 PhotoEditingViewController.swift 和一个 MainInterface.storyboard 的文件,里面包含了扩展的一些基本回调接口,接下来就和编写普通 app 一样,用 Storyboard 设计 UI 布局,在UIViewController 里编写处理逻辑。

UI 很简单,主要由一个 UIImageView 和 一个 UICollectionView 组成,UIImageView 占满整个屏幕,用于展示处理后的图片;UICollectionView 放在底部,用于展示一组图片的预览效果图,用户点击这些预览图就能对图片进行处理。

输入图片说明

加入对应的 outlets 并设置好对应关系

@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var imageView: UIImageView!​

具体的 UI 代码这里就不一一列出来了,我们主要关注的是扩展接口的调用和处理逻辑

PHContentEditingController 协议

我们刚才创建的 "PhotoEditingViewController" 类遵从了 PHContentEditingController 协议,我们要实现以下方法:

  • func canHandle(_ adjustmentData: PHAdjustmentData) -> Bool: 如果你的扩展应用能对之前的编辑生效,则返回 true, 否则返回 false
func canHandle(_ adjustmentData: PHAdjustmentData) -> Bool {
    // Inspect the adjustmentData to determine whether your extension can work with past edits.
    // (Typically, you use its formatIdentifier and formatVersion properties to do this.)
    return true
}
  • func startContentEditing(with contentEditingInput: PHContentEditingInput, placeholderImage: UIImage): 这个方法在扩展被调用前调用,是扩展的开始方法,获取一个 PHContentEditingInput 对象和一个 UIImage 对象 (原图或已编辑过的图)
func startContentEditing(with contentEditingInput: PHContentEditingInput, placeholderImage: UIImage) {
    
    // Present content for editing, and keep the contentEditingInput for use when closing the edit session.
    // If you returned true from canHandleAdjustmentData:, contentEditingInput has the original image and adjustment data.
    // If you returned false, the contentEditingInput has past edits "baked in".
    self.input = contentEditingInput
    
    if self.input.mediaType != .image { // 只处理Image类型
        return
    }
    
    // Read adjustment data to choose (again) the last chosen filter.
    var colorName : String?
    if let adjustmentData = self.input.adjustmentData {
        do {
            colorName = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(adjustmentData.data as NSData) as? String
        } catch {
            print("can't unarchive adjustment data, reverting to default filter")
        }
    }
    
    if colorName != nil {
        self.inputColorName = colorName!
        for colorItem in ColorTintManager.shared().colors {
            if colorItem.name.compare(self.inputColorName) == ComparisonResult.orderedSame {
                self.colorItem = colorItem
                break
            }
        }
    }
    
    ColorTintManager.shared().setNewImage(placeholderImage)
    self.imageView.image = placeholderImage
    self.bgImageView.image = self.imageView.image
    self.collectionView.reloadData()
}
  • func finishContentEditing(completionHandler: @escaping ((PHContentEditingOutput?) -> Void)): 这个方法在图片被编辑完成后调用,是扩展的结束方法,会创建一个 PHContentEditingInput 对象(包含处理后的数据), 并返回给宿主应用
func finishContentEditing(completionHandler: @escaping ((PHContentEditingOutput?) -> Void)) {
    // Update UI to reflect that editing has finished and output is being rendered.
    
    // Render and provide output on a background queue.
    
    DispatchQueue.global().async {
        
        // Create editing output from the editing input.
        let output = PHContentEditingOutput(contentEditingInput: self.input)
        
        // Provide new adjustments and render output to given location.
        if self.input.mediaType == .image {
            if self.colorItem != nil && self.colorItem!.name.compare(self.inputColorName) != ComparisonResult.orderedSame {
                
                output.adjustmentData = PHAdjustmentData(
                    formatIdentifier: self.formatIdentifier,
                    formatVersion: self.formatVersion,
                    data: NSKeyedArchiver.archivedData(withRootObject: self.colorItem!.name)
                )
                _ = self.imageView.image?.write(to: output.renderedContentURL)
            }
        }
        
        // Call completion handler to commit edit to Photos.
        completionHandler(output)
        
        // Clean up temporary files, etc.
    }
}
  • var shouldShowCancelConfirmation: Bool: 用户点击取消按钮时调用,是否弹出确认菜单
var shouldShowCancelConfirmation: Bool {
    // Determines whether a confirmation to discard changes should be shown to the user on cancel.
    // (Typically, this should be "true" if there are any unsaved changes.)
    return false
}
  • func cancelContentEditing(): 用户点击取消按钮时调用,用于释放不必要的资源
func cancelContentEditing() {
    // Clean up temporary files, etc.
    // May be called after finishContentEditingWithCompletionHandler: while you prepare output.
}

运行测试

一切准备好后,打包并上传到 TestFlight,然后就可以进行测试了。 打开系统的照片应用,选择一张照片,进入编辑模式

输入图片说明

在底部的工具栏上有个三个点的图标,点击图标,选择 "Color Tint",就可以在该扩展中编辑图片了

输入图片说明

这就是该扩展的最终UI展示:

输入图片说明

总结

通过 "Color TInt" 这个应用,我掌握了 "Photo Editing Extension" 这种扩展的编写,也对 iOS 的扩展有了更深入的了解,相信其他类型的扩展也是大同小异。要获取更多信息,可以参考苹果的官方文档 App Extension Programming Guide

© 著作权归作者所有

共有 人打赏支持
RDeveloper
粉丝 4
博文 26
码字总数 8379
作品 0
广州
高级程序员
私信 提问
使用 Xamarin 开发 iOS 键盘扩展(含网络访问)

版权声明:本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/...

walter lv
02/24
0
0
LivePhoto开发,你要知道的知识点

前言 Apple从iPhone6s开始支持Live Photo。Live Photo 会录下拍照前后 1.5 秒所发生的一切,因此用户获得的不仅仅是一张精美照片,还有拍照前后时刻的动作和声音。具体的操作可以参见拍照和编...

zhanggui
2018/07/09
0
0
百里挑一:21 个优质 Swift 开源 App

Mybridge AI 根据代码质量和 star 排名从 900 多个开源项目中选出 21 个开源项目。 1:Firefox iOS [Official] Firefox iOS app built in Swift (Github Stars: 5,906). 2:WordPress for i......

局长
2016/09/01
7.3K
7
10个优秀Objective-C和iOS开发在线视频教程

如果你自己开发iOS应用,你肯定会发现网上有很多资源。学习编程的一个最好的方法就是自己写代码,而开始写代码的最快的方式就是看其他人怎么写。我们从海量视频和学习网站中整理出了我们认为...

mingxun
2014/05/09
0
0
unity中使用protobuffer作为网络通讯封包协议的实现和流程

一 使用的库 protobuffer 有两个c#实现,其中protobuffer-csharp 这个版本 比较适合跨语言开发,这个版本模仿java 实现;在ios上面,我们要使用 lite 版本,同时需要修改代码 却掉 pluginre...

李勇2
2015/02/28
0
0

没有更多内容

加载失败,请刷新页面

加载更多

IOS  学习记录

1.StackView=>IOS 9及以上支持 2.布局方式: AutoLayout / StackView 堆布局 (线性布局) 3.屏幕适配 (资源分辨率、设计分辨率、屏幕分辨率) Size Class技术 可以针对 屏幕的方向进行设置...

萨x姆
33分钟前
0
0
第四次工业革命:自主经济的崛起

https://36kr.com/p/5170370.html

shengjuntu
昨天
3
0
Cloud Native 与12-Factor

12-Factor(twelve-factor),也称为“十二要素”,是一套流行的应用程序开发原则。Cloud Native架构中使用12-Factor作为设计准则。 12-Factor 的目标在于: 使用标准化流程自动配置,从而使...

waylau
昨天
9
0
java多线程2

“非线程安全”问题存在于“实例变量”中,如果是方法内部的私有变量,则不存在线程安全问题。这是因为方法内部的变量都是私有造成的。 synchronized 获取的都是对象锁。如果多个线程访问多个...

一滴水穿石
昨天
4
0
今天的学习

1,document.location.href:获取整个url 2,str.split(' '):用字符分割字符串 3,$this->load->library(' '):引用图像处理类 4,$this->load->library(' '):引用Email类 5,特殊访问指针$th......

墨冥
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部