https://www.hackingwithswift.com/ios9

Search extensibility

Update: I wrote a tutorial on Core Spotlight in iOS 9 as Hacking with Swift project 32 – check it out!

Finally (finally!) you can hook your apps directly into Spotlight for integrated, system-wide search, and it comes in the form of CoreSpotlight. But don't get your hopes up: Spotlight doesn't just magically index all your data while you sit back and snooze. Instead, you need to specify exactly what you want to expose to the outside world.

What's more, Apple is specifically focusing this technology on things that are going to be directly useful to the user, so you need to be careful what you index in Spotlight. We don't know how the algorithm works, but Apple has said that iOS will automatically monitor how frequently users interact with your search results, and if you consistently serve up unhelpful results because you indexed your data badly then your results may stop appearing.

To get started, create a new instance of the CSSearchableItemAttributeSet class, then give it a title and acontentDescription. You then wrap that inside a CSSearchableItem, before passing it to CSSearchableIndex using itsindexSearchableItems method.

If a user taps on one of your search results in Spotlight, your app will get launched with a new app delegate callback:application:continueUserActivity:restorationHandler:. If the activity type of the NSUserActivity that gets passed in matches CSSearchableItemActionType, you can immediately direct the user to the relevant content by pulling out theCSSearchableItemActivityIdentifier key from the activity's userInfo dictionary.

If you prefer to read code, here's an example:

  1. let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeImage as String)
  2. attributeSet.title = "My Great Content"
  3. attributeSet.contentDescription = "This is something you'll search for."
  4.  
  5. let item = CSSearchableItem(uniqueIdentifier: "YOUR UNIQUE CONTENT IDENTIFIER HERE", domainIdentifier: "com.hackingwithswift", attributeSet: attributeSet)
  6. CSSearchableIndex.defaultSearchableIndex().indexSearchableItems([item]) { (err: NSError?) -> Void in
  7. print("Search item successfully indexed!")
  8. }

You'll need to import both CoreSpotlight and MobileCoreServices to make that code work. You will also need to replace "YOUR UNIQUE CONTENT IDENTIFIER HERE" with something meaningful to you that uniquely identifies this content, so that if the user launches your app as a result of doing a Spotlight search, you know what to look for.

Speaking of which, here's the code to put in your app delegate to load some content after a Spotlight search:

  1. func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
  2. if userActivity.activityType == CSSearchableItemActionType {
  3. let uniqueIdentifier = userActivity.userInfo?[CSSearchableItemActivityIdentifier]
  4. print("Do stuff with \(uniqueIdentifier)")
  5. }
  6.  
  7. return true
  8. }

Again, make sure you import CoreSpotlight so your code compiles. Hopefully you can now see why the unique identifier is so important – it's what your app gets handed so you can load the correct content.

There are various extensions to CSSearchableItemAttributeSet to encode data such as events and map co-ordinates, so this could prove to be one of the biggest new features in iOS 9. To see just how much information you can encode (focal length for images! media copyright information! contact phone numbers!) press Shift+Cmd+O and type CSSearchableItemAttributeSet then wait for the completions to appear - you'll see media, events, images, places and more.

App Thinning

Universal apps (aka "fat binaries") have always meant that Apple ships a single app package that contains all the assets and code for it to run on any supported device. So, since the iPad launched that meant every iPhone app automatically included all the iPad imagery even though it wasn't used.

When the number of supported devices was low (non-retina iPhone and non-retina iPad) this wasn't a huge problem, and if you were smart about your assets most users wouldn't care. But as devices have proliferated, each app now needs to include iPhone retina, iPhone retina HD, iPad non-retina and iPad retina, all in one package, even though each device will only be showing one set of assets.

Apple's solution is something developers have been asking for for a long time: app thinning ensures that users download only the app components required to run the app on their specific device, which means an iPhone retina device (4s, 5, 5s, 6) will download only retina assets and not retina HD devices. The result: smaller apps, faster downloads, and happier users.

But App Thinning is even cleverer, because with Xcode 7 you upload your app to iTunes connect in an intermediate state called Bitcode. When users download your app, the App Store will automatically produce an optimized version of your app (i.e., 64-bit if needed) to match the device the user is using. This means they get only the assets they need and only the binary code they need, making the download even smaller.

Still think that's not enough? Apparently Apple agrees, because as part of App Thinning you can now host content for your app in iTunes Connect, and request it inside your app only when needed. This has been possible with in-app purchases for a few years, but being able to tag and fetch content on demand is new and very interesting.

I wonder whether Apple is shipping app thinning now in preparation to launch an @3x iPad – such a device would have huge images, so old school universal binaries would be more wasteful than ever.

GameplayKit

Update: I wrote a tutorial on GameplayKit and GKMinmaxStrategist in iOS 9 as Hacking with Swift project 34 – check it out!

Update 2: I wrote a tutorial on GameplayKit and GKRandomSource in iOS 9 as Hacking with Swift project 35 – check that out too!

