Question
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
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started