I don't recieve the runtime error anymore, however the item does not save into the shopping list
//
// AppDelegate.swift
// Shopping List
//
// Created by Deepak Prasad on 1/10/22.
//
import UIKit
extension Notification.Name { // Declaration is only valid at file scope
public static let kShoppingChanged = Notification.Name("ShoppingListDidChangeNotification")
}
class ShoppingListViewController: UITableViewController {
let CellIdentifier = "Cell Identifier"
var items = [Item]() {
didSet {
buildShoppingList()
}
}
var shoppingList = [Item]() {
didSet {
tableView.reloadData()
}
}
// MARK: -
// MARK: View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
// Set Title
title = "Shopping List"
// Load Items
loadItems()
// Register Class
tableView.register(UITableViewCell.classForCoder(), forCellReuseIdentifier: CellIdentifier)
// Add Observer
NotificationCenter.default.addObserver(self, selector: #selector(updateShoppingList), name: .kShoppingChanged, object: nil) //'default' label can only appear inside a 'switch' statement
}
// MARK: -
// MARK: Table View Data Source Methods
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return shoppingList.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Dequeue Reusable Cell
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier, for: indexPath as IndexPath)
// Fetch Item
let item = shoppingList[indexPath.row]
// Configure Table View Cell
cell.textLabel?.text = item.name
return cell
}
// MARK: -
// MARK: Notification Handling
@objc func updateShoppingList(notification: NSNotification) {
loadItems()
}
// MARK: -
// MARK: Helper Methods
func buildShoppingList() {
shoppingList = items.filter({ (item) -> Bool in
return item.inShoppingList
})
}
private func loadItems() {
if let filePath = pathForItems(), FileManager.default.fileExists(atPath: filePath) {
if let archivedItems = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as? [Item] {
items = archivedItems
}
}
}
private func pathForItems() -> String? {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
if let documents = paths.first, let documentsURL = NSURL(string: documents) {
return documentsURL.appendingPathComponent("items")?.path
}
return nil
}
}
Post
Replies
Boosts
Views
Activity
Perfect that worked great thank you!
Now when I click save I get the same error appears "[Shopping_List.AddItemViewController save:]: unrecognized selector sent to instance ..."
//
// AppDelegate.swift
// Shopping List
//
// Created by Deepak Prasad on 1/10/22.
//
import UIKit
protocol AddItemViewControllerDelegate {
func controller(controller: AddItemViewController, didSaveItemWithName name: String, andPrice price: Float)
}
class AddItemViewController: UIViewController {
@IBOutlet var nameTextField: UITextField!
@IBOutlet var priceTextField: UITextField!
var delegate: AddItemViewControllerDelegate?
// MARK: -
// MARK: View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: -
// MARK: Actions
@IBAction func cancel(sender: UIBarButtonItem) {
dismiss(animated: true, completion: nil)
}
@IBAction func save(sender: UIBarButtonItem) {
if let name = nameTextField.text, let priceAsString = priceTextField.text, let price = Float(priceAsString) {
// Notify Delegate
delegate?.controller(controller: self, didSaveItemWithName: name, andPrice: price)
// Dismiss View Controller
dismiss(animated: true, completion: nil)
}
}
}
Thank you for the reply, I have added this line but now I am getting this error, Type 'UIPushBehavior' has no member 'addItem(sender:)'
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(UIPushBehavior.addItem(sender:)))
Thank you for all the help everyone!
Thanks for the reply, I have used google and fixed all the other errors due to the API being deprecated. This is the last error I have that I wasn't able to fix.
I have added this code and i'm getting these errors now
extension Notification.Name { // Declaration is only valid at file scope
public static let kShoppingChanged = Notification.Name("ShoppingListDidChangeNotification")
}
NotificationCenter.default.addObserver(self, #selector: Notification(updateShoppingList(_:)), name: .kShoppingChanged, object: nil) //'default' label can only appear inside a 'switch' statement
so I moved the declaration to the top and now it looks like this
NotificationCenter.default.addObserver(self, selector: #selector(updateShoppingList(_:)), name: .kShoppingChanged, object: nil)
and the error is Cannot find 'updateShoppingList' in scope
this is the updateShoppingList function:
func updateShoppingList(notification: NSNotification) {
loadItems()
}
Thank you so much!! that fixed those errors. I am now getting a caution that says: "archiveRootObject(_:toFile:)' was deprecated in iOS 12.0: Use +archivedDataWithRootObject:requiringSecureCoding:error: and -writeToURL:options:error: instead"
Are you able to help with this?
// Write to File
if NSKeyedArchiver.archiveRootObject(items, toFile: itemsPath) {
ud.set(true, forKey: "UserDefaultsSeedItems")
}
}
Sorry I am still new so some of the questions are hard for me to understand, that worked perfectly thank you so much for all the help!!!!
Thanks for the help, im getting a few more errors now which I put comments next to so you can see
let ud = UserDefaults.standard
if !ud.bool(forKey: "UserDefaultsSeedItems") {
if let filePath = Bundle.main.path(forResource: "seed", ofType: "plist"), let seedItems = NSArray(contentsOfFile: filePath) {
print("seedItems", seedItems)
// Items
var items = [Item]()
// Create List of Items
for seedItem in seedItems {
let name = seedItem.name //ERROR Value of type 'Any' has no member 'name'
let price = seedItem.price //ERROR Value of type 'Any' has no member 'price'
print("\(name) - \(price)")
// Create Item
let item = Item(name: name, price: price)
// Add Item
items.append(item)
}
}
print(items) //ERROR Cannot find 'items' in scope
if let itemsPath = pathForItems() {
// Write to File
if NSKeyedArchiver.archiveRootObject(items, toFile: itemsPath) { //ERROR Cannot find 'items' in scope
ud.set(true, forKey: "UserDefaultsSeedItems")
}
}
}
}
}
Thank you for the reply! I am following this tutorial here if this helps you understand my problem more, https://code.tutsplus.com/tutorials/ios-from-scratch-with-swift-building-a-shopping-list-application-1--cms-25515
It has grocery items in the array
Here is the code for the Item class, let me know if you need other code. Sorry I am a beginner so I'm unsure what is needed.
import UIKit
class Item: NSObject, NSCoding {
func encode(with coder: NSCoder) {
coder.encode(uuid, forKey: "uuid")
coder.encode(name, forKey: "name")
coder.encode(price, forKey: "price")
coder.encode(inShoppingList, forKey: "inShoppingList")
}
var uuid: String = NSUUID().uuidString
var name: String = ""
var price: Float = 0.0
var inShoppingList = false
// MARK: -
// MARK: Initialization
init(name: String, price: Float) {
super.init()
self.name = name
self.price = price
}
// MARK: -
// MARK: NSCoding Protocol
required init?(coder decoder: NSCoder) {
super.init()
if let archivedUuid = decoder.decodeObject(forKey:)("uuid") as? String {
uuid = archivedUuid
}
if let archivedName = decoder.decodeObject(forKey:)("name") as? String {
name = archivedName
}
price = decoder.decodeFloat(forKey:)("price")
inShoppingList = decoder.decodeBool(forKey:)("inShoppingList")
}
func encodeWithCoder(coder: NSCoder) {
coder.encode(uuid, forKey: "uuid")
coder.encode(name, forKey: "name")
coder.encode(price, forKey: "price")
coder.encode(inShoppingList, forKey: "inShoppingList")
}
}