文章目录
  1. 1. 简介
  2. 2. 主屏幕 Quick Actions
  3. 3. Peek and Pop
  4. 4. UIPreviewInteraction
  5. 5. Low-Level Force API

简介

iOS 9+ / iPhone 6s +

  • 提供访问app特性的便捷方式;
  • 沉浸式的交互方式
  • 提供连续性的用户体验(Peek and Pop)

主屏幕 Quick Actions

2 types:

  • Static
    在Info.plist中定义

  • Dynamic
    在app加载后通过代码动态创建;可以包含一个系统图标/自定义图标/通讯录地址

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    // 1. create a ShortcutIcon
    let contactName = "Lexi Torres"
    var cocntactIcon: UIApplicationShortcutIcon? = nil
    if CNContactStore.authorizationStatus(for: .contacts) == .authorized {
    let predicate = CNContact.predicateForContacts(matchingName: contactName)
    let contacts = try? CNContactStore().unifiedContacts(matching: predicate, keysToFetch: [])
    if let contact = contacts?.first {
    contactIcon = UIApplicationShortcutIcon(contact: contact)
    }
    }
    let icon = contactIcon ?? UIApplicationShortcutIcon(type: .message)
    // 2. create action using the icon
    let type = "com.company.app.sendChatTo"
    let subtitle = "Send a chat"
    let shortcutItem1 = UIApplicationShortcutItem(type: type,
    localizedTitle: contactName ,
    localizedSubtitle: subtitle,
    icon: icon)
    // 3. add more shortcutItem if necessary
    ...
    let shortcutItems = [shortcutItem1, ...]
    // 4. register to application
    application.shortcutItems = shortcutItems

    处理action

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // on app activation
    func application(application: UIApplication,
    performActionFor shortcutItem: UIApplicationShortcutItem,
    completionHandler: @escaping(Bool) -> Void ){
    let didHandle: Bool = /* handle logic using shortcutItem */
    completionHandler(didHandle)
    }
    // on app launch, 在App完全退出的情况下,上面方法Handler返回的是NO。
    // 这就需要我们在下面方法中也加入相应的回调处理
    func application(application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    var performAdditionalHandling = true
    if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsKey.shortcutItem] as? UIApplicationShortcutItem {
    /* handle logic using shortcutItem */
    performAdditionalHandling = false
    }
    return performAdditionalHandling
    }

最佳实践:

  • 每个app都需要提供quick actions
  • 用于high-value的任务上
  • 使quick actions 可预测
  • quick actions的处理逻辑要注意向前兼容(Be prepared to handle dynamic quick actions from a previous version of your app)
  • 添加的功能不能只通过quick action才能使用

Peek and Pop

  • Registered View Controller
    需要实现 UIViewControllerPreviewingDelegate

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    // 1. Comforming previewing delegate
    class ChatTableViewControlelr: UITableViewController, UIViewControllerPreviewingDelegate {
    // 2. register
    override func viewDidLoad() {
    super.viewDidLoad()
    ...
    registerForPreviewing(with: self, sourceView: tableView)
    }
    // 3. previewing delegate implement
    func previewingContext(_ previewingContext: UIViewControllerPreviewing,
    viewControllerForLocation location: CGPoint) -> UIViewController? {
    guard let indexPath = tableView.indexPathForRow(at: location) else { return nil }
    let chatDetailViewController = ...
    chatDetailViewController.chatItem = chatItem(at: indexPath)
    let cellRect = tableView.rectForRow(at: indexPath)
    let sourceRect = previewingContext.sourceView.convert(cellRect, from: tableView)
    previewingContext.sourceRect = sourceRect
    return chatDetailViewController
    }
    func previewingContext(_ previewingContext: UIViewControllerPreviewing,
    commit viewControllerToCommit: UIViewController) {
    show(viewControllerToCommit, sender: self)
    }
    // optional actions
    override func previewActionItems() -> [UIPreviewActionItem] {
    let heart = UIPreviewAction(title: "heart", style: .default) { (action, viewController) in
    // Send a heart
    }
    }
    // 也可以用UIPreviewActionGroup() 包装一组actions
    let replyActions = [action1, action2]
    let sendReply = UIPreviewActionGroup(title: "a group reply" style: .default, actions: replyActions)
    return [heart, sendReply]
    }

其他的action styles: .selected, .destructive

  • 最佳实践
    • 能够被tapped的content应该支持 Peek and Pop
    • Return a preview view controller consistently
    • Don’t take too long in the previewing delegate
    • Set the previewing context sourceRect

UIPreviewInteraction

同样的Peek and Pop处理过程 + 自动Haptic Feedback + 自定义界面

  • 实现 UIPreviewInteractionDelegate

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    // 1. comfrom
    extension ChatDetailViewController: UIPreviewInteractionDelegate {
    var replyPreviewInteraction: UIPreviewInteraction!
    }
    // 2. create
    override func viewDidLoad() {
    super.viewDidLoad()
    ...
    replyPreviewInteraction = UIPreviewInteraction(view: view)
    replyPreviewInteraction.delegate = self
    }
    previewInteractionShouldBegin()
    // 3. preveiw transition
    func previewInteraction(_ previewInteraction: UIPreviewInteraction,
    didUPdatePreveiwTransition transitionProgress: CGFloat,
    ended: Bool) {
    // progress value [0, 1]
    updateForPreview(progress: transitionProgress)
    if ended {
    completePreview()
    }
    }
    // 4. cancel handling
    func previewInteractionDidCancel(_ previewInteraction: UIPreviewInteraction) {
    UIView.animate(withDuration: 0.4) {
    self.updateForPreview(progress: 0)
    self.resetToInitialAppearance()
    }
    }
    // 5. commit transition
    func previewInteraction(_ previewInteraction: UIPreviewInteraction,
    didUpdateCommitTransition transitionProgress: CGFloat,
    ended: Bool) {
    updateForCommit(progress: transitionProgress)
    if ended {
    completeCommit()
    }
    }

Low-Level Force API

Properties on UITouch: force and maximumPossibleForce

文章目录
  1. 1. 简介
  2. 2. 主屏幕 Quick Actions
  3. 3. Peek and Pop
  4. 4. UIPreviewInteraction
  5. 5. Low-Level Force API