iOS机制

3D Touch (一) —— Home Screen Quic

2022-04-05  本文已影响0人  刀客传奇

版本记录

版本号 时间
V1.0 2022.04.05 星期二 清明节

前言

3D TouchiPhone 6s+iOS9+之后新增的功能。其最大的好处在于不启动app的情况下,快速进入app中的指定界面,说白了,就是一个快捷入口。接下来几篇我们就一起看下相关的内容。

开始

首先看下主要内容:

了解如何将静态和动态主屏幕快速操作(Static and Dynamic Home Screen Quick Actions)集成到您的 SwiftUI iOS 应用中。内容来自翻译

接着看下写作环境:

Swift 5.5, iOS 15, Xcode 13

快捷操作(Quick actions)是让您的用户在主屏幕中快速访问您应用的常用功能的好方法。 iOS 13 引入了Quick actions的概念,用户可以在其中触摸并按住应用程序图标以显示一组快捷方式或操作(shortcuts or actions),以便直接从主屏幕执行。

默认情况下,所有应用程序都具有编辑主屏幕或删除应用程序的快捷操作:

开发者还可以提供自己的快捷操作,为用户提供常用应用功能的强大快捷方式。 iOS 相机应用程序具有拍摄不同类型的照片或录制视频的操作。购物应用程序可能会让您直接跳转到您的订单或愿望清单,而消息传递应用程序可能会显示您最喜欢的联系人,以便您轻松访问它们。

我相信您可以想出快捷操作可以使您的用户受益的方式。在本教程中,您将了解:

打开下载好的程序,Note Buddy 是一款具有一些基本功能的笔记应用程序:

打开项目,然后构建并运行。你会看到这个笔记页面:

为了增强 Note Buddy 的功能,您可以在 Models 组中找到 Note 模型及其关联的 NoteStore 类。

转到 SwiftUI,在 Views 组中,您有:

最后,AppMain 使用对 NoteStore 的引用和在 WindowGroup 中设置 NoteList 视图并正确注入适当环境值的主体来描述您的应用程序。

在你开始编码之前,是时候仔细看看这两种类型的快速操作是什么,以及它们是如何工作的。


Static vs. Dynamic Quick Actions

您可以使用两种类型的快速操作:静态和动态。

您将静态操作用于在您的应用程序中永远不会更改的操作,例如Mail应用程序的New Message操作。

如果您的操作可能在某些条件下发生变化或取决于特定数据或状态,请使用dynamic actions。例如,Messages app将为您所有固定的对话添加快速操作。

在这两种情况下,您都添加代码来处理触发的特定操作。由于添加静态快速操作更快,您将从这些开始。


Creating Static Quick Actions

静态快速操作是让您的用户创建新笔记的好方法。

首先,添加模型代码以帮助您处理触发的操作。 右键单击 Models 组,然后单击 New File... ▸ Swift File。 将新文件命名为 Action 并单击 Create

将文件内容替换为:

import UIKit

// 1
enum ActionType: String {
  case newNote = "NewNote"
}

// 2
enum Action: Equatable {
  case newNote

  // 3
  init?(shortcutItem: UIApplicationShortcutItem) {
    // 4
    guard let type = ActionType(rawValue: shortcutItem.type) else {
      return nil
    }

    // 5
    switch type {
    case .newNote:
      self = .newNote
    }
  }
}

// 6
class ActionService: ObservableObject {
  static let shared = ActionService()

  // 7
  @Published var action: Action?
}

很多事情正在发生。这是您添加的内容:

Action 概念的目的是让您对应用程序支持的快速操作进行建模,并在 UIApplicationShortcutItem 之间进行映射时安全地使用它们。

现在,打开 AppMain.swift。在 noteStore 上方,为 ActionService 添加一个新属性:

private let actionService = ActionService.shared

然后更新 body 实现以确保服务被注入到视图层次结构中并且 NoteList 可以访问它:

var body: some Scene {
  WindowGroup {
    NoteList()
      .environmentObject(actionService)
      .environmentObject(noteStore)
      .environment(\.managedObjectContext, noteStore.container.viewContext)
  }
}

ActionServiceSwiftUI 环境中可用,是时候使用它了。 在 Views 组中打开 NoteList.swift 并在 noteStore 下添加以下属性:

@EnvironmentObject var actionService: ActionService
@Environment(\.scenePhase) var scenePhase

您不仅要访问 ActionService 类,还需要访问 ScenePhase,该属性会在您的应用程序变为活动状态以及进入后台时通知您。

在视图的底部,添加以下方法:

