Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Try to build a vending mechine IOS app, but there are some error when debug it. Someone can help to fix it? ViewController.Swift code import

Try to build a vending mechine IOS app, but there are some error when debug it. Someone can help to fix it?

ViewController.Swift code

import UIKit

fileprivate let reuseIdentifier = "vendingItem"

fileprivate let screenWidth = UIScreen.main.bounds.width

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {

@IBOutlet weak var collectionView: UICollectionView!

@IBOutlet weak var totalLabel: UILabel!

@IBOutlet weak var balanceLabel: UILabel!

@IBOutlet weak var quantityLabel: UILabel!

@IBOutlet weak var priceLabel: UILabel!

@IBOutlet weak var quantityStepper: UIStepper!

let vendingMachine: VendingMachine

var currentSelection: VendingSelection?

required init?(coder aDecoder: NSCoder) {

do{

let dictionary = try PlistConverter.dictionary(fromFile: "VendInventory", ofType: "Plist")

let inventory = try InventoryUnarchiver.vendingInventory(fromDictionary: dictionary)

self.vendingMachine = VendingMachine(inventory: inventory)

} catch let error{

fatalError("\(error)")

}

super.init(coder: aDecoder)

}

override func viewDidLoad() {

super.viewDidLoad()

// Do any additional setup after loading the view, typically from a nib.

setupCollectionViewCells()

updateDisplayWith(balance: vendingMachine.amountDeposited, totalPrice: 0, itemPrice: 0, itemQuantity: 1)

}

override func didReceiveMemoryWarning() {

super.didReceiveMemoryWarning()

// Dispose of any resources that can be recreated.

}

// MARK: - Setup

func setupCollectionViewCells() {

let layout = UICollectionViewFlowLayout()

layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 20, right: 0)

let padding: CGFloat = 10

let itemWidth = screenWidth/3 - padding

let itemHeight = screenWidth/3 - padding

layout.itemSize = CGSize(width: itemWidth, height: itemHeight)

layout.minimumLineSpacing = 10

layout.minimumInteritemSpacing = 10

collectionView.collectionViewLayout = layout

}

// mark vendingmachine

@IBAction func Purchase(_ sender: Any) {

if let currentSelection = currentSelection{

do {

try vendingMachine.vend(selection: currentSelection, quantity: Int, quantityStepper.value)

updateDisplayWith(balance: vendingMachine.amountDeposited, totalPrice: 0.0, itemPrice: 0,itemQuantity: 1)

}catch{

//fix: error handing code

}

if let indexPath = collectionView.indexPathsForSelectedItems?.first{

collectionView.deselectItem(at: <#T##IndexPath#>, animated: true)

updateCell(having: <#T##IndexPath#>, selected: false)

}

} else {

// Fix: alert user to no selection

}

}

func updateDisplayWith(balance: Double? = nil, totalPrice: Double? = nil, itemPrice:Double? = nil , itemQuantity: Int? = nil ){

if let balanceValue = balance{

balanceLabel.text = "$\(balanceValue)"

}

if let totalValue = balance{

totalLabel.text = "$\(totalValue)"

}

if let priceValue = itemPrice{

priceLabel.text = "$\(priceValue)"

}

if let quantityValue = itemQuantity{

quantityLabel.text = "\(quantityValue)"

}

}

func updateTotalPrice(for item: VendingItem){

let totalPrice = item.price * quantityStepper.value

updateDisplayWith(totalPrice: totalPrice)

}

@IBAction func updateQuantity(_ sender: UIStepper) {

let quantity = Int(quantityStepper.value)

updateDisplayWith(itemQuantity: quantity)

if let cuerrentSelection = currentSelection, let item = vendingMachine.item(forSelection: currentSelection!){

updateTotalPrice(for: item)

}

}

// MARK: UICollectionViewDataSource

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

return vendingMachine.selection.count

}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as? VendingItemCell else { fatalError() }

let item = vendingMachine.selection[indexPath.row]

cell.iconView.image = item.icon()

return cell

}

// MARK: - UICollectionViewDelegate

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

updateCell(having: indexPath, selected: true)

quantityStepper.value = 1

