swift4swift4.1swift4.2

Extension for String enum implementing CaseIterable Swift 4


From swift 4 the protocol CaseIterable in enums has made my life happier but I would like to know if I can create an extension for an enum Type:String,CaseIterable.

So far I can create an enum String extension like that:

extension RawRepresentable where RawValue == String{

    func toCorrectFormatSring()->String{

        var returnedString = self.rawValue

        returnedString = returnedString.uppercased()

        return returnedString

    }
}

But I have some enums that have a common function and I don't want to repeat it in all the enums. The function gives all the cases in a coma separated string and it looks like that:

enum Vehicle:String,CaseIterable{

    case car
    case truck

    static func getStringList()->String{

        let aArray = self.allCases
        var returnedString = ""

        for aItem in aArray{

            returnedString += "\(aItem.toCorrectFormatSring())\(aItem == aArray.last ? "":",")"

         }

         return returnedString

    }

}

The function I want to use wit the extension is getStringList. Is it possible?

OUPUT

[CAR,TRUCK]

Solution

  • You probably want something like this:

    extension RawRepresentable where RawValue == String {
         func toCorrectFormat() -> String {
            let returnedString = // whatever
            return returnedString
         }
    }
    extension CaseIterable where Self : RawRepresentable, Self.RawValue == String {
        static func getStringList() -> String {
            let aArray = Array(self.allCases)
            var returnedString = ""
            if let last = aArray.last {
                for aItem in aArray{
                    returnedString += "\(aItem.toCorrectFormat())\(aItem == last ? "" : ",")"
                }
            }
            return returnedString
        }
    }
    


    Now you're good to go, because the protocol extension injects the desired static function into the enum:

    enum E : String, CaseIterable {
        case howdy
        case byebye
    }
    let s = E.getStringList()
    

    Now that you know how to inject the desired functionality, you can rewrite getStringList in a much better way (the loop is silly, the comparison with last is wrong, and the string interpolation is unnecessary). I think what you're really after is something like this:

    extension CaseIterable where Self : RawRepresentable, Self.RawValue == String {
        static func getStringList() -> String {
            return Array(self.allCases)
                .map{$0.rawValue.uppercased()}
                .joined(separator:",")
        }
    }