iOS 9的新内容
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:
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeImage as String)
attributeSet.title = "My Great Content"
attributeSet.contentDescription = "This is something you'll search for." let item = CSSearchableItem(uniqueIdentifier: "YOUR UNIQUE CONTENT IDENTIFIER HERE", domainIdentifier: "com.hackingwithswift", attributeSet: attributeSet)
CSSearchableIndex.defaultSearchableIndex().indexSearchableItems([item]) { (err: NSError?) -> Void in
print("Search item successfully indexed!")
}
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:
func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
if userActivity.activityType == CSSearchableItemActionType {
let uniqueIdentifier = userActivity.userInfo?[CSSearchableItemActivityIdentifier]
print("Do stuff with \(uniqueIdentifier)")
} return true
}
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:
import SafariServices
Second, make your view controller conform to the SFSafariViewControllerDelegate
delegate, using something like this:
class ViewController: UIViewController, SFSafariViewControllerDelegate {
Third, create and show the SFSafariViewController
, pointing at a URL of your choosing:
let sfc = SFSafariViewController(URL: NSURL(string: "http://www.slashdot.org")!)
sfc.delegate = self
presentViewController(sfc, animated: true, completion: nil)
Finally, catch the delegate callback safariViewControllerDidFinish()
, which is triggered when the user taps the built-in Done button:
func safariViewControllerDidFinish(controller: SFSafariViewController) {
controller.dismissViewControllerAnimated(true, completion: nil)
}
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:
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 UICollectionViewFlowLayout
, sectionHeadersPinToVisibleBounds
, 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的新内容的更多相关文章
- fir.im Weekly - 从 iOS 10 SDK 新特性说起
从 iOS 7 翻天覆地的全新设计,iOS 8 中 Size Classes 的出现,应用扩展,以及 Cloud Kit 的加入,iOS 9 的分屏多任务特性,今年的 WWDC iOS 10 SDK ...
- 从iOS 11 UI Kit中谈谈iOS 11的新变化
北京时间9月20日凌晨1点,iOS 11终于迎来了正式版的推送,相信各位小伙伴已经在第一时间进行了升级.iOS 11毫无疑问是一次大规模的系统更新,UI.系统内核.锁屏等多方面都进行了不同程度的改进. ...
- iOS 9的新的改变 iOS SDK Release Notes for iOS 9 说了些改变
iOS 9的新的改变 iOS SDK Release Notes for iOS 9 说了些改变 看了下还算能理解!!!有兴趣可以看看哈!!!不喜勿喷!!后面的对于废除的方法什么有用感觉!!! ...
- Windows cmd 长时间不输出新内容 直到按下ctrl + c 取消或者回车的解决办法
换了一台新电脑, 在使用 ant 拷贝大量文件的时候 cmd 窗口过了很久没有继续输出新的内容,远远超过平时的耗时, 以为已经卡死 按下 ctrl + c 取消, 这时并没有取消, 而是输出了新内容, ...
- 新内容转入github
所有新内容已经转入 https://github.com/honggzb/Study-General https://github.com/honggzb/Study2016
- jQuery 往table添加新内容有以下四个方法:
Query 添加新内容有以下四个方法: append() - 在被选元素的结尾插入内容 prepend() - 在被选元素的开头插入内容 after() - 在被选元素之后插入内容 before() ...
- xcode10设置自定义代码快 - Xcode10新功能新内容
1. 2. 详情: Xcode10新功能新内容https://blog.csdn.net/u010960265/article/details/80630118
- 添加新内容的四个 jQuery 方法:append,prepend,after,before
添加新内容的四个 jQuery 方法区别如下: append() - 在被选元素(里面)的结尾插入内容prepend() - 在被选元素(里面)的开头插入内容 //jQuery append() 方法 ...
- Ajax实例二:取得新内容
Ajax实例二:取得新内容 通过点击pre和next按钮,从服务器取得最新内容. HTML代码 <div id="slide">图片显示区</div> &l ...
随机推荐
- D&F学数据结构系列——B树(B-树和B+树)介绍
B树 定义:一棵B树T是具有如下性质的有根树: 1)每个节点X有以下域: a)n[x],当前存储在X节点中的关键字数, b)n[x]个关键字本身,以非降序存放,因此key1[x]<=key2[x ...
- SELECT 语句不详解
INSERT INTO ... SELECT 语句, 将查询的结果插入到一张新表中(可为临时表) DECLARE @MyTable Table ( SalesOrderID int, Custome ...
- Gradle Goodness: Continue Build Even with Failed Tasks
If we run a Gradle build and one of the tasks fails, the whole build stops immediately. So we have f ...
- lintcode:寻找旋转排序数组中的最小值 II
寻找旋转排序数组中的最小值 II 假设一个旋转排序的数组其起始位置是未知的(比如0 1 2 4 5 6 7 可能变成是4 5 6 7 0 1 2). 你需要找到其中最小的元素. 数组中可能存在重复的元 ...
- PushBackInputStream与PushBackInputStreamReader的用法
举个例子:获取XX内容 PushBackInputStream pb=new PushBackInputStream(in,4);//4制定缓冲区大小 byte[] buf=new byte[4]; ...
- Android核心分析之二十五Android GDI之共享缓冲区机制
Androird GDI之共享缓冲区机制 1 native_handle_t对private_handle_t 的包裹 private_handle_t是gralloc.so使用的本地缓冲区 ...
- eclipse导入maven项目后依赖jar包更新问题->update project按钮
eclipse导入maven项目后依赖jar包更新问题 1.eclipse有专门的导入maven项目按钮,file-import-maven project,eclipse会自动查找指定路径下的pom ...
- 使用 JAX-RS 简化 REST 应用开发
本文将详细介绍 Java EE 6 中所引入的对 JSR-311 (JAX-RS : Java API for RESTful Web Services) 的支持,并通过一个完整的示例应用程序展示 J ...
- linux查询cpu核心数
linux怎么查询cpu核心数 1.查看逻辑CPU个数: #cat /proc/cpuinfo |grep "processor"|sort -u|wc -l24 2.由于有超线程 ...
- Android 自定义View,仿微信视频播放按钮
闲着,尝试实现了新版微信视频播放按钮,使用的是自定义View,先来个简单的效果图...真的很简单哈. 由于暂时用不到,加上时间原因,加上实在是没意思,加上……,本控件就没有实现自定义属性,有兴趣的朋友 ...