Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Search in iOS 9: Needle in a Haystack

Search in iOS 9: Needle in a Haystack

Getting started with iOS search introduced in iOS 9

Matt Blackmon

August 24, 2016
Tweet

Transcript

  1. import MobileCoreServices import CoreSpotlight let attributeSet = CSSearchableItemAttributeSet( itemContentType: kUTTypeData

    as String) attributeSet.title = “Brass" let item = CSSearchableItem( uniqueIdentifier: "uniqueIDForBrass", domainIdentifier: "com.bgaddict.gameEntry", attributeSet: attributeSet) CSSearchableIndex.defaultSearchableIndex() .indexSearchableItems([item]) { error in }
  2. import MobileCoreServices import CoreSpotlight let attributeSet = CSSearchableItemAttributeSet( itemContentType: kUTTypeData

    as String) attributeSet.title = “Brass" let item = CSSearchableItem( uniqueIdentifier: "uniqueIDForBrass", domainIdentifier: "com.bgaddict.gameEntry", attributeSet: attributeSet) CSSearchableIndex.defaultSearchableIndex() .indexSearchableItems([item]) { error in }
  3. import MobileCoreServices import CoreSpotlight let attributeSet = CSSearchableItemAttributeSet( itemContentType: kUTTypeData

    as String) attributeSet.title = “Brass" let item = CSSearchableItem( uniqueIdentifier: "uniqueIDForBrass", domainIdentifier: "com.bgaddict.gameEntry", attributeSet: attributeSet) CSSearchableIndex.defaultSearchableIndex() .indexSearchableItems([item]) { error in }
  4. import MobileCoreServices import CoreSpotlight let attributeSet = CSSearchableItemAttributeSet( itemContentType: kUTTypeData

    as String) attributeSet.title = “Brass" let item = CSSearchableItem( uniqueIdentifier: "uniqueIDForBrass", domainIdentifier: "com.bgaddict.gameEntry", attributeSet: attributeSet) CSSearchableIndex.defaultSearchableIndex() .indexSearchableItems([item]) { error in }
  5. import MobileCoreServices import CoreSpotlight let attributeSet = CSSearchableItemAttributeSet( itemContentType: kUTTypeData

    as String) attributeSet.title = “Brass" let item = CSSearchableItem( uniqueIdentifier: "uniqueIDForBrass", domainIdentifier: "com.bgaddict.gameEntry", attributeSet: attributeSet) CSSearchableIndex.defaultSearchableIndex() .indexSearchableItems([item]) { error in }
  6. let attributeSet = CSSearchableItemAttributeSet( itemContentType: kUTTypeData as String) attributeSet.title =

    “Brass” let thumbnail = UIImage.init(named: "brass")! attributeSet.thumbnailData = UIImageJPEGRepresentation(thumbnail, 0.8) let item = CSSearchableItem( uniqueIdentifier: "uniqueIDForBrass", domainIdentifier: "com.bgaddict.gameEntry", attributeSet: attributeSet) CSSearchableIndex.defaultSearchableIndex() .indexSearchableItems([item]) { error in } let thumbnail = UIImage.init(named: “brass")! attributeSet.thumbnailData = UIImageJPEGRepresentation(thumbnail, 0.8)
  7. let attributeSet = CSSearchableItemAttributeSet( itemContentType: kUTTypeData as String) attributeSet.title =

    “Brass” let thumbnail = UIImage.init(named: "brass")! attributeSet.thumbnailData = UIImageJPEGRepresentation(thumbnail, 0.8) let item = CSSearchableItem( uniqueIdentifier: "uniqueIDForBrass", domainIdentifier: "com.bgaddict.gameEntry", attributeSet: attributeSet) CSSearchableIndex.defaultSearchableIndex() .indexSearchableItems([item]) { error in } let thumbnail = UIImage.init(named: “brass")! attributeSet.thumbnailData = UIImageJPEGRepresentation(thumbnail, 0.8)
  8. let attributeSet = CSSearchableItemAttributeSet( itemContentType: kUTTypeData as String) attributeSet.title =

    “Brass” let thumbnail = UIImage.init(named: "brass")! attributeSet.thumbnailData = UIImageJPEGRepresentation(thumbnail, 0.8) let item = CSSearchableItem( uniqueIdentifier: "uniqueIDForBrass", domainIdentifier: "com.bgaddict.gameEntry", attributeSet: attributeSet) CSSearchableIndex.defaultSearchableIndex() .indexSearchableItems([item]) { error in } attributeSet.contentDescription = "This classic Martin Wallace eurogame recreates the industrial revolution in Northend England”
  9. let attributeSet = CSSearchableItemAttributeSet( itemContentType: kUTTypeData as String) attributeSet.title =

    “Brass” let thumbnail = UIImage.init(named: "brass")! attributeSet.thumbnailData = UIImageJPEGRepresentation(thumbnail, 0.8) let item = CSSearchableItem( uniqueIdentifier: "uniqueIDForBrass", domainIdentifier: "com.bgaddict.gameEntry", attributeSet: attributeSet) CSSearchableIndex.defaultSearchableIndex() .indexSearchableItems([item]) { error in } attributeSet.contentDescription = "This classic Martin Wallace eurogame recreates the industrial revolution in Northend England”
  10. let attributeSet = CSSearchableItemAttributeSet( itemContentType: kUTTypeData as String) attributeSet.title =

    “Brass” let thumbnail = UIImage.init(named: "brass")! attributeSet.thumbnailData = UIImageJPEGRepresentation(thumbnail, 0.8) let item = CSSearchableItem( uniqueIdentifier: "uniqueIDForBrass", domainIdentifier: "com.bgaddict.gameEntry", attributeSet: attributeSet) CSSearchableIndex.defaultSearchableIndex() .indexSearchableItems([item]) { error in } attributeSet.contentDescription = "This classic Martin Wallace eurogame recreates the industrial revolution in Northend England”
  11. So what now? AppDelegate gets called func application(_: UIApplication, continueUserActivity

    userActivity: NSUserActivity, restorationHandler: [AnyObject]? -> Void) -> Bool { if let gameTitle = userActivity.userInfo? ["kCSSearchableItemActivityIdentifier"] as? String where userActivity.activityType == “com.apple.corespotlightitem” { //note: gameTitle == "Brass" return self.navigateToGameDetail(gameTitle) } }
  12. So what now? AppDelegate gets called func application(_: UIApplication, continueUserActivity

    userActivity: NSUserActivity, restorationHandler: [AnyObject]? -> Void) -> Bool { if let gameTitle = userActivity.userInfo? ["kCSSearchableItemActivityIdentifier"] as? String where userActivity.activityType == “com.apple.corespotlightitem” { //note: gameTitle == "Brass" return self.navigateToGameDetail(gameTitle) } }
  13. So what now? AppDelegate gets called func application(_: UIApplication, continueUserActivity

    userActivity: NSUserActivity, restorationHandler: [AnyObject]? -> Void) -> Bool { if let gameTitle = userActivity.userInfo? ["kCSSearchableItemActivityIdentifier"] as? String where userActivity.activityType == “com.apple.corespotlightitem” { //note: gameTitle == "Brass" return self.navigateToGameDetail(gameTitle) } }
  14. let activity = NSUserActivity(activityType: “com.bgaddict.NewsSection") activity.title = "Boardgames News” activity.eligibleForSearch

    = true activity.keywords = ["eurogames", "ameritrash", “essen"] vc.userActivity = activity //vc is a view controller
  15. let activity = NSUserActivity(activityType: “com.bgaddict.NewsSection") activity.title = "Boardgames News” activity.eligibleForSearch

    = true activity.keywords = ["eurogames", "ameritrash", “essen"] vc.userActivity = activity //vc is a view controller
  16. let activity = NSUserActivity(activityType: “com.bgaddict.NewsSection") activity.title = "Boardgames News” activity.eligibleForSearch

    = true activity.keywords = ["eurogames", "ameritrash", “essen"] vc.userActivity = activity //vc is a view controller
  17. let activity = NSUserActivity(activityType: “com.bgaddict.NewsSection") activity.title = "Boardgames News” activity.eligibleForSearch

    = true activity.keywords = ["eurogames", "ameritrash", “essen"] vc.userActivity = activity //vc is a view controller
  18. let activity = NSUserActivity(activityType: “com.bgaddict.NewsSection") activity.title = "Boardgames News” activity.eligibleForSearch

    = true activity.keywords = ["eurogames", "ameritrash", “essen"] vc.userActivity = activity //vc is a view controller
  19. let activity = NSUserActivity(activityType: “com.bgaddict.NewsSection") activity.title = "Boardgames News” activity.eligibleForSearch

    = true activity.keywords = ["eurogames", "ameritrash", “essen"] vc.userActivity = activity //vc is a view controller
  20. let activity = NSUserActivity(activityType: “com.bgaddict.NewsSection") activity.title = "Boardgames News” activity.eligibleForSearch

    = true activity.keywords = ["eurogames", "ameritrash", “essen"] vc.userActivity = activity //vc is a view controller
  21. let activity = NSUserActivity(activityType: “com.bgaddict.NewsSection") activity.title = "Boardgames News” activity.eligibleForSearch

    = true activity.keywords = ["eurogames", "ameritrash", “essen"] vc.userActivity = activity //vc is a view controller
  22. let attributes = CSSearchableItemAttributeSet(itemCo ntentType : kUTTypeData as String) attributes.contentDescription

    = "Latest news from around the globe” let image = UIImage.init(named: “news") let imageData = UIImageJPEGRepresentation(image!, 0.8) attributes.thumbnailData = imageData!
  23. let attributes = CSSearchableItemAttributeSet(itemCo ntentType : kUTTypeData as String) attributes.contentDescription

    = "Latest news from around the globe” let image = UIImage.init(named: “news") let imageData = UIImageJPEGRepresentation(image!, 0.8) attributes.thumbnailData = imageData!
  24. //same attributeSet as used in indexing attributeSet.relatedUniqueIdentifier = “uniqueIDForBrass" //add

    to index, with same id let item = CSSearchableItem( uniqueIdentifier: "uniqueIDForBrass", domainIdentifier: "com.bgaddict.gameEntry", attributeSet: attributeSet) //add to user activity for nav point activity.contentAttributeSet = attributeSet
  25. //same attributeSet as used in indexing attributeSet.relatedUniqueIdentifier = “uniqueIDForBrass" //add

    to index, with same id let item = CSSearchableItem( uniqueIdentifier: "uniqueIDForBrass", domainIdentifier: "com.bgaddict.gameEntry", attributeSet: attributeSet) //add to user activity for nav point activity.contentAttributeSet = attributeSet
  26. //same attributeSet as used in indexing attributeSet.relatedUniqueIdentifier = “uniqueIDForBrass" //add

    to index, with same id let item = CSSearchableItem( uniqueIdentifier: "uniqueIDForBrass", domainIdentifier: "com.bgaddict.gameEntry", attributeSet: attributeSet) //add to user activity for nav point activity.contentAttributeSet = attributeSet
  27. //same attributeSet as used in indexing attributeSet.relatedUniqueIdentifier = “uniqueIDForBrass" //add

    to index, with same id let item = CSSearchableItem( uniqueIdentifier: "uniqueIDForBrass", domainIdentifier: "com.bgaddict.gameEntry", attributeSet: attributeSet) //add to user activity for nav point activity.contentAttributeSet = attributeSet
  28. Preparing your Website { "applinks": { "apps": [], "details": [

    { "appID": "123APPID.com.bgaddict.app", "paths": [ "/game/*", "/news/*"] } ] } } http://bgaddict.com/apple-app-site-association
  29. Preparing your Website For http://bgaddict.com/game/123 <meta name="BGAddict" content="123APPID.com.bgaddict.app, app-argument=http:// bgaddict.com/game/123">

    <title>Brass</title> <meta property="og:description" content="This classic Martin Wallace eurogame recreates the industrial revolution in Northend England”> <span itemprop="reviewCount">74</span> <meta itemprop="ratingValue" content="4">
  30. Preparing your Website For http://bgaddict.com/game/123 <meta name="BGAddict" content="123APPID.com.bgaddict.app, app-argument=http:// bgaddict.com/game/123">

    <title>Brass</title> <meta property="og:description" content="This classic Martin Wallace eurogame recreates the industrial revolution in Northend England”> <span itemprop="reviewCount">74</span> <meta itemprop="ratingValue" content="4">
  31. Preparing your Website For http://bgaddict.com/game/123 <meta name="BGAddict" content="123APPID.com.bgaddict.app, app-argument=http:// bgaddict.com/game/123">

    <title>Brass</title> <meta property="og:description" content="This classic Martin Wallace eurogame recreates the industrial revolution in Northend England”> <span itemprop="reviewCount">74</span> <meta itemprop="ratingValue" content="4">
  32. Preparing your Website For http://bgaddict.com/game/123 <meta name="BGAddict" content="123APPID.com.bgaddict.app, app-argument=http:// bgaddict.com/game/123">

    <title>Brass</title> <meta property="og:description" content="This classic Martin Wallace eurogame recreates the industrial revolution in Northend England”> <span itemprop="reviewCount">74</span> <meta itemprop="ratingValue" content="4">
  33. let universalURL = "http://bgaddict.com/game/ 123" attributeSet.relatedUniqueIdentifier = universalURL //when indexing

    let item = CSSearchableItem( uniqueIdentifier: universalURL, domainIdentifier: "com.bgaddict.gameEntry", attributeSet: attributeSet) //for user activity tracking activity.contentAttributeSet = attributeSet activity.eligibleForPublicIndexing = true Preparing your App
  34. Preparing your App func application(_: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler:

    [AnyObject]? -> Void) -> Bool { if let universalURL = userActivity.webpageURL where userActivity.activityType == NSUserActivityTypeBrowsingWeb { //opened from universal URL self.navigateTo(universalURL) } }
  35. Implementation Advice When debugging, delete your app often Check if

    CoreSpotlight is available on device (Almost) All Apps can use NSUserActivity Consider iOS 10
  36. Implementation Advice When debugging, delete your app often Check if

    CoreSpotlight is available on device (Almost) All Apps can use NSUserActivity Consider iOS 10
  37. Implementation Advice When debugging, delete your app often Check if

    CoreSpotlight is available on device (Almost) All Apps can use NSUserActivity Consider iOS 10
  38. Implementation Advice When debugging, delete your app often Check if

    CoreSpotlight is available on device (Almost) All Apps can use NSUserActivity Consider iOS 10
  39. Improving Rankings Add Actions for Navigation or Phone Calls Get

    to your content fast — it’s timed Keep your content current Don’t spam the index
  40. Improving Rankings Add Actions for Navigation or Phone Calls Get

    to your content fast — it’s timed Keep your content current Don’t spam the index
  41. Improving Rankings Add Actions for Navigation or Phone Calls Get

    to your content fast — it’s timed Keep your content current Don’t spam the index
  42. Improving Rankings Add Actions for Navigation or Phone Calls Get

    to your content fast — it’s timed Keep your content current Don’t spam the index
  43. Plan • Index Based Searching (Spotlight) • Usage Based Searching

    (NSUserActivity) • Web Informed Searching (Universal URLs) • Best Practices (Do as much as possible)
  44. Resources • WWDC 2015: Session 709, WWDC 2016: Session 223

    • App Validation tool (https://search.developer.apple.com/) • Technical Note TN2416( https://developer.apple.com/library/ios/ technotes/tn2416/_index.html) • OpenGraph (http://ogp.me) • Apple Developer forums (https://forums.developer.apple.com/ community/app-frameworks/spotlight)
  45. Fin