updateDisplayWith(totalPrice: 0, itemQuantity: 1)

currentSelection = vendingMachine.selection[indexPath.row]

if let currentSelection = currentSelection, let item = vendingMachine.item(forSelection: currentSelection){

let totalPrice = item.price * quantityStepper.value

updateDisplayWith(totalPrice: totalPrice, itemPrice: item.price)

}

}

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {

updateCell(having: indexPath, selected: false)

}

func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {

updateCell(having: indexPath, selected: true)

}

func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) {

updateCell(having: indexPath, selected: false)

}

func updateCell(having indexPath: IndexPath, selected: Bool) {

let selectedBackgroundColor = UIColor(red: 41/255.0, green: 211/255.0, blue: 241/255.0, alpha: 1.0)

let defaultBackgroundColor = UIColor(red: 27/255.0, green: 32/255.0, blue: 36/255.0, alpha: 1.0)

if let cell = collectionView.cellForItem(at: indexPath) {

cell.contentView.backgroundColor = selected ? selectedBackgroundColor : defaultBackgroundColor

}

}

}

VendingMechine.Swift code

import Foundation

import UIKit

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 #imageLiteral(resourceName: "default")

}

}

}

protocol VendingItem {

var price: Double {get}

var quantity: Int {get}

}

protocol VendingMachine{

var selection: [VendingSelection] { get }

var inventory: [VendingSelection: VendingItem] {get set}

var amountDeposited: Double {get set}

init(inventory: [VendingSelection: VendingItem])

func vend(selection: VendingSelection, quantity: Int ) throws

func deposit(_amount: Double)

func item(forSelection selecion: VendingSelection) -> VendingItem?

}

struct Item:VendingItem {

let price: Double

var quantity: Int

}

enum InventoryError: Error {

case invalidResource

case conversionFailure

case invalidSelection

}

class PlistConverter{

static func dictionary(fromFile name: String, ofType type:String)throws -> [String:AnyObject]{

guard let path = Bundle.main.path(forResource: name,ofType:type)else{

throw InventoryError.invalidResource

}

guard let dictionary = NSDictionary(contentFile:path) as? [String:AnyObject] else {

throw InventoryError.conversionFailure

}

return dictionary

}

}

class InventoryUnarchiver{

static func vendingInventory(fromDictionary dictionary: [String:AnyObject]) -> [VendingSelection: VendingItem]{

var inventory:[VendingSelection: VendingItem] = [:]

for (key,value) in dictionary{

if let itemDictionary = value as? [String:Any], let price = itemDictionary["price"] as? Double, let quantity = itemDictionary["quantity"] as? Int {

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

guard let selection = VendingSelection(rawValue:key) else{

throw InventoryError.invalidResource

}

inventory.updateValue(item, forKey: selection)

}

return inventory

}

}

enum VendingMachineError: Error {

case invalidSelection

case outOfStock

case insufficientFunds(require: Double)

}

class FoodVendingMachine: VendingMachine{

let selection: [VendingSelection] = [.soda,.dietSoda,.chips,.cookie,.wrap,.sandwich,.candyBar,.popTart,.water,.fruitJuice,.sportsDrink,.gum]

var inventory: [VendingSelection : VendingItem]

var amountDeposited: Double = 10.0

required init(inventory: [VendingSelection : VendingItem]) {

self.inventory = inventory

}

func vend(selection: VendingSelection,quantity: Int) throws {

guard var item = inventory[selection]else{

throw VendingMachineError.invalidSelection

}

guard item.quantity >= quantity else{

throw VendingMachineError.outOfStock

}

let totalPrice = item.price * Double (quantity)

if amountDeposited >= totalPrice{

amountDeposited -= totalPrice

item.quantity -= quantity

inventory.updateValue(item, forKey: selection)

}else{

let amountRequired = totalPrice - amountDeposited

throw VendingMachineError.insufficientFunds(require: amountRequired)

}

}

func deposit(_amount: Double) {

<#code#>

}

func item(forSelection selecion: VendingSelection) -> VendingItem? {

return inventory[selection]

}

}

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image_2

Step: 3

blur-text-image_3

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Students also viewed these Databases questions