1. 程式人生 > >Swift中enum自定義型別的實現

Swift中enum自定義型別的實現

在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
            }
        }

效果如下:

這裡寫圖片描述