本主題旨在自己學(xué)習(xí)的過(guò)程中舉出實(shí)例業(yè)務(wù)項(xiàng)目片段幫助自己提高靈性界赔,深入領(lǐng)會(huì)知識(shí)概念,記作學(xué)習(xí)拓展筆記。希望在有幸被您看到文章的同時(shí)為您帶來(lái)更多啟示设捐。
Hashable
如果我們想要將自定義結(jié)構(gòu)體、類儲(chǔ)存在 Set 中塘淑,或是將其作為 Dictionary 的鍵值 Key萝招,可以繼承 Hashable 并實(shí)現(xiàn)需要實(shí)現(xiàn)的內(nèi)容。
例如實(shí)現(xiàn):自定義多選 UI存捺,選出去過(guò)的城市槐沼,將選中的城市存儲(chǔ)在集合中。
先上Demo:
https://github.com/wiiale/AdvancedSwiftThinker/tree/master/T01-Hashable-Footprint
這里為了保持簡(jiǎn)單捌治,直接tableView.reloadData()
了岗钩,也可以添加漂亮的 UI、動(dòng)畫(huà)效果來(lái)自定義的更加明顯肖油。
實(shí)現(xiàn)代碼中主要與 Hasable 相關(guān)模塊
實(shí)現(xiàn)
// City.swift
struct City {
let name: String
let province: String
}
extension City: Hashable {
var hashValue: Int {
get {
return "\(name)\(province)".hashValue
}
}
static func ==(lhs: City, rhs: City) -> Bool {
return lhs.name == rhs.name
}
}
使用
Set<City>: City 需要實(shí)現(xiàn)Hashable
才能存儲(chǔ)在集合 Set 中兼吓。
// TableViewDataSource.swift
import UIKit
class TableViewControllerDataSource: NSObject, UITableViewDataSource {
var cities: [City]
// Set<City>
var selectedCitiesSet: Set<City>
weak var owner: TableViewController?
init(cities: [City], selectedCitiesSet: Set<City>, owner: TableViewController?) {
self.cities = cities
self.selectedCitiesSet = selectedCitiesSet
self.owner = owner
}
···
}
狀態(tài)改變時(shí),是否相等的比較避免不必要的狀態(tài)更新森枪,同時(shí)用到了實(shí)現(xiàn) Hashable 時(shí)需要實(shí)現(xiàn) Equatable 的重載==
操作符來(lái)進(jìn)行判等操作视搏。對(duì)于元素類型實(shí)現(xiàn)了 Equatable 協(xié)議的數(shù)組,也可以直接使用contains
方法會(huì)查看數(shù)組是否包含滿足給定的謂詞條件的元素等操作疲恢。
TableViewController.swift
func stateDidChanged(state: State, previousState: State?, command: Command?) {
if let command = command, case .loadCities(let handler) = command {
CityStore.shared.getCities(completionHandler: handler)
}
// 判等
if previousState == nil
|| previousState!.dataSource.cities != state.dataSource.cities
|| previousState!.dataSource.selectedCitiesSet != state.dataSource.selectedCitiesSet
{
tableView.dataSource = state.dataSource
tableView.reloadData()
}
}
注意點(diǎn)(1)-避免哈希碰撞
如果用不太穩(wěn)妥的方式實(shí)現(xiàn) hashValue 則會(huì)導(dǎo)致哈希碰撞凶朗,需要注意 hashValue 的實(shí)現(xiàn)方式。錯(cuò)誤示例:
var hashValue: Int {
get {
return name.hashValue ^ province.hashValue
}
}
City(name: "Shanghai", province: "Shanghai").hashValue // 0
City(name: "Beijing", province: "Beijing") .hashValue // 0
City(name: "Hangzhou", province: "Zhejiang").hashValue // 6535861917244346740
City(name: "Zhejiang", province: "Hangzhou").hashValue // 6535861917244346740
注意點(diǎn)(2)-繼承 NSObject 的類
NSObject 已繼承 Equatable, Hashable显拳,存在方法 isEqual棚愤,不需要重載==
運(yùn)算符。
class CityObj: NSObject { ··· }
extension CityObj {
override var hashValue: Int {
get {
return "\(name)\(province)".hashValue
}
}
override func isEqual(_ object: Any?) -> Bool {
return name == (object as? CityObj)?.name
}
}
本文 ViewController 學(xué)習(xí)并嘗試單向數(shù)據(jù)流動(dòng)的方式編寫(xiě)杂数,參考自喵神的單向數(shù)據(jù)流動(dòng)的函數(shù)式 View Controller
本冊(cè)文集中以“提出簡(jiǎn)單需求->簡(jiǎn)單實(shí)現(xiàn)需求片段”為流程宛畦,內(nèi)容只針對(duì)該知識(shí)點(diǎn)實(shí)現(xiàn)的業(yè)務(wù)實(shí)例進(jìn)行熟悉,業(yè)務(wù)也必定存在比文章方法更好的實(shí)現(xiàn)方式揍移,文章旨在分析知識(shí)點(diǎn)并加深理解次和。文集不普及基本知識(shí),不包含《Swift 進(jìn)階》書(shū)籍的詳細(xì)內(nèi)容那伐。深入學(xué)習(xí)Swift請(qǐng)大家支持正版書(shū)籍(ObjC 中國(guó))