func performActionIfNeeded() {
  // 1
  guard let action = actionService.action else { return }

  // 2
  switch action {
  case .newNote:
    createNewNote()
  }

  // 3
  actionService.action = nil
}

这个方法做了三件事:

每当您的应用程序处于活动状态时,您都需要触发此代码。 您将使用 onChange(of:perform:) 视图修饰符和之前添加的 scenePhase 属性。

toolbar修饰符的右大括号后添加以下代码:

// 1
.onChange(of: scenePhase) { newValue in
  // 2
  switch newValue {
  case .active:
    performActionIfNeeded()
  // 3
  default:
    break
  }
}

在这里,代码:

1. Modifying the Info Property List File

您将逻辑添加到处理操作的代码中。 但在运行应用程序之前,您仍然需要告诉系统您的静态操作。 这很简单。

Resources组中,打开 Info.plist。 右键单击顶部的Information Property List,然后单击Add Row

Key 列中,键入 Home Screen Shortcut Items,然后按回车键完成编辑。 Xcode 自动将 Type 设置为 Array 并为您添加一个项目。 通过单击 V 形展开元素,您将看到两个嵌套键:

此数组中列出的每个项目代表您的应用支持的单个静态快速操作。使用以下值更新占位符项:

除了默认键之外,您还需要添加一个。将鼠标悬停在标题上,然后单击出现的 + 图标。键入 UIApplicationShortcutItemIconSymbolName(暂时忽略弹出选项,您必须键入完整的字符串)作为键和 square.and.pencil 作为值。

以下是每个键的细分:

您可以在 Apple documention中阅读 Info.plist 中的快捷方式项目还有其他可用的键。

2. Building and Running Your App

构建并运行您的应用程序。 返回主屏幕并长按 Note Buddy 应用程序图标以查看列表中现在可用的快速操作:

点击New Note以查看会发生什么:

没有?!?

嗯,这很奇怪。 您添加了一个模型来处理应用程序中的操作,并在 Info.plist中定义了一个静态操作。

这是出了什么问题?

当用户与快速操作进行交互时,系统会告诉您的应用程序,但您还没有对这些信息做任何事情。 是时候这样做了!

3. Handling Static Quick Actions

SwiftUI 还没有提供任何原生机制来响应快速操作的启动事件。 因此,这部分需要依赖 UIKit

右键单击 AppMain.swift 并选择 New File... ▸ Swift File。 将文件命名为 AppDelegate 并单击Create。 将文件内容替换为:

// 1
import UIKit

// 2
class AppDelegate: NSObject, UIApplicationDelegate {
  private let actionService = ActionService.shared

  // 3
  func application(
    _ application: UIApplication,
    configurationForConnecting connectingSceneSession: UISceneSession,
    options: UIScene.ConnectionOptions
  ) -> UISceneConfiguration {
    // 4
    if let shortcutItem = options.shortcutItem {
      actionService.action = Action(shortcutItem: shortcutItem)
    }

    // 5
    let configuration = UISceneConfiguration(
      name: connectingSceneSession.configuration.name,
      sessionRole: connectingSceneSession.role
    )
    configuration.delegateClass = SceneDelegate.self
    return configuration
  }
}

// 6
class SceneDelegate: NSObject, UIWindowSceneDelegate {
  private let actionService = ActionService.shared

  // 7
  func windowScene(
    _ windowScene: UIWindowScene,
    performActionFor shortcutItem: UIApplicationShortcutItem,
    completionHandler: @escaping (Bool) -> Void
  ) {
    // 8
    actionService.action = Action(shortcutItem: shortcutItem)
    completionHandler(true)
  }
}

如果你对 UIKit 不太熟悉,别担心!以下是上述代码的概述:

最后,您的 SwiftUI 应用需要使用新的 AppDelegateSceneDelegate。因此,在 AppMain.swift 中的 actionService 下方,在 AppMain 中添加以下属性:

@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

是时候再次构建和运行您的应用程序了。 返回主屏幕并再次尝试使用您的快速操作:

极好的! 您添加了您的第一个静态快速操作。 虽然这为许多可能性打开了大门,但您无法使用运行时使用的信息对其进行自定义。 这就是动态操作的用武之地。


Creating Dynamic Quick Actions

如果用户想要编辑他们最近的笔记,他们仍然需要打开应用程序,滚动列表以找到它,点击它然后进行编辑。

简化和加快流程会很棒!

Info.plist 中进行静态操作时,您可以在代码中添加所有动态操作。 在 Note Buddy 的情况下,可能对于您的许多应用程序,当您的场景的阶段变为background时,将添加这些动态操作。 因此,在前往主屏幕之前,您可以设置一些操作以在最近修改日期之前编辑最新的笔记。