This is easily one of the most surprising changes in iOS 9, and it was rushed over so quickly in the keynote that if you blinked you probably missed it. GameplayKit is surprising because of what it does: it's designed to make it easy to add high-level gameplay logic without having to code the algorithms yourself. State machines? Done. Randomization? Check. Path finding? Got it.

To give you an idea of just how powerful GameplayKit is, Apple has shipped demo code for a four-in-a-row game that uses a new class called GKMinmaxStrategist. This is a class that can, under certain conditions, provide AI responses to automatically win in a game. Those conditions are pretty simple: the game must be sequential (i.e., players take turns), the game must be zero sum (one player loses when the other wins), the game must not be based on chance, and you must be able to provide GKMinmaxStrategist with perfect information – that is, all information required to play and win is openly visible.

SFSafariViewController

Update: I wrote a tutorial on SFSafariViewController in iOS 9 as Hacking with Swift project 32 – check it out!

iOS 8 gave us WKWebView, the super-fast new way of using WebKit inside our apps that also included some UI elements such as swiping between the page history. iOS 9 goes one step further: SFSafariViewController is a wholly embedded Safari inside your app, exposing even more behaviour that users have come to expect, such as shared cookies, AutoFill of forms, and Reader Mode.

This might seem like a strange thing to do, but think about it: lots of apps have embedded web browsers inside them, such as when you tap a link inside Twitter. But frequently these embedded web views just aren't as good as Safari, so you end up tapping the inevitable "Open in Safari" button just to escape. Well, with iOS 9 is no longer needed: SFSafariViewController is a full-screen Safari user interface controller by Apple, with a simple Done button to return to your app.

To try it out now, you need to do four things. First, pull in the SafariServices framework like this:

  1. import SafariServices

