跳至主要内容

15分钟搞定iOS9 Quick Actions

苹果在iOS 9中引入的 3D touch功能,相关的API分为3个部分:


  • Quick actions

  • Peek and Pop

  • Pressure Sensitivity







在iPhone 6s或者 iPhone 6s Plus上,当用户按压app icon的时候,会弹出Quick Action,当用户选择其中的action的时候,app会启动并接收到相应的消息。

本文介绍如何给App添加Quick Action支持。

开发环境

官方文档说用Xcode 7.0上的模拟器不支持 3D Touch,必须使用支持 3D Touch的设备进行调试。

@conradev开源的SBShortcutMenuSimulator让我们可以在Xcode 7.0上使用模拟器进行调试。

Build

按照https://github.com/DeskConnect/SBShortcutMenuSimulator上给出的文档进行操作。

在Mac的Termnial执行:

git clone https://github.com/DeskConnect/SBShortcutMenuSimulator.git

cd SBShortcutMenuSimulator

make


开启模拟器

在Mac的Termnial执行:

xcrun simctl spawn booted launchctl debug system/com.apple.SpringBoard --environment DYLD\_INSERT\_LIBRARIES=$PWD/SBShortcutMenuSimulator.dylib\`

xcrun simctl spawn booted launchctl stop com.apple.SpringBoard\`


下面的命令可以在模拟器上显示日历的Quick Action echo 'com.apple.mobilecal' | nc 127.0.0.1 8000

你只需要把echo后面的bundle id换成你自己的demo的bundle id就可以进行测试。

继续介绍如何给你的App加上Quick Actions的支持。

Home Screen Quick Actions

Quick Actions分为2类:static与dynamic。

static quick actions。
在App的Info.plist文件中UIApplicationShortcutItems这个数组中定义。UIApplicationShortcutItems的每一项都需要定义UIApplicationShortcutItemType、 UIApplicationShortcutItemTitle。
其它字段都是optional的。
如下图所示:

dynamic quick actions
设置UIApplication对象的shortCutItems属性动态创建UIApplicationShortcutItem。

如何响应用户的操作

app delegate中的application(_:performActionForShortcutItem:completionHandler:)用来响应用户的操作。可以在这里处理响应的action(static与dynamic都在此处理)。

相关代码

@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate {

enum ShortcutType: String {
case Green = "Green"
case Red = "Red"
}

var window: UIWindow?

static let applicationShortcutUserInfoIconKey = "applicationShortcutUserInfoIconKey"
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]()?) -\> Bool {
var launchedFromShortCut = false
//Check for ShortCutItem
if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey]() as? UIApplicationShortcutItem {
launchedFromShortCut = true
handleShortCutItem(shortcutItem)
}

let item1 = UIApplicationShortcutItem(type: ShortcutType.Green.rawValue, localizedTitle: "dynamic shortcut 1, green")
let item2 = UIApplicationShortcutItem(type: ShortcutType.Red.rawValue, localizedTitle: "dynamic shortcut 2, red")
let item3 = UIApplicationShortcutItem(type: ShortcutType.Green.rawValue, localizedTitle: "dynamic shortcut 3, green")
let item4 = UIApplicationShortcutItem(type: ShortcutType.Red.rawValue, localizedTitle: "dynamic shortcut 4, red")
let item5 = UIApplicationShortcutItem(type: ShortcutType.Green.rawValue, localizedTitle: "dynamic shortcut 5, green")
application.shortcutItems = [item1, item2, item3, item4, item5]()

// Return false incase application was lanched from shorcut to prevent
// application(\_:performActionForShortcutItem:completionHandler:) from being called
return !launchedFromShortCut
}

func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: Bool -\> Void) {
let handledShortCutItem = handleShortCutItem(shortcutItem)
completionHandler(handledShortCutItem)
}

func handleShortCutItem(shortcutItem: UIApplicationShortcutItem) -\> Bool {
var handled = false
//Get type string from shortcutItem
if let shortcutType = ShortcutType.init(rawValue: shortcutItem.type) {
//Get root navigation viewcontroller and its first controller
let rootNavigationViewController = window!.rootViewController as? UINavigationController
let rootViewController = rootNavigationViewController?.viewControllers.first as UIViewController?
//Pop to root view controller so that approperiete segue can be performed
rootNavigationViewController?.popToRootViewControllerAnimated(false)

switch shortcutType {
case .Green:
rootViewController?.performSegueWithIdentifier(toGreenSeque, sender: nil)
handled = true
case.Red:
rootViewController?.performSegueWithIdentifier(toRedSeque, sender: nil)
handled = true
}
}

// 这里还可以动态设置,关闭添加的Quick Action。
// UIApplication.sharedApplication().shortcutItems = nil

return handled
}
}


需要注意的是,如果app启动的时候(比如之前app被kill掉),需要在 application:didFinishLaunchingWithOptions: 或者application:willFinishLaunchingWithOptions:中检查检查launchOptions字典中的UIApplicationLaunchOptionsShortcutItemKey来判断是否是通过Quick Action进入的app。

如果确实是从Quick Action进入的app,在application:didFinishLaunchingWithOptions:中处理完响应的action之后,需要返回false。

这样可以避免application(_:performActionForShortcutItem:completionHandler:)被调用到。

Quick Actions最多为4个

最多可以显示4个Quick Action(包含静态和动态)。
上面的代码可以看到,我们定义了2个静态的,试图添加5个动态的Quick Action,
application.shortcutItems = [item1, item2, item3, item4, item5];

执行效果如下图:



动态添加的只有item1, item2成功加入。

测试发现,动态添加Quick Action成功之后,即使系统重启,下次打开依然有效。第一次全新安装(但是不运行App),只会显示静态的Quick Action。(如有谬误,敬请指正,谢谢)

总结

发挥你的创意,给你的App添加Quick Action支持,让用户获得更好的体验吧。

评论

此博客中的热门博文

非公开 app

 1.对用户 用户只能通过特定链接才能使用该 app,其他使用和应用商店 app 一致。 2.对开发 a,以应用商店提交 app 的标准方式提交 app,在备注添加一行,写上“App 将用于非公开分发”,提交 app。 b,  填写非公开 app 申请,https://developer.apple.com/contact/request/unlisted-app/ c,等待审核,整个审核过程会比平常审核慢 2-5 个工作日,后续更新应该会正常。 app分发类型 非公开app ABM App Store 企业包 app分发类型 非公开app ABM App Store 企业包 是否需要https, 自己搭建托管环境 否,文件托管到 App Store 否,文件托管到 App Store 否,文件托管到App Store 是,需要自己托管,需要 https 环境,受信任的 ssl证书 是否可以直接在 App Store 搜索到 否 否 是 否 是否可以在 App Store 展示 应用信息,包括 在应用信息页面 手动点击更新 是 否 是 不上传到App Store无 App Store信息 在应用商店 更新列表点击更新 是 是 是 否 是否需要手 动更新app 开启App Store的自动更新,就自动更新,否则手动更新 开启App Store的自动更新,就自动更新,否则手动更新,只能点我的头像,更新列表里面去更新 开启App Store的自动更新,就自动更新,否则手动更新 必须去 app 里面 点击更新,或者 去下载页面去 下载最新的app 包是否会过期 否,只要账号正常 否,只要账号正常 否,只要账号正常 是,包里面有 两个证书,虽 然只打包进一 个证书文件, 但那个证书文 件关联另一个, (打包的时候一 起使用)打包 的文件有效期1 年,关联的文 件有效期 3 年。打包的时候 是否允许马甲, 重复应用(相似 ui,相似代码) 是 是 否 是 应用商店审核要求 有,除了马甲应用,其他都一样 有,除了马甲应用,其他都一样 不允许马甲应用,其他都一样 不需要审核 是否能用其他 开发者账号上传 我们的定制版应用 未知 可以 不允许 无app store 应用上传权限 哪些版本可以 改成该版本 1.App Store包 2.企业包 1.企业包 1.企业包 ...

非公开 app 分发

非公开 app  简介 app 除了不能搜索到该 app,其他使用和普通的应用商店一致。 只需要使用对应的链接就可以跳转到该 app 。 非公开 app 上传审核流程 1.appstore connect 新建应用,配置和普通上传应用商店(公开应用)完全一致 2.在备注里面加上一行:该 app 属于非公开 app,提交 app 3.去非公开 app 申请链接app 为非公开 app,https://developer.apple.com/contact/request/unlisted-app/ 4.审核被拒,有两部分,一个是普通appstore审核被拒(可能没有),最后还会多上一个非公开 app 审核被拒的部分。等待只有非公开 app 审核被拒的问题后,再等上两天左右就好了。 5.审核通过后,会通过邮件发送该 app 的链接,此链接其实和其他 app 的链接格式一致,并无区别,唯一的区别是该 app 在应用商店搜索不到。

企业包下载安装问题

1. 下载后,去设置 ---> 通用 ---> VPN与设备管理(设备管理),找到对应的企业证书名称,选择信任即可正常打开软件使用。 2. app过期,或者系统时间手动修改到app过期时间,安装包无法正常使用,手动调整系统时间到正常时间即可正常运行。