那些開發人員應該知道但又略顯模糊的iOS 8 API(1)
無論你問任何人,他們都會告訴你:WWDC2014是他們近些時日最令人興奮的一件事,沒有硬體發布資訊,完全是關於軟體和開發人員工具的。
2014年iOS 8和OS X Yosemite的公布將會讓蘋果平台成為今年最具領導力的平台, iOS的擴充性,連續性,SpriteKit增強以及SceneKit,還有Metal,Game HealthKit,HomeKit,Local Authentication和全新的拍照架構。更不用說令人信服的Xcode和Interface Builder,改進後的iTunes Connect、TestFlight、Crash Reports以及CloudKit,當然還有Swift!
還要抱怨嗎? 蘋果已經慷慨地放寬了對新技術的保密措施,這意味著我們現在就可以討論那些閃亮的新東西。
本周,我們將探討下以下列出的功能,分享一些iOS 8中每個人都應該知道的但比較模糊的API。
從現在起,NSHipster將主要使用Swift編寫範例程式碼,當然偶爾會用Objective-C編寫。夏天結束的時候,我們希望所有的現有代碼樣本都能移植到Swift上,從而在語言間進行迅速切換。
## NSProcessInfo -isOperatingSystemAtLeastVersion ##
忘了[[UIDevice currentDevice] systemVersion] 和NSFoundationVersionNumber吧,這裡有一個新的方法可在代碼中確定當前的作業系統:NSProcessInfo -isOperatingSystemAtLeastVersion
- import Foundation
-
- let yosemite = NSOperatingSystemVersion(majorVersion: 10, minorVersion: 10, patchVersion: 0)
- NSProcessInfo().isOperatingSystemAtLeastVersion(yosemite) // false
不過請記住,為了測試進行相容性測試的時候),SomeClass.class或respondsToSelector:是檢查作業系統版本的一個更不錯的選擇。C和Swift編譯器的宏可以
用來有條件地編譯基於目標配置的源。基於target的構建配置,C或者Swift編譯的宏可以有條件地編譯原始碼)
## 新 NSFormatter 子類 ##
Foundation架構中最為嚴重缺乏就是對數量單位例如品質和長度的處理能力。iOS中8和OS X Yosemite引入了三個新的類--NSEnergyFormatter、NSMassFormatter以及NSLengthFormatter,填 補了這一缺失。這有效地使Foundation架構中NSFormatter子類的數目加倍,以前僅限於NSNumberFormatter、NSDateFormatter以及NSByteCountFormatter。
雖然這些新的格式化類是Foundation架構中的一部分,但是它們主要在HealthKit中使用。
## NSEnergyFormatter ##
NSEnergyFormatter以焦耳和卡路裡作為格式化能量單位,焦耳是運動鍛煉時用到的單位,卡路裡營養學上熱量單位。
- let energyFormatter = NSEnergyFormatter()
- energyFormatter.forFoodEnergyUse = true
-
- let joules = 10_000.0
- println(energyFormatter.stringFromJoules(joules)) // "2.39 Cal"
## NSMassFormatter ##
雖然是物質存在的基本單位,但mass在HealthKit中主要指使用者的重量。但還有一句忘記翻譯:是的,Mass和weight是不一樣的,但是在程式中,這裡不是科學課程,所以不要那麼迂腐了!)
- let massFormatter = NSMassFormatter()
- let kilograms = 60.0
- println(massFormatter.stringFromKilograms(kilograms)) // "132 lb"
## NSLengthFormatter ##
為完善新NSFormatter,還有一個子類是NSLengthFormatter。把它看成是一個MKDistanceFormatter的更有用版本,它擁有更多的單位選項和格式設定選項。
- let lengthFormatter = NSLengthFormatter()
- let meters = 5_000.0
- println(lengthFormatter.stringFromMeters(meters)) // "3.107 mi"
## CMPedometer ##
iOS 8繼續了之前的健康路線,在最近一次發布中,CMStepCounter比之前做了嚴格的改進,可及時從離散資料點進行查詢,跟蹤使用者的步數和距離,甚至計算使用者爬了多少級樓梯。
令人驚訝的是M7的晶片可以勝任這項任務。
- import CoreMotion
-
- let lengthFormatter = NSLengthFormatter()
- let pedometer = CMPedometer()
- pedometer.startPedometerUpdatesFromDate(NSDate(), withHandler: { data, error in
- if !error {
- println("Steps Taken: \(data.numberOfSteps)")
-
- let distance = data.distance.doubleValue
- println("Distance: \(lengthFormatter.stringFromMeters(distance))")
-
- let time = data.endDate.timeIntervalSinceDate(data.startDate)
- let speed = distance / time
- println("Speed: \(lengthFormatter.stringFromMeters(speed)) / s")
- }
- })
## CMAltimeter ##
在支援的裝置上,CMPedometer對floorsAscended/ floorsDescended的統計可使用CMAltimeter進行擴充,以獲得更精細的垂直距離:
- import CoreMotion
-
- let altimeter = CMAltimeter()
- if CMAltimeter.isRelativeAltitudeAvailable() {
- altimeter.startRelativeAltitudeUpdatesToQueue(NSOperationQueue.mainQueue(), withHandler: { data, error in
- if !error {
- println("Relative Altitude: \(data.relativeAltitude)")
- }
- })
- }
## CLFloor ##
CLFloor是iOS 8中的新API,CoreMotion中的新功能體現了蘋果公司的雄心勃勃的室內導航計劃。這些資訊將會在本地化導航應用中扮演重要的角色。
- 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中管理著來自使用者所有裝置中的生物資料,可以用強大的方式跟蹤並匯總使用者的多項生物資料,比如心率、熱量攝入以及有氧輸出等資料。
下面樣本展示了如何對持續一天的資料進行分組和逐個解讀:
- 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:]
- var inputStream: NSInputStream?
- var outputStream: NSOutputStream?
-
- NSStream.getStreamsToHostWithName(hostname: "nshipster.com",
- port: 5432,
- inputStream: &inputStream,
- outputStream: &outputStream)
## NSString -localizedCaseInsensitiveContainsString ##
又如下面這個是“小而堅實的修複”,一種更簡便的NSString的方法:
- let string: NSString = "Café"
- let substring: NSString = "É"
-
- string.localizedCaseInsensitiveContainsString(substring) // true
## CTRubyAnotationRef ##
如果你是一個語言學和文字排版的執著者,那麼CoreText架構新增添的部分可能會令你起身歡呼了。
......哦對。不過這個Ruby不是你印象中的Ruby,它用來在某些亞洲人的指令碼中展示字元發音的。
- @import CoreText;
-
- NSString *kanji = @"貓";
- NSString *hiragana = @"ねこ";
-
- CFStringRef furigana[kCTRubyPositionCount] =
- {(__bridge CFStringRef)hiragana, NULL, NULL, NULL};
-
- CTRubyAnnotationRef ruby =
- CTRubyAnnotationCreate(kCTRubyAlignmentAuto, kCTRubyOverhangAuto, 0.5, furigana);
不可否認,文檔沒有完全清晰地描述如何精確地將這部分合并到剩餘的CoreText繪製調用中,但是結果看起來也許會是這樣:
ねこ
貓
## 新的日曆識別符 ##
有什麼比Ruby注釋更書獃子氣的?iOS 8和OS X Yosemite中添加了新日曆標識符。此次更新讓Foundation架構更新至最新的CLDR版本。不過,在NSHipsters看來,French Republican Calendar法國共和曆)依然有自己的亮點。
新日曆識別符:
- NSCalendarIdentifierCoptic: 又名亞曆山大曆,之前被Coptic Orthodox Church使用。
- NSCalendarIdentifierEthiopicAmeteMihret:埃塞俄比亞日曆,Amete Mihret公元8世紀左右)
- NSCalendarIdentifierEthiopicAmeteAlem:埃塞俄比亞日曆,Amete Alem公元前5493前後)
- NSCalendarIdentifierIslamicTabular:一個簡單的伊斯蘭曆法表格,在公元622年7月15日星期四的天文時代使用。
- NSCalendarIdentifierIslamicUmmAlQura:在沙地阿拉伯使用的伊斯蘭烏姆Qura日曆。根據天文計算,而不是表格的行為。