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 Using the Vending Machine Updating the Price

Dale Ribeiro
Dale Ribeiro
4,820 Points

Type 'VendingMachine' does not conform to protocol 'VendingMachineType'

Hi there,

I'm getting a complier error when I add the itemForCurrentSelection method to the VendingMachineType protocol. I have the method under the VendingMachine class. The error reads "Type 'VendingMachine does not conform to protocol 'VendingMachineType'. I've looked through my code, but can't seem to find the cause of the error.

Here is my code:

import Foundation
import UIKit

// Protocols

protocol VendingMachineType {
    var selection: [VendingSelection] { get }
    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)
    func itemForCurrentSelection(selection: VendingSelection) -> ItemType?
}

protocol ItemType {
    var price: Double { get }
    var quantity: Double { get set }
}

// Error Types

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

enum VendingMachineError: ErrorType {
    case InvalidSelection
    case OutOfStock
    case InsufficientFunds(required: Double)
}

// 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 InventoryError.InvalidResource
        }

        guard let dictionary = NSDictionary(contentsOfFile: path), let castDictionary = dictionary as? [String: AnyObject] else {
            throw InventoryError.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 InventoryError.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

    func icon() -> UIImage {
        if let image = UIImage(named: self.rawValue) {
            return image
        } else {
            return UIImage(named: "Default")!
        }
    }
}

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

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

    required init(inventory: [VendingSelection : ItemType]) {
        self.inventory = inventory
    }

    func vend(selection: VendingSelection, quantity: Double) throws {
        guard var item = inventory[selection] else {
            throw VendingMachineError.InvalidSelection
        }

        guard item.quantity > 0 else {
            throw VendingMachineError.OutOfStock
        }

        item.quantity -= quantity
        inventory.updateValue(item, forKey: selection)

        let totalPrice = item.price * quantity
        if amountDeposited >= totalPrice {
            amountDeposited -= totalPrice
        } else {
            let amountRequired = totalPrice - amountDeposited
            throw VendingMachineError.InsufficientFunds(required: amountRequired)
        }

        func itemForCurrentSelection(selection: VendingSelection) -> ItemType? {
            return inventory[selection]
        }
    }



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

2 Answers

Dale, so close. You put the itemForCurrentSelection() function inside the vend() function. Once you take it out and make it a function in VendingMachine you should be ok.

Dale Ribeiro
Dale Ribeiro
4,820 Points

Thank you! I thought I checked to make sure everything was in the right place, but I guess I overlooked that. I appreciate your help.

i am facing the same problem,but didn't get what u said can you please elaborate more ?

I have another problem in InteractiveApp m getting error Editor placeholder in source file in below snippet

extension Page {

func addChoice(title:String, story: Story) -> Page
{
    let page = Page(story: story)
    return addChoice(title, page: page)
}

in return addChoice(title, page:page ) // Error is shown in this line

Jatinder, these three lines:

        func itemForCurrentSelection(selection: VendingSelection) -> ItemType? {
            return inventory[selection]
        }

that Dale had inside the vend() function:

    func vend(selection: VendingSelection, quantity: Double) throws {
        guard var item = inventory[selection] else {
            throw VendingMachineError.InvalidSelection
        }

        guard item.quantity > 0 else {
            throw VendingMachineError.OutOfStock
        }

        item.quantity -= quantity
        inventory.updateValue(item, forKey: selection)

        let totalPrice = item.price * quantity
        if amountDeposited >= totalPrice {
            amountDeposited -= totalPrice
        } else {
            let amountRequired = totalPrice - amountDeposited
            throw VendingMachineError.InsufficientFunds(required: amountRequired)
        }

        func itemForCurrentSelection(selection: VendingSelection) -> ItemType? {  //<----
            return inventory[selection]
        }
    }

need to be taken out of the function and made a sibling, like this:

    func vend(selection: VendingSelection, quantity: Double) throws {  
        guard var item = inventory[selection] else {
            throw VendingMachineError.InvalidSelection
        }

        guard item.quantity > 0 else {
            throw VendingMachineError.OutOfStock
        }

        item.quantity -= quantity
        inventory.updateValue(item, forKey: selection)

        let totalPrice = item.price * quantity
        if amountDeposited >= totalPrice {
            amountDeposited -= totalPrice
        } else {
            let amountRequired = totalPrice - amountDeposited
            throw VendingMachineError.InsufficientFunds(required: amountRequired)
        }
    }

    func itemForCurrentSelection(selection: VendingSelection) -> ItemType? {  //<---
         return inventory[selection]
    }

Thank You ! its working now