Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS Build a Vending Machine App in Swift 2.0 Loading Data From a Resource Finishing Touches

Alistair Cooper
PLUS
Alistair Cooper
Courses Plus Student 7,020 Points

! Use of undeclared type 'VendingSelection' compiler error

Hi there,

Next to all the uses of [VendingSelection] in the VendingMachineType protocol I'm getting a "! Use of undeclared type 'VendingSelection'" compiler error. Should the // Concrete Types section with the enum VendingSelection declaration go above the VendingMachineType protocol?

Thanks for any ideas!

    protocol VendingMachineType {
        var selection: [VendingSelection] { get }  // get = it's a read only property
        var inventory: [VendingSelection: ItemType] { get set }
        var amountDeposited: Double { get set }

        init(inventory: [VendingSelection: ItemType])

        func vend(selection: VendingSelection, quantity: Double) throws
        func deposit(amount: Double)
    }
Martin Wildfeuer
Martin Wildfeuer
Courses Plus Student 11,071 Points

VendingSelection needs to be defined somewhere in your code, but it seems to be missing. Can you post the definition of VendingSelection as well, please? It might shed some light on this, thanks :)

Alistair Cooper
Alistair Cooper
Courses Plus Student 7,020 Points

Hi Martin,

Sorry, here's the whole code. I have a feeling it's painfully simple :^i Thanks for taking a look!

    import Foundation

    // Protocols

    protocol VendingMachineType {
        var selection: [VendingSelection] { get }  // get = it's a read only property
        var inventory: [VendingSelection: ItemType] { get set }
        var amountDeposited: Double { get set }

        init(inventory: [VendingSelection: ItemType])

        func vend(selection: VendingSelection, quantity: Double) throws
        func deposit(amount: Double)
    }

    protocol ItemType {
        var price: Double { get }
        var quantity: Double { get set }   // the quantity can change so it's get set
    }

    // Error Types

    enum InventoryType: ErrorType {
        case InvalidResource
        case ConversionError
        case InvalidKey
    }

    // Helper Classes

    class PlistConverter {
        class func dictionaryFromFile(resource: String, ofType type: String) throws -> [String : AnyObject] {

            guard let path = NSBundle.mainBundle().pathForResource(resource, ofType: type) else {
                throw InventoryType.InvalidResource
            } // .mainBundle() coresponds to app bundle for this app.

            guard let dictionary = NSDictionary(contentsOfFile: path), let castDictionary = dictionary as? [String: AnyObject] else {
                throw InventoryType.ConversionError
            }

            return castDictionary
        }

    class InventoryUnarchiver {
        class func vendingInventoryFromDictionary(dictionary: [String: AnyObject]) throws -> [VendingSelection: ItemType] {

            var inventory: [VendingSelection: ItemType] = [:]

            for (key, value) in dictionary {
                if let itemDict = value as? [String: Double], let price = itemDict["price"], let quantity = itemDict["quantity"] {

                    let item = VendingItem(price: price, quantity: quantity)

                    guard let key = VendingSelection(rawValue: key) else {
                        throw InventoryType.InvalidKey

                    }

                    inventory.updateValue(item, forKey: key)
                }
            }
            return inventory
        }

    }

    // Concrete Types

    enum VendingSelection: String {
        case Soda
        case DietSoda
        case Chips
        case Cookie
        case Sandwich
        case Wrap
        case CandyBar
        case PopTart
        case Water
        case FruitJuice
        case SportsDrink
        case Gum
    }

    struct VendingItem: ItemType {
        let price: Double
        var quantity: Double
    }

    // VendingMachine is better as a class. Classes are good at modeling state
    class VendingMachine: VendingMachineType {
        let selection: [VendingSelection] = [.Soda, .DietSoda, .Chips, .Cookie, .Sandwich, .Wrap, .CandyBar, .PopTart, .Water, .FruitJuice, .SportsDrink, .Gum]
        var inventory: [VendingSelection : ItemType]
        var amountDeposited: Double = 10.0   // setting an initial value to give user money to play with

        // because it's required in the protocol we need the required keyword
        required init(inventory: [VendingSelection : ItemType]) {
            self.inventory = inventory
        }

        func vend(selection: VendingSelection, quantity: Double) throws {
            // add code
        }

        func deposit(amount: Double) {
            // add code
        }
    }

2 Answers

Martin Wildfeuer
PLUS
Martin Wildfeuer
Courses Plus Student 11,071 Points

Hey there, thanks for posting your code! As far as I can tell the class PlistConverter misses a closing bracket. That is

            ...
            return inventory
        }  
    }  
} // This one is missing

Let me know if that solves your problem :)

Alistair Cooper
PLUS
Alistair Cooper
Courses Plus Student 7,020 Points

lol! oh dear. Yes that's it. Lesson learned. Thanks Martin! -A