跳至主要内容

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 分发

非公开 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 在应用商店搜索不到。

非公开 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.企业包 ...

iOS企业包下载中的下载

 首先,链接格式是itms-services://?action=download-manifest&url=https://xxxx.plist plist文件格式是 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>items</key> <array> <dict> <key>assets</key> <array> <dict> <key>kind</key> <string>software-package</string> <key>url</key> <string>ipa的完整的url,可以是http的</string> </dict> <dict> <key>kind</key> <string>display-image</string> <key>url</key> <string>小图的完整的url,可以是http的</string> </dict> <dict> <key>kind</key> <string>full-size-image</string> <key>url</key...