iOS 8 新特性介绍

随便去问任何人,他们都会告诉你WWDC2014是近年来最为激动的回忆。 整个大会没有发布任何新硬件,它是一次史无前例的软件开发者盛宴!

仅是iOS 8和OS X Yosemite的发布就能让2014成为苹果平台划时代的一年,加上Extension,Continuity,SpriteKit 改进,iOS SceneKit,Metal,HealthKit,Local Authentication和全新的照片框架。更不用说,Xcode和Interface Builder的明显改观,重新设计的iTunes Connect,TestFlight,崩溃报告和CloudKit。当然还有oh yeah-Swift。

更棒的是?苹果放松了她的保密协定,也就是说我们可以现在就公开讨论这些崭新的玩具!

这周,我们将拨开iOS 8的云雾,探讨一些所有人都应该知道新API。

从现在开始NSHipster讲主要使用Swift写样历代吗。夏天结束之前,我们希望能将全部的现存代码转换为Swift,并且提供可以切换语言的选项。


NSProcessInfo -isOperatingSystemAtLeastVersion

忘记[[UIDevice currentDevice] systemVersion]NSFoundationVersionNumber吧, 现在可以用NSProcessInfo -isOperatingSystemAtLeastVersion来确定系统版本。

1
2
3
4
import Foundation
 
let yosemite = NSOperatingSystemVersion(majorVersion: 10, minorVersion: 10, patchVersion: 0)
NSProcessInfo().isOperatingSystemAtLeastVersion(yosemite) // false

值得注意的是,在做兼容性测试的时候还是应该使用SomeClass.classrespondsToSelector:。 Swift和C中的编译器宏可以用来根据不同生成配置和目标来选择代码。

新的NSFormatter子类

Foundation中严重缺失的一项功能就是不能处理重量和长度单位转换。在iOS 8和OS X Yosemite中,引进了三个新类NSEnergyFormatterNSMassFormatterNSLengthFormatter来弥补这一缺失。

这使得NSFormatter子类的数量翻了一倍, 之前只有NSNumberFormatterNSDateFormatterNSByteCountFormatter

虽然这些都是Foundation的子类,但是它们主要都是在HealthKit当中使用。

NSEnergyFormatter

NSEnergyFormatter使用焦作为能量的原始单位,当处理健康信息时,则使用卡.

1
2
3
4
5
let energyFormatter = NSEnergyFormatter()
energyFormatter.forFoodEnergyUse = true
 
let joules = 10_000.0
println(energyFormatter.stringFromJoules(joules)) // "2.39 Cal"

NSMassFormatter

虽然质量是物质存在的基本单位, 在HealthKit中,它主要指的是身体重量.

1
2
3
let massFormatter = NSMassFormatter()
let kilograms = 60.0
println(massFormatter.stringFromKilograms(kilograms)) // "132 lb"

NSLengthFormatter

NSFormatter的最后一个新子类是NSLengthFormatter. 我们可以把它想象为MKDistanceFormatter的加强版。

1
2
3
let lengthFormatter = NSLengthFormatter()
let meters = 5_000.0
println(lengthFormatter.stringFromMeters(meters)) // "3.107 mi"

CMPedometer

沿着iOS 8的健康路线, CMStepCounter被重新设计了. CMPedometer作为它的改良版本不仅可以即时获取离散的点数据,并且可以同时跟踪脚步和距离,甚至计算总共爬了多少级楼梯。

M7芯片真是功能强大.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import CoreMotion
 
let lengthFormatter = NSLengthFormatter()
let pedometer = CMPedometer()
pedometer.startPedometerUpdatesFromDate(NSDate(), withHandler: { data, error in
     if !error {
         println( "Steps Taken: <span class=" MathJax_Preview ">\(data.numberOfSteps)" )
 
         let distance = data.distance.doubleValue
         println( "Distance: \)</span><script type=" math/tex ">data.numberOfSteps)" )
 
         let distance = data.distance.doubleValue
         println( "Distance: </script>lengthFormatter.stringFromMeters(distance))" )
 
         let time = data.endDate.timeIntervalSinceDate(data.startDate)
         let speed = distance / time
         println( "Speed: <span class=" MathJax_Preview ">\(lengthFormatter.stringFromMeters(speed)) / s" )
     }
})</span>

