Dictionary Wrapper for Custom Types

I'm trying to implement a dictionary wrapper that uses a custom value type like so:

import Foundation

enum Color {
    case Red
    case Green
    case Blue
}

struct IntColorDict {
    private var dict: [Int: Color]

    init(_ dict: [Int: Color]) {
        self.dict = dict
    }
}

extension IntColorDict: SequenceType {
    typealias Generator = IntColorDictGenerator

    func generate() -> Generator {
        return IntColorDictGenerator(self)
    }
}

struct IntColorDictGenerator: GeneratorType {
    typealias Element = (Int, Color)

    var generator: DictionaryGenerator<Int, Color>

    init(_ colorDict: IntColorDict) {
        generator = colorDict.dict.generate()
    }

    mutating func next() -> Element? {
        return generator.next()
    }
}


If I now do

let c: [Int: Color] = [1: .Red, 2: .Green, 3: .Blue]
for (k, v) in IntColorDict(c) {
    print("k: \(k), v: \(v)")
}

the compiler fails with the error

fatal error: value failed to bridge from Swift type to a Objective-C type


The problem obviously is the Color type, since when I replace all occurrences of Color with another Int (i.e. var dict: [Int: Int]) everything works fine. How can I fix this?


Or maybe there is even a completely different solution? What I actually need is a dictionary with a certain value type that has some extended functionality compared to default Swift Dictionaries (but only for that specific value type!). I cannot solve this problem by extending the Dictionary definition as extensions are not supported for data types with "where" constraints, so the wrapper above seems like a natural solution.

Answered by DTS Engineer in 72600022

How are you testing this? I copied your code into a new test project (created from the OS X > Command Line Tool template) and it worked just fine.

k: 2, v: Green
k: 3, v: Blue
k: 1, v: Red
Program ended with exit code: 0

This is with Xcode 7.0 on OS X 10.10.5.

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
Accepted Answer

How are you testing this? I copied your code into a new test project (created from the OS X > Command Line Tool template) and it worked just fine.

k: 2, v: Green
k: 3, v: Blue
k: 1, v: Red
Program ended with exit code: 0

This is with Xcode 7.0 on OS X 10.10.5.

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

You're right! I tend to test such small things in Playgrounds and am always surprised to see completely different results when the same code is run as an actual app. I guess I really need to change my habits. Thank you!

Wow, this just saved me hours of hair pulling (after hours of hair pulling)! For me, I was getting the same error testing this in a playground:


struct BlockCollection : SequenceType {
    private static var idx=0
    var blockDict:[Int:Int->()]=[:]
    mutating func addBlock(b:Int->()) -> Int {
        blockDict[BlockCollection.idx]=b
        BlockCollection.idx+=1
        return BlockCollection.idx-1
    }
    mutating func dropBlock(k:Int) {
        blockDict.removeValueForKey(k)
    }
    func generate() -> AnyGenerator<Int->()> {
        var dgen=blockDict.generate()
        return anyGenerator {
            return dgen.next()?.1
        }
    }
}


func blockDictTest() {
    var bc=BlockCollection()
    bc.addBlock {print($0+2)}
    bc.addBlock {print($0*2)}
    bc.addBlock {print($0%2)}
    for b in bc {
        b(7)
    }
}


but it works fine in an actual project.

Dictionary Wrapper for Custom Types
 
 
Q