Swift中enum自定義型別的實現
阿新 • • 發佈:2019-01-02
在Swift中列舉型別非常強大,內建的實現可以大大減少我們手敲的程式碼量.下面碰巧就有這麼一個需求:Person類裡面有一個type屬性,其值包含2個內容,一個是name,型別為String,另一個是logo,型別也為字串,不過表現為繪文字emoji.
因為結構或類的靜態屬性都可以用點訪問符來直接訪問,所以我們可以輕易寫出如下程式碼:
class Person{
struct type{
static let big = ("big","��")
static let med = ("med","��")
static let tin = ("tin" ,"✂️")
}
var type:(String,String)?
}
let p = Person()
p.type = Person.type.big
print(p.type!.1)
貌似瀏覽器不完全支援emoji編碼,不過請你相信我那些綠色中間帶著問號的菱形在Xcode裡都是漂亮的emoji字元 ;)
這樣實現非常輕便,也是一種選擇.不過作為Swift中自帶的enum來說貌似更符合這樣的場合,於是我們嘗試寫出如下程式碼,雖然是錯誤的:
class Person{
enum type:(String,String) {
case big = ("big" ,"xxx")
case med = ("med","xxx")
case tin = ("tin","xxx")
}
}
不過編譯器該抗議了!他會告訴你enum的raw型別有誤!
這樣是不可以的哦!不過Swift給我對enum型別自定義擴充套件的一種方法,就是實現RawRepresentable協議!
為了遵守該協議你必須實現3個東東:
1.typealias RawValue = 你需要的型別
2.rawValue的計算屬性
3.初始化器init?(rawValue:)
下面我們再假想一個場景:一個記錄中包含一個type,用來說明記錄型別,與上面類似,每一個型別都有name和logo兩部分.我們可以選擇自定義一個結構來搞定:
struct Type_t{
var name:String
var logo:String
}
不過在這裡,使用元組更為簡單,以下是完整的實現:
private enum TypeName:String{
case longTerm = "LongTerm"
case targeted = "Targeted"
case allTheTime = "AllTheTime"
case critical = "Critical"
case urgent = "Urgent"
}
enum type:RawRepresentable{
case longTerm,targeted,allTheTime,critical,urgent
static let allTypes:[type] = [.longTerm,.targeted,.allTheTime,.critical,.urgent]
typealias RawValue = (name:String,logo:String)
var rawValue: (name:String, logo:String){
switch self{
case .longTerm:
return (TypeName.longTerm.rawValue,"��")
case .targeted:
return (TypeName.targeted.rawValue,"��")
case .allTheTime:
return (TypeName.allTheTime.rawValue,"��")
case .critical:
return (TypeName.critical.rawValue,"��")
case .urgent:
return (TypeName.urgent.rawValue,"⏰")
}
}
init?(rawValue: type.RawValue) {
switch rawValue.name{
case TypeName.longTerm.rawValue:
self = .longTerm
case TypeName.targeted.rawValue:
self = .targeted
case TypeName.allTheTime.rawValue:
self = .allTheTime
case TypeName.critical.rawValue:
self = .critical
case TypeName.urgent.rawValue:
self = .urgent
default:
return nil
}
}
}
於是乎如果我們想要用type來初始化UI,我們可以這麼寫:
var idx = 0
KsMain.type.allTypes.forEach {type in
if type != .longTerm{
ksTypeSeg.setTitle(type.rawValue.1, forSegmentAt: idx)
idx += 1
}
}
效果如下: