打造功能丰富的 iOS 应用:分享、接力与搜索功能实现指南
在开发 iOS 应用时,为了提升用户体验和应用的实用性,我们可以为其添加分享、接力(Handoff)和搜索等功能。这些功能能够让应用更好地融入用户的设备生态系统,使应用不再孤立,而是成为用户日常使用的一部分。下面将详细介绍如何为应用添加这些功能。
1. 附件删除功能
在应用中,我们可能需要实现附件删除的功能。以下是相关代码示例:
self.attachmentsCollectionView?
.deleteItems(at: [indexPath])
self.endEditMode()
} catch let error as NSError {
NSLog("Failed to delete attachment: \(error)")
}
同时,在
collectionView(_, cellForItemAt indexPath:)
方法中添加代码,设置单元格的代理为
self
,并添加长按手势:
// Add a long-press gesture to it, if it doesn't
// already have it
let longPressGesture = UILongPressGestureRecognizer(target: self,
action: #selector(DocumentViewController.beginEditMode))
attachmentCell.gestureRecognizers = [longPressGesture]
// Contact us when the user taps the delete button
attachmentCell.delegate = self
完成上述代码添加后,运行应用,就可以实现附件删除功能了。
2. 分享功能实现
分享功能可以让用户方便地将应用内的内容分享到社交媒体、邮件或短信等平台。在 iOS 中,分享功能由
UIActivityViewController
处理。以下是实现分享功能的具体步骤:
1. 打开
Main.storyboard
,进入图像附件视图控制器。
2. 从对象库中添加
UIToolBar
到视图,并将其放置在屏幕底部。该工具栏会包含一个
UIBarButtonItem
,类似于
UIButton
,但专门用于工具栏。
3. 调整工具栏大小,使其适应屏幕宽度。点击“Pin”菜单,固定视图的左、右和底部边缘,确保工具栏始终位于屏幕底部并填满屏幕宽度。
4. 选择按钮,将其
System Item
属性设置为
Action
,这样按钮图标将变为标准的 iOS 分享图标。
5. 在助理编辑器中打开
ImageAttachmentViewController.swift
。
6. 按住
Control
键,从刚添加的工具栏按钮拖动到
ImageAttachmentViewController
,创建一个名为
shareImage
的新动作。
7. 在
shareImage
方法中添加以下代码:
@IBAction func shareImage(_ sender: UIBarButtonItem) {
// Ensure that we're actually showing an image
guard let image = self.imageView?.image else {
return
}
let activityController = UIActivityViewController(
activityItems: [image], applicationActivities: nil)
// If we are being presented in a window that's a Regular width,
// show it in a popover (rather than the default modal)
if UIApplication.shared.keyWindow?.traitCollection
.horizontalSizeClass == UIUserInterfaceSizeClass.regular {
activityController.modalPresentationStyle = .popover
activityController.popoverPresentationController?
.barButtonItem = sender
}
self.present(activityController, animated: true,
completion: nil)
}
当用户点击分享按钮时,会弹出
UIActivityViewController
,用户可以选择将图像分享到不同的平台。如果应用在较大屏幕(如 iPhone 6 Plus 或 iPad)上运行,分享视图将以弹出框的形式显示。
3. 接力(Handoff)功能实现
接力功能允许用户在不同设备(如 iOS 设备和 macOS 应用)之间无缝切换工作。以下是实现接力功能的步骤:
1. 选择项目导航器顶部的项目。
2. 进入
Notes
目标设置(即 macOS 应用),滚动到“Document Types”部分。
3. 展开“Additional document type properties”,选择
CFBundleTypOSTypes
条目,点击出现的“+”按钮,添加一个新条目。
4. 将新条目命名为
NSUbiquitousDocumentUserActivityType
,类型设置为
String
,值设置为
au.com.secretlab.Notes.editing
。
5. 在
Notes-iOS
中进行相同的设置。如果使用了自定义的
bundleID
,请确保在此处使用该
bundleID
并在末尾添加
.editing
,否则接力功能将无法正常工作。
6. 打开属于
Notes-iOS
目标的
AppDelegate.swift
文件。
7. 实现以下方法:
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
// Return to the list of documents
if let navigationController =
self.window?.rootViewController as? UINavigationController {
navigationController.popToRootViewController(animated: false)
// We're now at the list of documents; tell the restoration
// system that this view controller needs to be informed
// that we're continuing the activity
if let topViewController = navigationController.topViewController {
restorationHandler([topViewController])
}
return true
}
return false
}
-
打开
DocumentListViewController.swift文件。 -
在
DocumentListViewController类中添加以下方法:
override func restoreUserActivityState(_ activity: NSUserActivity) {
// We're being told to open a document
if let url = activity.userInfo?[NSUserActivityDocumentURLKey] as? URL {
// Open the document
self.performSegue(withIdentifier: "ShowDocument", sender: url)
}
}
-
最后,在
DocumentViewController的viewWillAppear方法中添加以下代码,使活动变为当前活动:
// If this document is not already open, open it
if document.documentState.contains(UIDocumentState.closed) {
document.open { (success) -> Void in
if success == true {
self.textView?.attributedText = document.text
self.attachmentsCollectionView?.reloadData()
// We are now engaged in this activity
document.userActivity?.becomeCurrent()
// Register for state change notifications
self.stateChangedObserver = Notification.default
.addObserver(
forName: NSNotification.Name.UIDocumentStateChanged,
object: document,
queue: nil,
using: { (notification) -> Void in
self.documentStateChanged()
})
self.documentStateChanged()
}
完成上述步骤后,运行 iOS 应用和 macOS 应用,在一个设备上打开文档,在另一个设备上就可以通过接力功能继续编辑该文档。
4. 搜索功能实现
搜索功能可以让用户方便地在应用内搜索文档。在 iOS 中,有三种搜索技术可供使用:
NSUserActivity
对象、Core Spotlight 和网页索引。这里主要介绍通过
NSUserActivity
实现搜索功能的方法。
4.1 索引活动
通过
NSUserActivity
为应用添加搜索索引支持的步骤如下:
1. 打开
DocumentViewController.swift
文件。
2. 在文件顶部导入
Core Spotlight
框架:
import CoreSpotlight
-
更新
viewWillAppear方法,在文档打开时为文档的用户活动添加可搜索的元数据:
// If this document is not already open, open it
if document.documentState.contains(UIDocumentState.closed) {
document.open { (success) -> Void in
if success == true {
self.textView?.attributedText = document.text
self.attachmentsCollectionView?.reloadData()
// Add support for searching for this document
document.userActivity?.title = document.localizedName
let contentAttributeSet
= CSSearchableItemAttributeSet(
itemContentType: document.fileType!)
contentAttributeSet.title = document.localizedName
contentAttributeSet.contentDescription = document.text.string
document.userActivity?.contentAttributeSet
= contentAttributeSet
document.userActivity?.isEligibleForSearch = true
// We are now engaged in this activity
document.userActivity?.becomeCurrent()
// Register for state change notifications
self.stateChangedObserver = Notification.default
.addObserver(
forName: NSNotification.Name.UIDocumentStateChanged,
object: document,
queue: nil,
using: { (notification) -> Void in
self.documentStateChanged()
})
self.documentStateChanged()
}
完成上述代码添加后,运行应用,打开文档并输入一些内容,关闭应用后,在主屏幕上向下滑动打开搜索框,输入文档中的内容,文档就会出现在搜索结果中。点击搜索结果,应用将启动并打开相应的文档。
4.2 Spotlight 扩展
为了让应用的所有文档内容都能在 Spotlight 中搜索到,我们可以添加一个 Spotlight 索引应用扩展。以下是添加扩展的步骤:
1. 打开文件菜单,选择“New” -> “Target”。
2. 选择
iOS
->
Application Extension
->
Spotlight Index Extension
。
3. 将新目标命名为
Notes-SpotlightIndexer
。
4. 点击“Finish”后,Xcode 会弹出一个窗口询问是否激活新创建的方案,点击“Activate”切换到新方案。
5. 为扩展授予访问 iCloud 容器的权限:
- 进入目标属性,点击“Capabilities”标签。
- 打开 iCloud 开关,等待加载完成。
- 打开 iCloud Documents 开关。
- 选择 Mac 和 iOS 应用使用的 iCloud 容器,确保不选择其他容器。将“Use default container” 改为 “Specify custom container”。
6. 确保
Notes-SpotlightIndexer
目标能够使用定义重要文件名称的枚举:
- 打开
DocumentCommon.swift
文件,选择“View” -> “Utilities” -> “Show File Inspector” 打开文件检查器。
- 确保“Notes-SpotlightIndexer” 旁边的复选框被选中。
7. 实现 Spotlight 索引器:
- 打开
IndexRequestHandler.swift
文件,该文件是添加目标时 Xcode 生成的模板代码的一部分。
- 在文件顶部添加以下代码:
import UIKit
- 在 `IndexRequestHandler` 类中添加以下计算属性,用于获取应用已知的所有文档的集合:
var availableFiles : [URL] {
let fileManager = FileManager.default
var allFiles : [URL] = []
// Get the list of all local files
if let localDocumentsFolder
= fileManager.urls(for: .documentDirectory,
in: .userDomainMask).first {
do {
let localFiles = try fileManager
.contentsOfDirectory(atPath: localDocumentsFolder.path)
.map({
localDocumentsFolder.appendingPathComponent($0,
isDirectory: false)
})
allFiles.append(contentsOf: localFiles)
} catch {
NSLog("Failed to get list of local files!")
}
}
// Get the list of documents in iCloud
if let documentsFolder = fileManager
.url(forUbiquityContainerIdentifier: nil)?
.appendingPathComponent("Documents", isDirectory: true) {
do {
// Get the list of files
let iCloudFiles = try fileManager
.contentsOfDirectory(atPath: documentsFolder.path)
.map({
documentsFolder.appendingPathComponent($0,
isDirectory: false)
})
allFiles.append(contentsOf: iCloudFiles)
} catch {
// Log an error and return the empty array
NSLog("Failed to get contents of iCloud container")
return []
}
}
// Filter these to only those that end in ".note",
// and return NSURLs of these
return allFiles
.filter({ $0.lastPathComponent.hasSuffix(".note") })
}
- 在 `IndexRequestHandler` 类中添加以下方法,用于为给定的 URL 生成 `CSSearchableItem`:
func itemForURL(_ url: URL) -> CSSearchableItem? {
// If this URL doesn't exist, return nil
if (url as NSURL).checkResourceIsReachableAndReturnError(nil) == false
{
return nil
}
// Replace this with your own type identifier
let attributeSet = CSSearchableItemAttributeSet(
itemContentType: "au.com.secretlab.Note")
attributeSet.title = url.lastPathComponent
// Get the text in this file
let textFileURL = url.appendingPathComponent(
NoteDocumentFileNames.TextFile.rawValue)
if let textData = try? Data(contentsOf: textFileURL),
let text = try? NSAttributedString(data: textData,
options:
[NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType],
documentAttributes: nil) {
attributeSet.contentDescription = text.string
} else {
attributeSet.contentDescription = ""
}
let item =
CSSearchableItem(uniqueIdentifier: url.absoluteString,
domainIdentifier: "au.com.secretlab.Notes",
attributeSet: attributeSet)
return item
}
- 删除 `searchableIndex(_, reindexAllSearchableItemsWithAcknowledgementHandler:)` 方法,并替换为以下代码:
override func searchableIndex(_ searchableIndex: CSSearchableIndex,
reindexAllSearchableItemsWithAcknowledgementHandler
acknowledgementHandler: @escaping () -> Void) {
// Reindex all data with the provided index
let files = availableFiles
var allItems : [CSSearchableItem] = []
for file in files {
if let item = itemForURL(file) {
allItems.append(item)
}
}
searchableIndex.indexSearchableItems(allItems) { (error) -> Void in
acknowledgementHandler()
}
}
- 删除 `searchableIndex(_, reindexSearchableItemsWithIdentifiers:, acknowledgementHandler:)` 方法,并替换为以下代码:
override func searchableIndex(_ searchableIndex: CSSearchableIndex,
reindexSearchableItemsWithIdentifiers identifiers: [String],
acknowledgementHandler: @escaping () -> Void) {
// Reindex any items with the given identifiers and the provided index
var itemsToIndex : [CSSearchableItem] = []
var itemsToRemove : [String] = []
for identifier in identifiers {
if let url = URL(string: identifier), let item = itemForURL(url) {
itemsToIndex.append(item)
} else {
itemsToRemove.append(identifier)
}
}
searchableIndex.indexSearchableItems(itemsToIndex) { (error) -> Void in
searchableIndex
.deleteSearchableItems(withIdentifiers: itemsToRemove) {
(error) -> Void in
acknowledgementHandler()
}
}
}
-
最后,在
DocumentListViewController.swift文件中添加以下代码,使应用能够在用户选择搜索结果后打开相应的文档:
import CoreSpotlight
override func restoreUserActivityState(_ activity: NSUserActivity) {
// We're being told to open a document
if let url = activity.userInfo?[NSUserActivityDocumentURLKey] as? URL {
// Open the document
self.performSegue(withIdentifier: "ShowDocument", sender: url)
}
// We're coming from a search result
if let searchableItemIdentifier = activity
.userInfo?[CSSearchableItemActivityIdentifier] as? String,
let url = URL(string: searchableItemIdentifier) {
// Open the document
self.performSegue(withIdentifier: "ShowDocument", sender: url)
}
}
通过以上步骤,应用将能够定期对所有文档进行索引,并在搜索结果中显示这些文档。
总结
通过为应用添加分享、接力和搜索功能,我们可以提升应用的用户体验和实用性,使应用更好地融入用户的设备生态系统。这些功能的实现不仅可以让用户更方便地使用应用,还可以提高应用在用户设备中的可见性和使用率。希望以上内容对你有所帮助,祝你在应用开发中取得成功!
整个功能实现的流程可以用以下 mermaid 流程图表示:
graph LR
A[附件删除功能] --> B[分享功能实现]
B --> C[接力功能实现]
C --> D[搜索功能实现]
D --> D1[索引活动]
D --> D2[Spotlight 扩展]
同时,为了更清晰地展示不同功能的实现步骤,我们可以用表格进行总结:
| 功能 | 实现步骤 |
| — | — |
| 附件删除功能 | 1. 添加删除代码
2. 设置单元格代理和长按手势 |
| 分享功能 | 1. 打开
Main.storyboard
添加工具栏和按钮
2. 创建
shareImage
动作
3. 添加分享代码 |
| 接力功能 | 1. 设置文档类型属性
2. 实现
continueUserActivity
方法
3. 实现
restoreUserActivityState
方法
4. 使活动变为当前活动 |
| 搜索功能 - 索引活动 | 1. 导入
Core Spotlight
框架
2. 更新
viewWillAppear
方法添加元数据 |
| 搜索功能 - Spotlight 扩展 | 1. 添加扩展目标
2. 授予 iCloud 访问权限
3. 实现索引器方法 |
打造功能丰富的 iOS 应用:分享、接力与搜索功能实现指南
功能实现的关键要点回顾与深入分析
在前面的内容中,我们详细介绍了如何为 iOS 应用添加附件删除、分享、接力和搜索等功能。接下来,我们将对这些功能实现过程中的一些关键要点进行深入分析。
附件删除功能
附件删除功能的实现主要涉及两个关键步骤:删除集合视图中的项目和结束编辑模式。代码如下:
self.attachmentsCollectionView?
.deleteItems(at: [indexPath])
self.endEditMode()
} catch let error as NSError {
NSLog("Failed to delete attachment: \(error)")
}
在这个代码中,
attachmentsCollectionView
是用于显示附件的集合视图,通过
deleteItems(at:)
方法删除指定索引路径的项目。同时,为了确保用户体验的一致性,我们需要调用
endEditMode()
方法结束编辑模式。
另外,为了让用户能够触发删除操作,我们在
collectionView(_, cellForItemAt indexPath:)
方法中添加了长按手势,并设置单元格的代理为
self
:
// Add a long-press gesture to it, if it doesn't
// already have it
let longPressGesture = UILongPressGestureRecognizer(target: self,
action: #selector(DocumentViewController.beginEditMode))
attachmentCell.gestureRecognizers = [longPressGesture]
// Contact us when the user taps the delete button
attachmentCell.delegate = self
这样,当用户长按单元格时,就会触发
beginEditMode()
方法,从而进入编辑模式,进行删除操作。
分享功能
分享功能的核心是使用
UIActivityViewController
来提供系统服务,让用户可以将图像分享到不同的平台。实现步骤如下:
1. 在故事板中添加工具栏和分享按钮。
2. 创建
shareImage
动作,并在其中添加分享代码:
@IBAction func shareImage(_ sender: UIBarButtonItem) {
// Ensure that we're actually showing an image
guard let image = self.imageView?.image else {
return
}
let activityController = UIActivityViewController(
activityItems: [image], applicationActivities: nil)
// If we are being presented in a window that's a Regular width,
// show it in a popover (rather than the default modal)
if UIApplication.shared.keyWindow?.traitCollection
.horizontalSizeClass == UIUserInterfaceSizeClass.regular {
activityController.modalPresentationStyle = .popover
activityController.popoverPresentationController?
.barButtonItem = sender
}
self.present(activityController, animated: true,
completion: nil)
}
在这个代码中,我们首先检查是否有图像可供分享,然后创建
UIActivityViewController
并传入图像作为活动项目。如果应用在较大屏幕上运行,我们将分享视图以弹出框的形式显示,这样可以提供更好的用户体验。
接力(Handoff)功能
接力功能允许用户在不同设备之间无缝切换工作,实现步骤较为复杂,主要包括以下几个方面:
1. 设置文档类型属性,确保不同设备之间的活动类型一致:
1. 选择项目导航器顶部的项目。
2. 进入 `Notes` 目标设置(即 macOS 应用),滚动到“Document Types”部分。
3. 展开“Additional document type properties”,选择 `CFBundleTypOSTypes` 条目,点击“+”按钮添加新条目。
4. 将新条目命名为 `NSUbiquitousDocumentUserActivityType`,类型设置为 `String`,值设置为 `au.com.secretlab.Notes.editing`。
5. 在 `Notes-iOS` 中进行相同的设置。
-
实现
continueUserActivity方法,处理用户从一个设备接力到另一个设备的活动:
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
// Return to the list of documents
if let navigationController =
self.window?.rootViewController as? UINavigationController {
navigationController.popToRootViewController(animated: false)
// We're now at the list of documents; tell the restoration
// system that this view controller needs to be informed
// that we're continuing the activity
if let topViewController = navigationController.topViewController {
restorationHandler([topViewController])
}
return true
}
return false
}
-
实现
restoreUserActivityState方法,根据用户活动信息打开相应的文档:
override func restoreUserActivityState(_ activity: NSUserActivity) {
// We're being told to open a document
if let url = activity.userInfo?[NSUserActivityDocumentURLKey] as? URL {
// Open the document
self.performSegue(withIdentifier: "ShowDocument", sender: url)
}
}
- 使活动变为当前活动,让系统知道用户正在进行的活动:
// If this document is not already open, open it
if document.documentState.contains(UIDocumentState.closed) {
document.open { (success) -> Void in
if success == true {
self.textView?.attributedText = document.text
self.attachmentsCollectionView?.reloadData()
// We are now engaged in this activity
document.userActivity?.becomeCurrent()
// Register for state change notifications
self.stateChangedObserver = Notification.default
.addObserver(
forName: NSNotification.Name.UIDocumentStateChanged,
object: document,
queue: nil,
using: { (notification) -> Void in
self.documentStateChanged()
})
self.documentStateChanged()
}
通过以上步骤,我们可以确保用户在不同设备之间能够无缝切换工作,提高工作效率。
搜索功能
搜索功能的实现分为索引活动和 Spotlight 扩展两个部分。
索引活动
:通过
NSUserActivity
为应用添加搜索索引支持,主要步骤如下:
1. 导入
Core Spotlight
框架:
import CoreSpotlight
-
更新
viewWillAppear方法,为文档的用户活动添加可搜索的元数据:
// If this document is not already open, open it
if document.documentState.contains(UIDocumentState.closed) {
document.open { (success) -> Void in
if success == true {
self.textView?.attributedText = document.text
self.attachmentsCollectionView?.reloadData()
// Add support for searching for this document
document.userActivity?.title = document.localizedName
let contentAttributeSet
= CSSearchableItemAttributeSet(
itemContentType: document.fileType!)
contentAttributeSet.title = document.localizedName
contentAttributeSet.contentDescription = document.text.string
document.userActivity?.contentAttributeSet
= contentAttributeSet
document.userActivity?.isEligibleForSearch = true
// We are now engaged in this activity
document.userActivity?.becomeCurrent()
// Register for state change notifications
self.stateChangedObserver = Notification.default
.addObserver(
forName: NSNotification.Name.UIDocumentStateChanged,
object: document,
queue: nil,
using: { (notification) -> Void in
self.documentStateChanged()
})
self.documentStateChanged()
}
Spotlight 扩展
:为了让应用的所有文档内容都能在 Spotlight 中搜索到,我们需要添加一个 Spotlight 索引应用扩展,步骤如下:
1. 添加扩展目标:
1. 打开文件菜单,选择“New” -> “Target”。
2. 选择 `iOS` -> `Application Extension` -> `Spotlight Index Extension`。
3. 将新目标命名为 `Notes-SpotlightIndexer`。
4. 点击“Finish”后,激活新方案。
- 授予 iCloud 访问权限:
1. 进入目标属性,点击“Capabilities”标签。
2. 打开 iCloud 开关,等待加载完成。
3. 打开 iCloud Documents 开关。
4. 选择 Mac 和 iOS 应用使用的 iCloud 容器,确保不选择其他容器。将“Use default container” 改为 “Specify custom container”。
- 实现索引器方法:
// 获取所有可用文件
var availableFiles : [URL] {
let fileManager = FileManager.default
var allFiles : [URL] = []
// Get the list of all local files
if let localDocumentsFolder
= fileManager.urls(for: .documentDirectory,
in: .userDomainMask).first {
do {
let localFiles = try fileManager
.contentsOfDirectory(atPath: localDocumentsFolder.path)
.map({
localDocumentsFolder.appendingPathComponent($0,
isDirectory: false)
})
allFiles.append(contentsOf: localFiles)
} catch {
NSLog("Failed to get list of local files!")
}
}
// Get the list of documents in iCloud
if let documentsFolder = fileManager
.url(forUbiquityContainerIdentifier: nil)?
.appendingPathComponent("Documents", isDirectory: true) {
do {
// Get the list of files
let iCloudFiles = try fileManager
.contentsOfDirectory(atPath: documentsFolder.path)
.map({
documentsFolder.appendingPathComponent($0,
isDirectory: false)
})
allFiles.append(contentsOf: iCloudFiles)
} catch {
// Log an error and return the empty array
NSLog("Failed to get contents of iCloud container")
return []
}
}
// Filter these to only those that end in ".note",
// and return NSURLs of these
return allFiles
.filter({ $0.lastPathComponent.hasSuffix(".note") })
}
// 为给定的 URL 生成 CSSearchableItem
func itemForURL(_ url: URL) -> CSSearchableItem? {
// If this URL doesn't exist, return nil
if (url as NSURL).checkResourceIsReachableAndReturnError(nil) == false
{
return nil
}
// Replace this with your own type identifier
let attributeSet = CSSearchableItemAttributeSet(
itemContentType: "au.com.secretlab.Note")
attributeSet.title = url.lastPathComponent
// Get the text in this file
let textFileURL = url.appendingPathComponent(
NoteDocumentFileNames.TextFile.rawValue)
if let textData = try? Data(contentsOf: textFileURL),
let text = try? NSAttributedString(data: textData,
options:
[NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType],
documentAttributes: nil) {
attributeSet.contentDescription = text.string
} else {
attributeSet.contentDescription = ""
}
let item =
CSSearchableItem(uniqueIdentifier: url.absoluteString,
domainIdentifier: "au.com.secretlab.Notes",
attributeSet: attributeSet)
return item
}
// 重新索引所有可搜索项
override func searchableIndex(_ searchableIndex: CSSearchableIndex,
reindexAllSearchableItemsWithAcknowledgementHandler
acknowledgementHandler: @escaping () -> Void) {
// Reindex all data with the provided index
let files = availableFiles
var allItems : [CSSearchableItem] = []
for file in files {
if let item = itemForURL(file) {
allItems.append(item)
}
}
searchableIndex.indexSearchableItems(allItems) { (error) -> Void in
acknowledgementHandler()
}
}
// 重新索引指定标识符的可搜索项
override func searchableIndex(_ searchableIndex: CSSearchableIndex,
reindexSearchableItemsWithIdentifiers identifiers: [String],
acknowledgementHandler: @escaping () -> Void) {
// Reindex any items with the given identifiers and the provided index
var itemsToIndex : [CSSearchableItem] = []
var itemsToRemove : [String] = []
for identifier in identifiers {
if let url = URL(string: identifier), let item = itemForURL(url) {
itemsToIndex.append(item)
} else {
itemsToRemove.append(identifier)
}
}
searchableIndex.indexSearchableItems(itemsToIndex) { (error) -> Void in
searchableIndex
.deleteSearchableItems(withIdentifiers: itemsToRemove) {
(error) -> Void in
acknowledgementHandler()
}
}
}
通过以上步骤,应用将能够定期对所有文档进行索引,并在搜索结果中显示这些文档。
总结与展望
通过为 iOS 应用添加分享、接力和搜索等功能,我们可以显著提升应用的用户体验和实用性,使应用更好地融入用户的设备生态系统。这些功能的实现不仅可以让用户更方便地使用应用,还可以提高应用在用户设备中的可见性和使用率。
在实际开发过程中,我们需要注意以下几点:
1.
代码的兼容性
:确保代码在不同版本的 iOS 系统和设备上都能正常运行。
2.
性能优化
:对于搜索和索引等功能,要注意性能优化,避免影响应用的响应速度。
3.
用户体验
:在实现功能的同时,要注重用户体验,确保操作流程简单、直观。
未来,随着 iOS 系统的不断更新和发展,我们可以进一步探索更多的功能和优化方案,为用户提供更加优质的应用体验。例如,可以结合机器学习和人工智能技术,实现更智能的搜索和推荐功能;或者进一步优化接力功能,实现更无缝的设备切换体验。
希望以上内容对你有所帮助,祝你在应用开发中取得更大的成功!
为了更清晰地展示不同功能的关键代码和实现要点,我们可以用表格进行总结:
| 功能 | 关键代码 | 实现要点 |
| — | — | — |
| 附件删除功能 |
self.attachmentsCollectionView?.deleteItems(at: [indexPath])
self.endEditMode()
| 删除集合视图项目,结束编辑模式 |
| 分享功能 |
let activityController = UIActivityViewController(activityItems: [image], applicationActivities: nil)
| 创建分享控制器,根据屏幕大小设置显示方式 |
| 接力功能 |
document.userActivity?.becomeCurrent()
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool
| 设置活动为当前活动,处理接力活动 |
| 搜索功能 - 索引活动 |
document.userActivity?.title = document.localizedName
document.userActivity?.isEligibleForSearch = true
| 为用户活动添加元数据,设置可搜索 |
| 搜索功能 - Spotlight 扩展 |
var availableFiles : [URL]
func itemForURL(_ url: URL) -> CSSearchableItem?
| 获取所有可用文件,生成可搜索项 |
同时,我们可以用 mermaid 流程图来展示搜索功能中 Spotlight 扩展的实现流程:
graph LR
A[添加扩展目标] --> B[授予 iCloud 访问权限]
B --> C[实现索引器方法]
C --> C1[获取所有可用文件]
C --> C2[生成可搜索项]
C --> C3[重新索引所有可搜索项]
C --> C4[重新索引指定标识符的可搜索项]
通过以上的总结和分析,我们可以更加清晰地了解这些功能的实现原理和关键要点,为后续的开发和优化提供有力的支持。
超级会员免费看
11

被折叠的 条评论
为什么被折叠?



