Swift 圖表使用Foudation庫中測量類型詳解
前言
在這篇文章中,我們將建立一個條形圖,比較基督城地區(qū)自然散步的持續(xù)時間。我們將使用今年推出的新的Swift Charts
框架,并將看到如何繪制默認(rèn)不符合 Plottable
協(xié)議的類型的數(shù)據(jù),如 Measurement<UnitDuration>
。
定義圖表的數(shù)據(jù)
讓我們先定義一下要在圖表中展現(xiàn)的數(shù)據(jù)。
我們聲明了一個包含標(biāo)題和步行時間(小時)的 Walk
結(jié)構(gòu)體。我們使用 Foundation
框架中的測量類型Measurement和單位類型UnitDuration來表示每次步行的時間。
struct Walk { let title: String let duration: Measurement<UnitDuration> }
我們在數(shù)組 works
中存儲要在圖表中顯示的數(shù)據(jù)。
let walks = [ Walk( title: "Taylors Mistake to Sumner Beach Coastal Walk", duration: Measurement(value: 3.1, unit: .hours) ), Walk( title: "Bottle Lake Forest", duration: Measurement(value: 2, unit: .hours) ), Walk( title: "Old Halswell Quarry Loop", duration: Measurement(value: 0.5, unit: .hours) ), ... ]
在圖表中使用測量值
嘗試直接在圖表中使用測量值
讓我們定義一個 Chart
,并將 walks
數(shù)組作為數(shù)據(jù)參數(shù)傳遞給它。因?yàn)槲覀冎牢覀兊?code>walk 標(biāo)題是唯一的,所以我們可以直接使用它們作為 id
,但你也可以將你的數(shù)據(jù)模型改為 Identifiable
。
Chart(walks, id: \.title) { walk in BarMark( x: .value("Duration", walk.duration), y: .value("Walk", walk.title) ) }
注意,因?yàn)?Measurement<UnitDuration>
沒有遵守 Plottable
協(xié)議,我們會得到一個錯誤:「Initializer 'init(x:y:width:height:stacking:)' requires that 'Measurement' conform to 'Plottable'」
BarkMark
的初始化器期望收到一個用于 x 和 y 的 PlottableValue
參數(shù)。而且 PlottableValue
的值類型必須符合 Plottable
協(xié)議。
我們有幾個選擇來解決這個錯誤。我們可以提取測量值的 value
,它是一個 Double
類型,它是默認(rèn)符合 Plottable
的,我們可以擴(kuò)展具有 Plottable
一致性的 Measurement<UnitDuration>
,或者我們可以定義一個包裝了測量的類型并使其符合 Plottable
協(xié)議。
如果我們簡單地從測量值中提取,我們就會失去上下文,不知道用什么單位來創(chuàng)建測量值。這意味著,我們將無法正確格式化圖表的標(biāo)簽來向用戶表示單位。雖然我們可以記住我們在創(chuàng)建測量時使用了小時 hours
,但這并不理想。例如,我們可以決定以后改變數(shù)據(jù)模型,以分鐘為單位存儲持續(xù)時間,或者數(shù)據(jù)可能來自其他地方,所以手動重構(gòu)單位并不是一個完美的解決方案。
用 Plottable
的一致性來擴(kuò)展 Measurement<UnitDuration>
是可行的,但根據(jù) Swift 中關(guān)于外部類型的追溯一致性的警告 (Warning for Retroactive Conformances of External Types),如果 Swift Charts 在未來添加了這種一致性,它可能會被破壞。
我們將研究如何定義我們自己的類型來包裝 measurement
,并為我們的自定義類型添加 Plottable
的一致性。
設(shè)計一個包裝器類型
設(shè)計一個符合 Plottable 標(biāo)準(zhǔn)的包裝器類型
我們將定義一個自定義的 PlottableMeasurement
類型,并使其成為通用的,所以它可以容納任何類型的單位的測量類型。
struct PlottableMeasurement<UnitType: Unit> { var measurement: Measurement<UnitType> }
然后,我們將為 PlottableMeasurement
添加 Plottable
的一致性,其單位為 UnitDuration
類型。我們可以在將來添加對其他單位的支持。
extension PlottableMeasurement: Plottable where UnitType == UnitDuration { var primitivePlottable: Double { self.measurement.converted(to: .minutes).value } init?(primitivePlottable: Double) { self.init( measurement: Measurement( value: primitivePlottable, unit: .minutes ) ) } }
Plottable
協(xié)議有兩個要求: primitivePlottable
屬性必須返回原始類型之一,如 Double
、String
或 Date
,以及一個可失敗的初始化器,從原始 plottable
類型創(chuàng)建一個值。
我決定將測量值轉(zhuǎn)換為分鐘,但你可以選擇適合你需要的任何其他單位。只是在與原始值轉(zhuǎn)換時要使用相同的單位,這一點(diǎn)很重要。
我們現(xiàn)在可以更新我們的圖表,以使用我們的自定義 Plottable
類型。
Chart(walks, id: \.title) { walk in BarMark( x: .value( "Duration", PlottableMeasurement(measurement: walk.duration) ), y: .value("Walk", walk.title) ) }
它可以工作,但X軸上的標(biāo)簽沒有格式化,沒有向用戶顯示測量單位。我們接下來要解決這個問題。
顯示格式化標(biāo)簽
顯示帶有測量單位的格式化標(biāo)簽
為了定制X軸上的標(biāo)簽,我們將使用chartXAxis(content:)
修改器,并用傳遞給我們的值重構(gòu)x軸的標(biāo)記。
Chart(walks, id: \.title) { ... } .chartXAxis { AxisMarks { value in AxisGridLine() AxisValueLabel(""" \(value.as(PlottableMeasurement.self)! .measurement .converted(to: .hours), format: .measurement( width: .narrow, numberFormatStyle: .number.precision( .fractionLength(0)) ) ) """) } }
我們首先添加網(wǎng)格線,然后重構(gòu)給定值的標(biāo)簽。
AxisValueLabel
在初始化器中接受一個LocalizedStringKey
,它可以通過插值測量和指定其格式風(fēng)格來構(gòu)建。
我們收到的值是使用我們在 Plottable
一致性中定義的初始化器創(chuàng)建的,所以在我們的案例中,測量值是以分鐘為單位提供的。但我相信對于這個特定的圖表,使用小時會更好。我們可以很容易地將測量值轉(zhuǎn)換為插值內(nèi)部所需的單位。在這里,我們確定該值是 PlottableMeasurement
類型的,所以我們可以強(qiáng)制解包類型轉(zhuǎn)換。
我選擇了縮小的格式和小數(shù)點(diǎn)后零位數(shù)作為數(shù)字樣式,但你可以根據(jù)你的具體圖表調(diào)整這些設(shè)置。
最后的結(jié)果是在X軸上顯示以小時為單位的格式化持續(xù)時間。
你可以從我們的 GitHub repo 中獲得這篇文章中使用的項(xiàng)目的完整 示例代碼。
以上就是Swift 圖表使用Foudation庫中測量類型詳解的詳細(xì)內(nèi)容,更多關(guān)于Swift 圖表Foudation庫測量類型的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Swift中static和class關(guān)鍵字的深入講解
這篇文章主要給大家介紹了關(guān)于Swift中static和class關(guān)鍵字的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03快速排序算法在Swift編程中的幾種代碼實(shí)現(xiàn)示例
快速排序是一種不穩(wěn)定的排序,存在著優(yōu)化空間,這里我們來看快速排序算法在Swift編程中的幾種代碼實(shí)現(xiàn)示例:2016-07-07Swift利用指紋識別或面部識別為應(yīng)用添加私密保護(hù)功能
這篇文章主要給大家介紹了關(guān)于Swift利用指紋識別或面部識別為應(yīng)用添加私密保護(hù)功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用swift具有一定的參考學(xué)習(xí)價值,需要的朋友下面隨著小編來一起看看吧2018-05-05Swift實(shí)現(xiàn)Selection Sort選擇排序算法的實(shí)例講解
選擇排序是一種穩(wěn)定的排序算法,且實(shí)現(xiàn)代碼通常比冒泡排序要來的簡單,這里我們就來看一下Swift實(shí)現(xiàn)Selection Sort選擇排序的實(shí)例講解2016-07-07