1. Handling Dynamic Quick Actions

要添加动态操作,首先将一个新case添加到您的 ActionTypeAction 枚举中。

打开 Action.swift 并将以下内容添加到 ActionType 中:

case editNote = "EditNote"

将以下新case添加到Action

case editNote(identifier: String)

这就是为什么 ActionTypeAction 需要是两个独立的枚举。 ActionType 代表不同快速动作类型的标识符,而 Action 代表动作本身。 在某些情况下,例如 .editNotecase,它可以包含其他关联值。

添加新的枚举case后,您会注意到编译器友好地告诉您 init?(shortcutItem:) 中的 switch 语句不再详尽。 通过将以下case添加到开关来解决此问题:

case .editNote:
  if let identifier = shortcutItem.userInfo?["NoteID"] as? String {
    self = .editNote(identifier: identifier)
  } else {
    return nil
  }

在这里,您将检查 shortcutItemuserInfo 字典以获取要编辑的笔记的 ID。 如果成功,则将操作初始化为具有关联值的 .editNote。 否则,初始化程序将通过返回 nil 失败。

如果您现在尝试构建项目,您将在 NoteList.swift 中看到另一个编译失败。 转到它,你会发现你还需要在 performActionIfNeeded()中实现新的动作处理。

将以下代码添加到 switch 语句中:

case .editNote(let identifier):
  selectedNote = noteStore.findNote(withIdentifier: identifier)

构建并运行您的应用程序。 然后前往主屏幕,长按 Note Buddy 图标并查看结果:

再一次……什么都没有?

虽然您已经确保快速操作正确传递到您的应用程序,但您仍然没有告诉您的应用程序显示任何动态项目。 接下来你会这样做。

2. Adding Your Dynamic Quick Actions

如前所述,添加动态操作的好地方是应用程序进入后台时。 此时,您拥有运行代码所需的所有信息,该代码确定要添加哪些操作,然后添加它们。

由于您已经在 NoteList 中观察了 ScenePhase,因此这是更新动作的好地方。 但在此之前,您需要创建自己的 UIApplicationShortcutItem 实例来描述您的动态操作。

前往 Note.swift 并在文件顶部添加以下import

import UIKit

Note 扩展中,添加以下属性:

// 1
var shortcutItem: UIApplicationShortcutItem? {
  // 2
  guard !wrappedTitle.isEmpty || !wrappedBody.isEmpty else { return nil }

  // 3
  return UIApplicationShortcutItem(
    type: ActionType.editNote.rawValue,
    localizedTitle: "Edit Note",
    localizedSubtitle: wrappedTitle.isEmpty ? wrappedBody : wrappedTitle,
    icon: .init(systemImageName: isFavorite ? "star" : "pencil"),
    userInfo: [
      "NoteID": identifier as NSString
    ]
  )
}

下面是代码分解:

现在您已经创建了一个属性来公开给定 Note 的适当快捷方式,请导航回 NoteList.swift。在 performActionIfNeeded()下添加以下方法:

func updateShortcutItems() {
  UIApplication.shared.shortcutItems = notes.compactMap(\.shortcutItem)
}

在这里,您压缩映射 notes 数组以生成仅包含非nilUIApplicationShortcutItem 的数组。 然后将该数组分配给 UIApplicationshortcutItems 属性,该属性又与您在主屏幕菜单中的静态操作一起可用。

现在,您只需在应用程序进入后台时调用此方法。 向上滚动到您之前添加的 onChange(of: perform:)修饰符,并在 switch 语句中添加以下内容:

case .background:
  updateShortcutItems()

构建并运行。 然后看看有哪些项目可用:

Yeah,你做到了。

对您的笔记进行一些编辑,收藏一些并重复该过程。 显示的笔记以及顺序在您后台运行应用程序时保持完美同步:

您可能已经注意到,并非所有笔记都显示出来。 iOS 将操作数量限制为仅显示适合屏幕的操作。但是,文档建议您不要专门限制动态操作的计数。而是,像 Note Buddy那样做。

这样,iOS 将显示它可以适应的所有快速操作。如果未来的更新能够实现更多功能,那就太好了,因为您无需在后台应用程序之前推出应用程序更新来支持添加更多操作。

如果您想了解更多信息,请查看有关 UIKit 中 Menus and Shortcuts 的 Apple 文档,以及Human Interface Guidelines for Home Screen Quick Actions

后记

本篇主要讲述了Home Screen Quick Actions for SwiftUI App,感兴趣的给个赞或者关注~~~

上一篇下一篇

猜你喜欢

热点阅读