NSUserActivity的基本使用
来源:互联网 发布:caffe经典模型实战pdf 编辑:程序博客网 时间:2024/05/01 18:45
简介
NSUserActivity并不是一个新的概念,在iOS8中就已经使用它来做Handoff,在iOS9中User Activities变的可以搜索,并且可以在每个Activity里加上Index用的Metadata。但是只能用在用户访问过的或者看见过的内容中。
一旦某些内容被记录进NSUserActivity,就可以在Spotlight和Safari中同时被搜索到。而且还能通过设置'Eligible For Public Indexing'来让这些被Index的内容传到Apple的云端Cloud Index里,从而实现每个用户都能搜索到这个内容。同时Apple也强调了隐私的保护。并不是所有内容都是Public的,同一个内容需要在云端被Index超过一个限额(具体多少没有公布),才会最后成为Public的内容。所以用户不用担心自己看到的内容成为公众都能搜索的内容。
NSUserActivity基本内容
NSUserActivity对象提供了一种轻量级的方式捕获APP的状态并存储可以在之后使用。我们可以使用activity对象捕获用户正在操作的信息,比如:查看APP内容、编辑文本、查看网页、看video等。当系统启动我们的APP之后,activity对象是可以获取的,APP能够使用activity对象的信息恢复activity对象到合理的状态。Spotlight也可以使用activity对象来为用户提高搜索结果。
在关键时刻创建NSUserActivity对象并注册它们到系统。例如:我们可能在用户打开网页、或APP移到后台、或用户在APP执行一些重要的任务的时候创建activity对象。用户的activity对象并不打算跟踪APP中的每一个任务,所以我们不应该使用activity对象用于一些小的编辑或者次要的修改。相反,当用户想之后继续使用或在其它设备上使用,我们应该使用activity对象。我们也可以使用它们为Spotlight 提供更好的搜索结果。
当创建一个用户的activity对象,做以下事情:
1:使用合理的activity type来创建并初始化用户的activity对象。
2:设置用户activity对象的title
3:使用一个或者多个下列属性来配置任务的对象:
isEligibleForHandoff
isEligibleForSearch
isEligibleForPublicIndexing
4:配置activity对象的相关属性
5:对于用户 activity 对象,如果是配置用于搜索和公开位置,可以配置contentAttributeSet, keywords, webpageURL 等属性以至于Spotlight 能够索引对象。
6:调用becomeCurrent() 方法来注册用户 activity 对象
3:使用一个或者多个下列属性来配置任务的对象:
isEligibleForHandoff
isEligibleForSearch
isEligibleForPublicIndexing
4:配置activity对象的相关属性
5:对于用户 activity 对象,如果是配置用于搜索和公开位置,可以配置contentAttributeSet, keywords, webpageURL 等属性以至于Spotlight 能够索引对象。
6:调用becomeCurrent() 方法来注册用户 activity 对象
当我们创建了NSUserActivity对象,我们使用了具体的字符串标识了activity的类型。该activity类型字符串是reverse-DNS格式。例如:当用户打开一个网页,我们可以指定activity的字符串为com.myCompany.myApp.OpenWebPage。我们必须在Info.plist文件中包含NSUserActivityTypes 作为key值对应的activity的类型。系统根据该key的信息来确定你的APP是否有能力处理给定的用户activity对象。并且支持Handoff,支持SiriKit,支持提高搜索结果等。
下面看一个简单demo,直接使用NSUserActivity实现搜索功能
demo非常简单,当运行程序之后,显示的是一个包含几首歌的列表,点击进入是一个详情界面。然后我们可以Command-Shift-H回到home界面,然后滑动到搜索界面,搜索对应的title等关键字就可以看到相应的搜索结果。当点击搜索结果会调到APP的详情界面。原文地址为:这里
首先看一下AppDelegate.swift文件:
import UIKit@UIApplicationMainclass AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { return true } func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool { let mainController = (window?.rootViewController as! UINavigationController).viewControllers.first mainController?.restoreUserActivityState(userActivity) return true }}
主要是关注func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping([Any]?) -> Void) -> Bool方法,当接受到数据相关联的用户activity时,该方法将会被调用。该方法提供了我们机会执行具体的任务来更新APP。如果我们并没有实现该方法中实现了该方法或者返回值为false,iOS将尝试为APP创建文本来打开URL,并且iOS知道APP并不能够处理当前activity。如果返回true表示APP能够处理当前activity。简单一点理解操作就是:当点击搜索之后的内容,会触发该方法,在这里我们可以进行相应的任务处理,demo中执行了页面的跳转。
ListViewController.swift文件 ,即列表页面
import UIKitclass ListViewController: UIViewController { fileprivate var songList: [SongInfo] = [] //存储搜索item的标识符 private var searchSongIdentifier: Int? @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() //添加数据,SongInfo是一个模型类,仅仅是包含了3个属性和初始化方法 songList.append(SongInfo(song: "Bob Dylan - Like a Rolling Stone", album: "Highway 61 Revisited (1965)", style: "Rock")) songList.append(SongInfo(song: "John Lennon - Imagine", album: "Imagine (1971)", style: "Rock, Pop")) songList.append(SongInfo(song: "Nirvana - Smells Like Teen Spirit", album: "Nevermind (1991)", style: "Rock")) } override func viewWillAppear(_ animated: Bool) { if let indexPath = tableView.indexPathForSelectedRow { tableView.deselectRow(at: indexPath, animated: false) } super.viewWillAppear(animated) } //当执行segue过渡时,会触发该方法,该方法主要是获取选中的位置,便于后续的搜索,以及页面跳转 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { var songId: Int? if let index = tableView.indexPathForSelectedRow?.row{ songId = index }else{ songId = searchSongIdentifier } //设置对应的歌曲信息和位置 let controller = segue.destination as! DetailedViewController controller.songInfo = songList[songId!] controller.songIndex = songId! } //判断activity中的userInfo字典中是否包含index作为key所对应的值,如果存在,存储对应的值到searchSongIdentifier,并进行跳转 override func restoreUserActivityState(_ activity: NSUserActivity) { if let index = activity.userInfo?["index"] as? Int{ searchSongIdentifier = index self.performSegue(withIdentifier: "showDetail", sender: self) } }}//MARK: - UITableViewDataSourceextension ListViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return songList.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let CellIdentifier = "MyCell" let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier) cell!.textLabel!.text = songList[(indexPath as NSIndexPath).row].song return cell! } }
该页面实现简单,主要是关注prepare和restoreUserActivityState方法,在直接点击列表后,会触发prepare方法,跳转到详情页面,并传递所需的数据。当用户点击搜索结果之后,由于触发func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping([Any]?) -> Void) -> Bool方法,方法中我们执行了restoreUserActivityState方法,这里会对获取index进行相应的判断,一旦获取对应的值,就跳转到对应的详情界面,即我们之前选中的页面。
DetailedViewController.swift文件
import UIKitclass DetailedViewController: UIViewController,NSUserActivityDelegate { var songInfo: SongInfo! var songIndex: Int? @IBOutlet weak var songLabel: UILabel! @IBOutlet weak var albumLabel: UILabel! @IBOutlet weak var styleLabel: UILabel! override func viewDidLoad() { super.viewDidLoad() songLabel.text = songInfo.song albumLabel.text = songInfo.album styleLabel.text = songInfo.style //创建NSUserActivity对象,activityType代表activity的类型,值为reverse-DNS format。该值与nfo.plist值保持一致 let activity = NSUserActivity(activityType: "com.appsfoundation.search.song") //activity的名称,当搜索的时候,我们可以看到对应的title activity.title = songInfo.song //在设置title之后,我们可以搜索title,为了提高搜索效果,所有设置一系列局部关键字帮助用户在搜索结果中找到activity var keywords = songInfo.song.components(separatedBy: "") keywords.append(songInfo.album) keywords.append(songInfo.style) activity.keywords = Set(keywords) //该布尔值确定是否能够使用Handoff在其它设备使用该activity activity.isEligibleForHandoff = true //是否应该被添加到设备index activity.isEligibleForSearch = true //是否能够被所有的IOS公众用户访问 activity.isEligibleForPublicIndexing = true //设置代理 activity.delegate = self //是否activity需要被更新,如果为真,在activity被发送之前触发代理方法 activity.needsSave = true //为了避免再indexing之前被释放,需要复制当前创建的activity带全局的userActivity(在UIResponder类中声明)。在创建之后,我们必须添加activity到设备的索引用于搜索结果 userActivity = activity //标记userActivity为当前使用的activity userActivity?.becomeCurrent() } //通知代理用户的activity将被存储,存储用户点击的index,用于点击搜索的内容定位具体的详情页面 func userActivityWillSave(_ userActivity: NSUserActivity) { userActivity.userInfo = ["index" : songIndex!] }}该界面非常简单,主要是创建NSUserActivity对象,并设置相应的属性,在代理方法中使用userActivity中的userInfo字典存储由上级传入选中的位置index,方便在搜索之后点击搜索结果重新定位当前界面。
相关界面效果如下:
0 0
- NSUserActivity的基本使用
- SpotLight和NSUserActivity的使用
- iOS 8 NSUserActivity和iOS9 CoreSpotlight 搜索API的使用
- iOS9搜索三剑客之NSUserActivity
- 多台设备同步 NSUserActivity详解
- Ant 的基本使用
- Ant 的基本使用
- Eclipse的基本使用
- Eclipse的基本使用
- JBuilder的基本使用
- JavaDB的基本使用
- Eclipse的基本使用
- Eclipse的基本使用
- JTable的基本使用
- cscope的基本使用
- gdb的基本使用
- DWR的基本使用
- svn的基本使用
- 基于epoll的聊天室程序
- POJ 1006 Biorhythms (中国剩余定理)
- 七种滤波方法的matlab实现和测试
- java中list集合的深度拷贝
- choose属性的使用(radio,checked)
- NSUserActivity的基本使用
- 求两个数的最大公约数和最小公倍数
- 工作记录之Spring学习笔记(1)集合的注入
- git实战1
- 珠海空号检测的运行原理
- jQuery源码解析之构造函数的方法
- Servlet3.0 新特性之模块化实践
- Leetcode刷题记——14. Longest Common Prefix(最长公共前缀)
- hive函数 -- split 字符串分割函数