在iPhone7發(fā)布之后,令人興奮的事情已經(jīng)塵埃落定,現(xiàn)在是時(shí)候繼續(xù)看看iOS10提供的新特性
這一周我們將要看看新的Measurement API:the Foundation framework
的新部分街州。從表面上看得湘,它看起來并不是都那么興奮:它提供了一種在計(jì)量單位間轉(zhuǎn)化的方式就像公里和英里赦拘。
然而唯欣,當(dāng)你仔細(xì)思考它蝌诡,我們花費(fèi)了極多的時(shí)間去轉(zhuǎn)化值矗晃。這可能發(fā)生在由于你有角度,但是你所用來旋轉(zhuǎn)視圖所用的API要求用弧度畦浓。可選擇的检疫,可能因?yàn)槟愕膽?yīng)用用英里計(jì)算距離讶请,但是你需要為了那些更喜歡用公里單位的用戶去轉(zhuǎn)換成公里單位。
在iOS10之前,你可能有創(chuàng)造自己的函數(shù)去轉(zhuǎn)換值乘其它的單位或者用外部庫《嵋纾現(xiàn)在蘋果已經(jīng)為你提供了有很大操控提升的API论巍,所以讓我們看看它到底能做什么。
基礎(chǔ) The Basics
This post uses Swift 3 released as part of the Xcode 8 GM build.
我們用測量模型去創(chuàng)造我們的量度用特殊的維度风响。你可以把“dimension”當(dāng)作一個有關(guān)聯(lián)并且可以相互轉(zhuǎn)換的單位組嘉汰,比如克可以轉(zhuǎn)變成千克或者也能再次返回。每一個dimension
有它自己的基礎(chǔ)單位状勤,而其它的單位就有了其相反的定義鞋怀。像容積的基本單位是公升,一毫升被定義為0.001公升持搜。
Creating Our Measurement
簡單的開始密似,假設(shè)我有一品脫的牛奶而且想知道它有多少毫升,像這樣:
let milk = Measurement(value: 1, unit: UnitVolume.imperialPints)
milk.converted(to: .liters)
// prints out 0.568261 L
這是很簡單的葫盼。一旦我們憑借單位dimension定義了我們的量度残腌,我們可以
合適的轉(zhuǎn)換成dimension的其它單位。我們自動檢查獲取milk變量的類型是Measurement<UnitVolume>贫导。它做了完美的表現(xiàn)抛猫,令我們可以合適的在這個組中轉(zhuǎn)換成其它的值。畢竟孩灯,我們?nèi)绾尾拍苻D(zhuǎn)換一公升的水成一公里闺金。
Operators
Measurement API 支持運(yùn)算符操作使用。
如果我們現(xiàn)在想要5品脫的牛奶钱反,我們可以這樣做
let fivePints = milk * 5
這個返回了新的量度掖看,因此我們可以依次轉(zhuǎn)換成其它的單位。
fivePints.converted(to: .cups)
// Prints 11.8387708333333 cup
你可以注意到當(dāng)我們在playground使用面哥,或者打印出Measurement哎壳,我們獲取了附加的單位符號。
當(dāng)然尚卫,乘法不是我們僅可用的操作符归榕。其它的,我們有相等:
let kms = Measurement(value: 5, unit: UnitLength.kilometers)
let meters = Measurement(value: 5000, unit: UnitLength.meters)
kms == meters // true
和加法:
kms + meters // 10000.0 m
Formatters
早先我提到的我們可能想去展現(xiàn)不同的單位在不同的地方吱涉。
伴隨著新的Measurement API刹泄,蘋果也提供了MeasurementFormatter
,一個添加了個在轉(zhuǎn)化成字符串之前格式化量度的能力怎爵。
默認(rèn)的特石,the measurement formatter將會使用用戶當(dāng)前的區(qū)域。我們將會手動的改變?nèi)タ纯串?dāng)我們想去輸出在兩個城市間的距離時(shí)發(fā)生什么:
let newcastleToLondon = Measurement(value: 248, unit: UnitLength.miles)
let formatter = MeasurementFormatter()
formatter.locale = Locale(identifier: "fr")
formatter.string(from: newcastleToLondon) // Prints 399,166 km
formatter.locale = Locale(identifier: "en_GB")
formatter.string(from: newcastleToLondon) // Prints 248 mi
好的鳖链!我們解決所有這些但是幾乎不需要我們自己做任何工作姆蘸。
Project
我們已經(jīng)快速看了這個API的基礎(chǔ)用法,因此讓我們對它做點(diǎn)有意思的事情。
我們將會創(chuàng)造一個風(fēng)力渦輪逞敷,伴隨著與能被滑塊所調(diào)校的風(fēng)速相比例旋轉(zhuǎn)的刀片狂秦。
這個渦輪相當(dāng)于一個uiview
的子類。它被添加到UIViewController
的view
上推捐,并伴隨著其它的基礎(chǔ)UI
元素:這個滑塊調(diào)整風(fēng)速而且label
將會用米每秒(m/s)和英里每小時(shí)(mph)來輸出風(fēng)速裂问。如果你想在playground
中完整的查看,請到github
上自由瀏覽牛柒。
我們將會集中在使用Measurement API的部分上:開始時(shí)堪簿,當(dāng)滑塊的值改變時(shí)展現(xiàn)風(fēng)速在label上:
func handleWindSpeedChange(slider: UISlider) {
let windSpeed = Measurement(value: Double(slider.value), unit: UnitSpeed.metersPerSecond)
let milesPerHour = windSpeed.converted(to: .milesPerHour)
windSpeedLabel.text = "Wind speed: \(windSpeed) (\(milesPerHour))"
}
我們的label
就像下面這樣
哇哦!我們不需要這么精確焰络,對于我們簡單的demo來說戴甩。有時(shí)我們展現(xiàn)了太多的小數(shù)以至于我們不能看見我們按照英里每小時(shí)的值。我們可以解決這個依靠我們先前簡要提到的MeasurementFormatter
闪彼。
let windSpeed = Measurement(value: Double(slider.value), unit: UnitSpeed.metersPerSecond)
let measurementFormatter: MeasurementFormatter = {
let formatter = MeasurementFormatter()
formatter.unitOptions = .providedUnit
let numberFormatter = NumberFormatter()
numberFormatter.minimumIntegerDigits = 1
numberFormatter.minimumFractionDigits = 1
numberFormatter.maximumFractionDigits = 1
formatter.numberFormatter = numberFormatter
return formatter
}()
let metersPerSecond = measurementFormatter.string(from: windSpeed)
let milesPerHour = measurementFormatter.string(from: windSpeed.converted(to: .milesPerHour))
windSpeedLabel.text = "Wind speed: \(metersPerSecond) (\(milesPerHour))"
我們創(chuàng)建我們的formatter
并且要求它使用特定的unitProvided
甜孤。這個防止the formatter忽略我們所期望的單位并且輸出測試項(xiàng)目接受器tit (test item taker) 覺得最合適的值。對于我畏腕,若沒有設(shè)置這個值缴川,這個測試項(xiàng)目接受器tit (test item taker) 將會導(dǎo)致我們的量度都按照英里每小時(shí)輸出。
The measurement formatter它自己包含了其它能夠允許我們?nèi)ジ袷交瘮?shù)值部分的量度的formatter(feels a bit like formatter-ception!)描馅。我們要求這個數(shù)字僅展現(xiàn)一個小數(shù)把夸。
最后,我們需要去用formatter
去取出string
構(gòu)成我們的m/s和英里每小時(shí)量度铭污。
像一點(diǎn)可見的反饋恋日,我們想去增加渦輪旋轉(zhuǎn)的頻率當(dāng)風(fēng)速增加時(shí)(注意,這些值僅僅是為了教育的目的嘹狞,而且完全沒有從風(fēng)里獲取能量的物理學(xué)基礎(chǔ))岂膳。
這個TurbineView
控制了動畫,但是我們需要去提供每秒刀片旋轉(zhuǎn)的角度磅网。你可能定義了一個在類里的屬性谈截,就像下面這樣:
/// The angle the blades rotate per second, in radians.
public var bladeRotationPerSecond: Double
這是OK的并且遵循了蘋果的API ,角度被弧度所提供涧偷。然而你怎么去阻止那些提供這些值時(shí)使用角度的用戶 簸喂。你可能會說:“那時(shí)應(yīng)該去讀說明文檔”。
這個參數(shù)可能有一些優(yōu)點(diǎn)燎潮,然而假使這個屬性沒有任何說明會怎樣喻鳄?它也會是一個相當(dāng)簡單的錯,對于大多數(shù)所習(xí)慣思考度數(shù)的角度的我們确封。
我們?nèi)绾问褂?code>Measurement除呵,限制僅僅接受有關(guān)角度的單位唉锌?這個
我們可以允許用戶提供任何他們覺得最舒服的角度并且在內(nèi)部轉(zhuǎn)化成任何我們需要的值。聽起來很棒竿奏,讓我們給出一段:
// TurbineView property
public var bladeRotationPerSecond: Measurement<UnitAngle> = Measurement(value: 0, unit: UnitAngle.degrees) {
didSet {
rotate()
}
}
在我們的視圖控制器我們可以決定每秒的循環(huán)用以下的代碼:
fun calculateTurbineRotation() {
// If we assume max value of slider = 1 rotation per second
let ratio = windSpeedSlider.value / windSpeedSlider.maximumValue
let fullRotation = Measurement(value: 360, unit: UnitAngle.degrees)
let rotationAnglePerSecond = fullRotation * Double(ratio)
turbine.bladeRotationPerSecond = rotationAnglePerSecond
}
我們可以用我們覺得最舒服的角度單位 --我選擇了角度。那之后我們使用基于當(dāng)前的風(fēng)速來容易的乘法操作去獲取旋轉(zhuǎn)的角度(如果滑塊值為0腥放,那速率將會是0/40=0泛啸,反之在數(shù)值范圍的最后如果滑塊的值為40那么速率將會是40/40=1)。
在這我們有了我們自己美麗的風(fēng)力渦輪秃症。
原文地址:[iOS 10 Day by Day :: Day 7 :: Measurement](https://www.shinobicontrols.com/blog/ios-10-day-by-day-day-7-measurement)
原作者:Sam Burnstone @sam_burnstone
ShinobiControls 官網(wǎng):ShinobiControls.com twitter : @shinobicontrols
譯者:simpleton king
看了戴倉薯
的daybyday文章候址,突然就想自己也翻一篇,第一次翻譯文章种柑,如果有什么翻的不好的地方岗仑,敬請指正。之前的daybyday可以到戴倉薯的文集(http://www.reibang.com/notebooks/5278512/latest) 瀏覽聚请。
順便求個幫助荠雕,大家iOS10下面canlebypruduce的resumedata有出問題么 ?導(dǎo)致不能繼續(xù)重新下載驶赏。
查了下stackoverflow炸卑,有說是apple的bug。