CMAltimeter

????????CMAltimeter???CMPedometer?floorsAscended?floorsDescended???????

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import CoreMotion
 
let altimeter = CMAltimeter()
if CMAltimeter.isRelativeAltitudeAvailable() {
     altimeter.startRelativeAltitudeUpdatesToQueue(NSOperationQueue.mainQueue(), withHandler: { data, error in
         if !error {
             println( "Relative Altitude: \)<script type=" math/tex ">lengthFormatter.stringFromMeters(speed)) / s" )
     }
})</pre>
<h2 id= "cmaltimeter" >CMAltimeter</h2>
<p>????????<code>CMAltimeter</code>???<code>CMPedometer</code>?<code>floorsAscended</code>?<code>floorsDescended</code>???????</p>
<pre class = "brush: csharp; gutter: true" >import CoreMotion
 
let altimeter = CMAltimeter()
if CMAltimeter.isRelativeAltitudeAvailable() {
     altimeter.startRelativeAltitudeUpdatesToQueue(NSOperationQueue.mainQueue(), withHandler: { data, error in
         if !error {
             println( "Relative Altitude: </script>data.relativeAltitude)" )
         }
     })
}

CLFloor

CLFloor的引入展示了苹果进军室内导航的宏伟计划,楼层信息将扮演着重要的角色。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import CoreLocation
 
class LocationManagerDelegate: NSObject, CLLocationManagerDelegate {
     func locationManager(manager: CLLocationManager!, didUpdateLocations locations: AnyObject[]!) {
         let location: CLLocation? = locations[0] as ? CLLocation
         if let floor: CLFloor? = location?.floor {
             println( "Current Floor: $$floor?.level)" )
         }
     }
}
 
let manager = CLLocationManager()
manager. delegate = LocationManagerDelegate()
manager.startUpdatingLocation()

HKStatistics

作为一个框架,HealthKit包含着大量的子类和常量。要想全部理解,HKStatistics是一个很好的开始。

HealthKit管理着所有的生理信息,例如:心率,卡路里摄入量,血氧等等,并且通过统一的API聚合在一起。

下面这个例子演示了如何从一天的连续数据中,挖掘和获取单独的数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import HealthKit
 
let collection: HKStatisticsCollection? = ...
let statistics: HKStatistics? = collection!.statisticsForDate(NSDate())
for item: AnyObject in statistics!.sources {
     if let source = item as ? HKSource {
         if let quantity: HKQuantity = statistics!.sumQuantityForSource(source) {
             if quantity.isCompatibleWithUnit(HKUnit.gramUnitWithMetricPrefix(.Kilo)) {
                 let massFormatter = NSMassFormatter()
                 let kilograms = quantity.doubleValueForUnit(HKUnit.gramUnitWithMetricPrefix(.Kilo))
                 println(massFormatter.stringFromKilograms(kilograms))
             }
 
             if quantity.isCompatibleWithUnit(HKUnit.meterUnit()) {
                 let lengthFormatter = NSLengthFormatter()
                 let meters = quantity.doubleValueForUnit(HKUnit.meterUnit())
                 println(lengthFormatter.stringFromMeters(meters))
             }
 
             if quantity.isCompatibleWithUnit(HKUnit.jouleUnit()) {
                 let energyFormatter = NSEnergyFormatter()
                 let joules = quantity.doubleValueForUnit(HKUnit.jouleUnit())
                 println(energyFormatter.stringFromJoules(joules))
             }
         }
     }
}

NSHipster将会在未来探讨更多的HealthKit,敬请关注!

NSStream +getStreamsToHostWithName

在许多方面,WWDC 2014也是苹果查漏补遗的一年,比如给NSStream添加了新的initializer(再也不用调用CFStreamCreatePairWithSocketToHost了),这就是:+[NSStream getStreamsToHostWithName:port:inputStream:outputStream:]

1
2
3
4
5
6
7
var inputStream: NSInputStream?
var outputStream: NSOutputStream?
 
NSStream.getStreamsToHostWithName(hostname: "nshipster.com" ,
                                       port: 5432,
                                inputStream: &inputStream,
                               outputStream: &outputStream)

NSString -localizedCaseInsensitiveContainsString

这又是一个NSString小而实用的修缮:

1
2
3
4
let string : NSString = "Café"
let substring: NSString = "É"
 
string .localizedCaseInsensitiveContainsString(substring) // true

 

CTRubyAnnotationRef

好吧,此Ruby非彼Ruby. . 这是用来给亚洲文字添加注音符号的.

1
2
3
4
5
6
7
8
9
10
@import CoreText;
 
NSString *kanji = @"猫" ;
NSString *hiragana = @"ねこ" ;
 
CFStringRef furigana[kCTRubyPositionCount] =
     {(__bridge CFStringRef)hiragana, NULL, NULL, NULL};
 
CTRubyAnnotationRef ruby =
     CTRubyAnnotationCreate(kCTRubyAlignmentAuto, kCTRubyOverhangAuto, 0.5, furigana);

无可否认的是,文档中并没有很清晰的描述具体如何将它整合进入你剩下的CoreText中,但是结果如下:

猫ねこ

新的日历识别符

iOS 8和OS X中这些新的日历识别符使得Fundation跟上了CLDR的步伐:

  • NSCalendarIdentifierCoptic: 亚历山大日历, 科普特正教使用.
  • NSCalendarIdentifierEthiopicAmeteMihret: 埃塞俄比亚日历, Amete Mihret
  • NSCalendarIdentifierEthiopicAmeteAlem: 埃塞俄比日历, Amete Alem
  • NSCalendarIdentifierIslamicTabular: 一个简单的伊斯兰星历.
  • NSCalendarIdentifierIslamicUmmAlQura: 沙特阿拉伯伊斯兰日历.

NSURLCredentialStorage

自从去年NSURLSession的引入之后,Foundation的URL载入系统并没有太大的改变。但是,新的NSURLCredentialStorage可以让你更加方便地以移步,非闭包的方式获取和存储密码。

1
2
3
4
5
6
7
8
9
10
11
import Foundation
 
let session = NSURLSession()
let task = session.dataTaskWithURL(NSURL( string : "http://nshipster.com" ), completionHandler: { data, response, error in
     // ...
})
 
let protectionSpace = NSURLProtectionSpace()
NSURLCredentialStorage.getCredentialsForProtectionSpace(protectionSpace: protectionSpace, task: task, completionHandler: { credentials in
     // ...
})

kUTTypeToDoItem

在比较过最新的API之后,你可能会注意到大量的新UTI常量。其中,kUTTypeToDoItem引起了我的注意:

1
2
3
import MobileCoreServices
 
kUTTypeToDoItem // "public.to-do-item"

作为一个公共类型,iOS和OS X现在提供了统一的方式让App之间共享任务。如果你碰巧正在开发一个任务管理工具,正确的整合好这个系统类型应该成为你的首要任务。

kCGImageMetadataShouldExcludeGPS

许多用户完全不知道他们用手机拍摄的大部分照片都包含了GPS元数据。更是有数不清的人因为这一个小细节泄露了自己的隐私。

最新的图片I/O框架中加入了一个新的选项CGImageDestination:kCGImageMetadataShouldExcludeGPS让你方便的控制是否包含GPS元数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@import UIKit;
@import ImageIO;
@import MobileCoreServices;
 
UIImage *image = ...;
NSURL *fileURL = [NSURL fileURLWithPath: @"/path/to/output.jpg" ];
NSString *UTI = kUTTypeJPEG;
NSDictionary *options = @{
                           (__bridge id)kCGImageDestinationLossyCompressionQuality: @(0.75),
                           (__bridge id)kCGImageMetadataShouldExcludeGPS: @(YES),
                           };
 
CGImageDestinationRef imageDestinationRef =
CGImageDestinationCreateWithURL((__bridge CFURLRef)fileURL,
                                 (__bridge CFStringRef)UTI,
                                 1,
                                 NULL);
 
CGImageDestinationAddImage(imageDestinationRef, [image CGImage], (__bridge CFDictionaryRef)options);
CGImageDestinationFinalize(imageDestinationRef);
CFRelease(imageDestinationRef);

WTF_PLATFORM_IOS

#define WTF_PLATFORM_IOS已经从JavaScriptCore中移除.

WKWebView

UIWebView已死. WKWebView万岁.

WKWebView提供了Safari级别的性能,并且在UIWebView的基础上提供了更多的配置选项:

1
2
3
4
5
6
7
8
9
10
11
import WebKit
 
let preferences = WKPreferences()
preferences.javaScriptCanOpenWindowsAutomatically = false
 
let configuration = WKWebViewConfiguration()
configuration.preferences = preferences
 
let webView = WKWebView(frame: self.view.bounds, configuration: configuration)
let request = NSURLRequest(URL: NSURL( string : "http://nshipster.com" ))
webView.loadRequest(request)

NSQualityOfService

线程这个概念已经在苹果的框架中被系统性的忽略。这对于开发者而言是件好事。

沿着这个趋势,NSOperation中新的qualityOfService的属性取代了原来的threadPriority。通过它可以推迟那些不重要的任务,从而让用户体验更加流畅。

NSQualityOfService枚举定义了以下值:

  • UserInteractive:和图形处理相关的任务,比如滚动和动画。
  • UserInitiated:用户请求的任务,但是不需要精确到毫秒级。例如,如果用户请求打开电子邮件App来查看邮件。
  • Utility:周期性的用户请求任务。比如,电子邮件App可能被设置成每五分钟自动检查新邮件。但是在系统资源极度匮乏的时候,将这个周期性的任务推迟几分钟也没有大碍。
  • Background:后台任务,用户可能并不会察觉对这些任务。比如,电子邮件App对邮件进行引索以方便搜索。

Quality of Service将在iOS 8和OS X Yosemite中广泛的应用,所以留意所有能利用它们的机会。

LocalAuthentication

最后,最令人期待的iOS 8新功能之一:LocalAuthentication。自从iPhone 5S加入TouchID,开发者就对它的应用前景垂涎三尺。

想象一下,只要有CloudKit和LocalAuthentication,创建新账号的烦恼讲不复存在。只需要扫描一下你的手就搞定了!

LocalAuthentication以LAContext的方式工作,验证声明的规格,然后返回是否验证成功。整个过程中,用户的生物信息都被安全的储存在硬件当中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
LAContext *context = [[LAContext alloc] init];
NSError *error = nil;
 
if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
                          error:&error])
{
     [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
             localizedReason:NSLocalizedString( @"..." , nil)
                       reply:^(BOOL success, NSError *error) {
         if (success) {
             // ...
         } else {
             NSLog( @"%@" , error);
         }
     }];
} else {
     NSLog( @"%@" , error);
}

虽然这些天每个人都在讨论Swift,但是作为一个开发者你更应该关注的是这些iOS 8和OS X Yosemite的新API。它们可以让你实实在在的_做_一些事。

如果你想接着探索,dive into the iOS 7.1 to 8.0 API diffs可以让你领会这些变化的重要性。当然,4000多的新API,很多只是细微的改变或者将方法改为属性,但是,它们值得拥有!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值