Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Please view the screen recording so you will know what your finished project sho
1. A `ShoppingItem` model object with properties:
1. A name of the item ("Apple").
2. A `Bool` indicating whether the item has been added to the shopping list.
3. You will need to make a computed property that initializes a `UIImage` from the name of the item.
3. You will need to make a computed property that initializes a `UIImage` from the name of the item. -done
2. **The shopping items should be persisted between launches of the application.** On the first launch of the application, use the given shopping `itemNames` to create instances of the `ShoppingItem` model, and save them to a file using `FileManager`. To help you do this, read the following substeps:
1. Use this snippet of names of images from the asset catalog to create instances of items in the `ShoppingList` model controller:

Expand Down
68 changes: 62 additions & 6 deletions Shopping List.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,25 @@
objects = {

/* Begin PBXBuildFile section */
31B4A72524945E71007F75C9 /* ShoppingItemsCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B4A72424945E71007F75C9 /* ShoppingItemsCollectionViewController.swift */; };
31B4A72724945E81007F75C9 /* ShoppingItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B4A72624945E81007F75C9 /* ShoppingItem.swift */; };
31B4A72924945F11007F75C9 /* ShoppingModelController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B4A72824945F11007F75C9 /* ShoppingModelController.swift */; };
31B4A72B2494622A007F75C9 /* ShoppingItemCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B4A72A2494622A007F75C9 /* ShoppingItemCollectionViewCell.swift */; };
31B4A72D24946F1D007F75C9 /* ShoppingItemsDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B4A72C24946F1D007F75C9 /* ShoppingItemsDetailViewController.swift */; };
4613E91221143BFC00E7FF73 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4613E91121143BFC00E7FF73 /* AppDelegate.swift */; };
4613E91421143BFC00E7FF73 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4613E91321143BFC00E7FF73 /* ViewController.swift */; };
4613E91721143BFC00E7FF73 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4613E91521143BFC00E7FF73 /* Main.storyboard */; };
4613E91921143BFD00E7FF73 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4613E91821143BFD00E7FF73 /* Assets.xcassets */; };
4613E91C21143BFD00E7FF73 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4613E91A21143BFD00E7FF73 /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
31B4A72424945E71007F75C9 /* ShoppingItemsCollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingItemsCollectionViewController.swift; sourceTree = "<group>"; };
31B4A72624945E81007F75C9 /* ShoppingItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingItem.swift; sourceTree = "<group>"; };
31B4A72824945F11007F75C9 /* ShoppingModelController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingModelController.swift; sourceTree = "<group>"; };
31B4A72A2494622A007F75C9 /* ShoppingItemCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingItemCollectionViewCell.swift; sourceTree = "<group>"; };
31B4A72C24946F1D007F75C9 /* ShoppingItemsDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingItemsDetailViewController.swift; sourceTree = "<group>"; };
4613E90E21143BFC00E7FF73 /* Shopping List.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Shopping List.app"; sourceTree = BUILT_PRODUCTS_DIR; };
4613E91121143BFC00E7FF73 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
4613E91321143BFC00E7FF73 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
4613E91621143BFC00E7FF73 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
4613E91821143BFD00E7FF73 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
4613E91B21143BFD00E7FF73 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
Expand All @@ -35,6 +43,48 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
31B4A72E2494848F007F75C9 /* Model */ = {
isa = PBXGroup;
children = (
31B4A72624945E81007F75C9 /* ShoppingItem.swift */,
);
path = Model;
sourceTree = "<group>";
};
31B4A72F249484A0007F75C9 /* Model Controller */ = {
isa = PBXGroup;
children = (
31B4A72824945F11007F75C9 /* ShoppingModelController.swift */,
);
path = "Model Controller";
sourceTree = "<group>";
};
31B4A730249484D5007F75C9 /* View Controllers */ = {
isa = PBXGroup;
children = (
31B4A72C24946F1D007F75C9 /* ShoppingItemsDetailViewController.swift */,
31B4A72424945E71007F75C9 /* ShoppingItemsCollectionViewController.swift */,
);
path = "View Controllers";
sourceTree = "<group>";
};
31B4A7312494850F007F75C9 /* Cells */ = {
isa = PBXGroup;
children = (
31B4A72A2494622A007F75C9 /* ShoppingItemCollectionViewCell.swift */,
);
path = Cells;
sourceTree = "<group>";
};
31B4A73224948557007F75C9 /* Storyboards */ = {
isa = PBXGroup;
children = (
4613E91521143BFC00E7FF73 /* Main.storyboard */,
4613E91A21143BFD00E7FF73 /* LaunchScreen.storyboard */,
);
path = Storyboards;
sourceTree = "<group>";
};
4613E90521143BFC00E7FF73 = {
isa = PBXGroup;
children = (
Expand All @@ -55,10 +105,12 @@
isa = PBXGroup;
children = (
4613E91121143BFC00E7FF73 /* AppDelegate.swift */,
4613E91321143BFC00E7FF73 /* ViewController.swift */,
4613E91521143BFC00E7FF73 /* Main.storyboard */,
31B4A73224948557007F75C9 /* Storyboards */,
31B4A730249484D5007F75C9 /* View Controllers */,
31B4A72F249484A0007F75C9 /* Model Controller */,
31B4A72E2494848F007F75C9 /* Model */,
31B4A7312494850F007F75C9 /* Cells */,
4613E91821143BFD00E7FF73 /* Assets.xcassets */,
4613E91A21143BFD00E7FF73 /* LaunchScreen.storyboard */,
4613E91D21143BFD00E7FF73 /* Info.plist */,
);
path = "Shopping List";
Expand Down Expand Up @@ -135,8 +187,12 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4613E91421143BFC00E7FF73 /* ViewController.swift in Sources */,
31B4A72D24946F1D007F75C9 /* ShoppingItemsDetailViewController.swift in Sources */,
31B4A72724945E81007F75C9 /* ShoppingItem.swift in Sources */,
31B4A72924945F11007F75C9 /* ShoppingModelController.swift in Sources */,
4613E91221143BFC00E7FF73 /* AppDelegate.swift in Sources */,
31B4A72B2494622A007F75C9 /* ShoppingItemCollectionViewCell.swift in Sources */,
31B4A72524945E71007F75C9 /* ShoppingItemsCollectionViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
11 changes: 7 additions & 4 deletions Shopping List/Assets.xcassets/Apple.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "apple.png"
"filename" : "apple.png",
"idiom" : "universal"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
},
"properties" : {
"auto-scaling" : "auto"
}
}
13 changes: 8 additions & 5 deletions Shopping List/Assets.xcassets/Grapes.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "grapes.png"
"filename" : "grapes.png",
"idiom" : "universal"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
},
"properties" : {
"auto-scaling" : "auto"
}
}
}
24 changes: 0 additions & 24 deletions Shopping List/Base.lproj/Main.storyboard

This file was deleted.

36 changes: 36 additions & 0 deletions Shopping List/Cells/ShoppingItemCollectionViewCell.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// FruitsCollectionViewCell.swift
// Shopping List
//
// Created by John McCants on 6/12/20.
// Copyright © 2020 Lambda School. All rights reserved.
//

import UIKit

class ShoppingItemCollectionViewCell: UICollectionViewCell {

@IBOutlet weak var addedLabel: UILabel!
@IBOutlet weak var itemImageView: UIImageView!
@IBOutlet weak var itemNameLabel: UILabel!


var shoppingItem : ShoppingItem? {
didSet {
updateViews()
}
}
func updateViews() {
guard let shoppingItem = shoppingItem else {return}
itemNameLabel.text = shoppingItem.itemName
itemImageView.image = shoppingItem.image

if shoppingItem.hasBeenAdded == false {
addedLabel.text = "Not added"
} else if shoppingItem.hasBeenAdded == true {
addedLabel.text = "Added"
}

}

}
102 changes: 102 additions & 0 deletions Shopping List/Model Controller/ShoppingModelController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//
// ShoppingModelController.swift
// Shopping List
//
// Created by John McCants on 6/12/20.
// Copyright © 2020 Lambda School. All rights reserved.
//

import Foundation
import UIKit

class ShoppingController {

//MARK: -Variables and Constants

let items : Bool = UserDefaults.standard.bool(forKey: .itemListInitializedKey)


let itemsNames = ["Apple", "Grapes", "Milk", "Muffin", "Soda", "Strawberries", "Popcorn"]

var shoppingItems : [ShoppingItem] = []

var shoppingListURL : URL? {
let fm = FileManager.default
guard let dir = fm.urls(for: .documentDirectory, in: .userDomainMask).first else {return nil}

return dir.appendingPathComponent("TheShoppingItemsList.plist")
}

//MARK: - Initializer

init() {
if items == false {
createInitialShoppingItems()
UserDefaults.standard.set(true, forKey: .itemListInitializedKey)
print("created \(items)")
} else {
loadFromPersistenceStore()
print("loaded \(items)")
}
}


//MARK: -Persistence Functions

func createInitialShoppingItems() {
for item in itemsNames {
let newItem = ShoppingItem(itemName: item, imageString: item)
shoppingItems.append(newItem)
}
saveToPersistenceStore()
}


func saveToPersistenceStore() {
guard let url = shoppingListURL else {return}
do {
let encoder = PropertyListEncoder()
let data = try encoder.encode(shoppingItems)
try data.write(to: url)

} catch {
print("Not able to encode the data")
}
}

func loadFromPersistenceStore() {
let fm = FileManager.default
guard let url = shoppingListURL, fm.fileExists(atPath: url.path) else {return}
do {
let data = try Data(contentsOf: url)
let decoder = PropertyListDecoder()
shoppingItems = try decoder.decode([ShoppingItem].self, from: data)

} catch {
print("Not able to decode the data")
}

}

//MARK: - Function to Calculate the number of total items added

func calculateTotalAddedItems() -> Int {
var count = 0
for item in shoppingItems {
if item.hasBeenAdded == true {
count += 1
}
}
return count
}


}

//MARK: -Extension of String Class for Key in User Defaults

extension String {
static let itemListInitializedKey = "itemListInitializedKey"

}

28 changes: 28 additions & 0 deletions Shopping List/Model/ShoppingItem.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// ShoppingItem.swift
// Shopping List
//
// Created by John McCants on 6/12/20.
// Copyright © 2020 Lambda School. All rights reserved.
//

import Foundation
import UIKit

struct ShoppingItem: Codable, Equatable {

var itemName : String
var imageString : String
var hasBeenAdded : Bool = false

var image : UIImage? {
return UIImage(named: imageString)
}

init(itemName: String, imageString: String) {
self.itemName = itemName
self.hasBeenAdded = false
self.imageString = imageString
}

}
Loading