Second, make your view controller conform to the SFSafariViewControllerDelegate delegate, using something like this:

  1. class ViewController: UIViewController, SFSafariViewControllerDelegate {

Third, create and show the SFSafariViewController, pointing at a URL of your choosing:

  1. let sfc = SFSafariViewController(URL: NSURL(string: "http://www.slashdot.org")!)
  2. sfc.delegate = self
  3. presentViewController(sfc, animated: true, completion: nil)

Finally, catch the delegate callback safariViewControllerDidFinish(), which is triggered when the user taps the built-in Done button:

  1. func safariViewControllerDidFinish(controller: SFSafariViewController) {
  2. controller.dismissViewControllerAnimated(true, completion: nil)
  3. }

One of the neat features of SFSafariViewController is that it comes with reader mode built in, and you can actually navigate straight to that view by using this code:

  1. let sfc = SFSafariViewController(URL: NSURL(string: "http://www.slashdot.org")!, entersReaderIfAvailable: true)

UIStackView

Update: I wrote a tutorial on UIStackView and iPad multitasking in iOS 9 as Hacking with Swift project 31 – check it out!

Android developers have long had a layout system called LinearLayout, where you add views to a superview and they automatically get placed either beneath each other or side by side. We haven't really had a good solution like this on iOS – table views are greatly at stacking information vertically, but are of course hugely limited in terms of their content.

With UIStackView, that's all changed: you can now add a series of views to a superview, specify how much spacing you want between them, and Auto Layout handles the rest for you. You get to choose whether you want the subviews to have equal sizes (.FillEqually) or proportional sizes (.FillProportionally) based on their intrinsic content sizes. You can also choose whether you want the subviews to fill horizontally or vertically, and you can change your mind later.

Important note: UIStackViews don't scroll, they just act as containers that automatically fit their content.

UICollectionViews can now behave more like UITableViews

With one simple boolean property for UICollectionViewFlowLayoutsectionHeadersPinToVisibleBounds, you can now make your flow layout work the same way as UITableView has always done: your section headers stick to the top of the screen while the user is scrolling inside that section, and only get pushed off when the next section comes in. Way, way overdue, but at least it's here now.

UICollectionViews now have easy re-ordering

Set the installsStandardGestureForInteractiveMovement property to true on your UICollectionViewController and give users the ability to re-order your items.

SKAudioNode

One of the major SpriteKit annoyances has been its simplistic audio system. In iOS 8, for example, you can play sounds but not stop them, and heaven forbid if you want to control the sound in any way. Well, in iOS 9 we have SKAudioNode to the rescue: not only can you pause and stop sounds (hurray!) but you can also set its positional property to true to have its sound adjusted based on the node's position in your scene. Yes: SpriteKit now has 3D audio.

Lots of tiny changes

One of my favorite things to do when Apple flicks the switch on a new iOS release is to read through the complete list of API changes, looking for all the tiny improvements and tweaks Apple makes each year. Here are some of the changes that jumped out to me this year:

  • UIViewController now has an addKeyCommand() method to register UIKeyCommands on your view controllers – manna from heaven for users of external keyboards.
  • MKMapView.showsTraffic: set it to true, and it, er, shows the traffic. Simple, but such a huge feature to have.
  • CIFeatureTypeText sounds like Apple added some sort of OCR to iOS, but sadly it just gives you the bounds where text was located. It's a step forward, but only a small one.
  • Just look at AVFoundation. Go on, look at it and cry tears of joy.

iOS 9的新内容的更多相关文章

  1. fir.im Weekly - 从 iOS 10 SDK 新特性说起

    从 iOS 7 翻天覆地的全新设计,iOS 8 中 Size Classes 的出现,应用扩展,以及 Cloud Kit 的加入,iOS 9 的分屏多任务特性,今年的 WWDC iOS 10 SDK ...

  2. 从iOS 11 UI Kit中谈谈iOS 11的新变化

    北京时间9月20日凌晨1点,iOS 11终于迎来了正式版的推送,相信各位小伙伴已经在第一时间进行了升级.iOS 11毫无疑问是一次大规模的系统更新,UI.系统内核.锁屏等多方面都进行了不同程度的改进. ...

  3. iOS 9的新的改变 iOS SDK Release Notes for iOS 9 说了些改变

    iOS 9的新的改变 iOS SDK Release Notes for iOS 9 说了些改变   看了下还算能理解!!!有兴趣可以看看哈!!!不喜勿喷!!后面的对于废除的方法什么有用感觉!!!   ...

  4. Windows cmd 长时间不输出新内容 直到按下ctrl + c 取消或者回车的解决办法

    换了一台新电脑, 在使用 ant 拷贝大量文件的时候 cmd 窗口过了很久没有继续输出新的内容,远远超过平时的耗时, 以为已经卡死 按下 ctrl + c 取消, 这时并没有取消, 而是输出了新内容, ...

  5. 新内容转入github

    所有新内容已经转入 https://github.com/honggzb/Study-General https://github.com/honggzb/Study2016

  6. jQuery 往table添加新内容有以下四个方法:

    Query 添加新内容有以下四个方法: append() - 在被选元素的结尾插入内容 prepend() - 在被选元素的开头插入内容 after() - 在被选元素之后插入内容 before() ...

  7. xcode10设置自定义代码快 - Xcode10新功能新内容

    1. 2. 详情: Xcode10新功能新内容https://blog.csdn.net/u010960265/article/details/80630118

  8. 添加新内容的四个 jQuery 方法:append,prepend,after,before

    添加新内容的四个 jQuery 方法区别如下: append() - 在被选元素(里面)的结尾插入内容prepend() - 在被选元素(里面)的开头插入内容 //jQuery append() 方法 ...

  9. Ajax实例二:取得新内容

    Ajax实例二:取得新内容 通过点击pre和next按钮,从服务器取得最新内容. HTML代码 <div id="slide">图片显示区</div> &l ...

随机推荐

  1. Codeforces 414C Mashmokh and Reverse Operation

    题意:给你2^n个数,每次操作将其分成2^k份,对于每一份内部的数进行翻转,每次操作完后输出操作后的2^n个数的逆序数. 解法:2^n个数,可以联想到建立一棵二叉树的东西,比如  2,1,4,3就可以 ...

  2. java与.net之间xml传递,xml最前面多了个?

    最近做一个项目,是java提供webservice供.net调用.参数采用xml格式.首先碰到的问题: 1).net这边采用XmlSerializer 方式序列化对象传递给对方.对方在本机调试可以收到 ...

  3. POJ 2182

    #include <iostream> #define MAXN 8005 using namespace std; int _m[MAXN]; int main() { //freope ...

  4. spring_150802_resource

    接口Service: package com.spring.service; public interface DogPetService { public void queryAllDogPets( ...

  5. 做一款仿映客的直播App

    投稿文章,作者:JIAAIR(GitHub) 一.直播现状简介 1.技术实现层面 技术相对都比较成熟,设备也都支持硬编码.iOS还提供现成的Video ToolBox框架,可以对摄像头和流媒体数据结构 ...

  6. sqlmap 使用举例

    详细的请见: http://drops.wooyun.org/tips/143 http://wenku.baidu.com/link?url=45xj6EVVWQjV8upwrBAMIqPP3xMc ...

  7. Python3导入自定义模块的3种方式

    前话 最近跟着廖雪峰的教程学到 模块 这一节.关于如何自定义一个模块,如果大家不懂的话还请先看下面这篇博文 ↓ http://www.liaoxuefeng.com/wiki/001431608955 ...

  8. SQL语句 递归

    --正向递归查询(根据ID查到自己和自己以下的所有数据)   connect by prior a.id = a. parentid   --反向递归查询(根据叶子ID查出自己和自己以上的根数据)   ...

  9. wordcount数据流过程解析

    (1)执行hadoopFile()操作,其中有生成HadoopRDD的new 方法.然后执行map方法.pair => pair._2.toString,只对Value值进行操作.在textFi ...

  10. Data Flow ->> Pivot

    这个组件和SQL Server的Pivot基本就是一回事.不过我观察到SSIS的Pivot只支持SUM这种聚合类型,并没有找到哪个选择可以设置聚合类型,而T-SQL语法的Pivot则支持多种聚合类型, ...