Updating CoreData value with UIStepper effect per cell - swift

Hopefully someone can help me... I am passing an item from the web into coredata, I am passing the values with a click of a button.. as soon as the button gets pressed then number of items and cost are immediately passed on to Coredata attributes. e.i price: 30.00, itemQuantity 1 (all well and good here per cell)
these items are then displayed on a cellForRowAt along side with a UIStepper to change the values of the item per cell. take a look:
var itemsArray: [ItemModel] = []
let currentPrice = itemsArray[indexPath.row].price
let currentQty = itemsArray[indexPath.row].itemQuantity
let totalQty = currentQty + Int16(sender.value)
let totalPrice = Double(currentPrice) * sender.value
itemsArray[indexPath.row].setValue(totalPrice, forKey: "price")
itemsArray[indexPath.row].setValue(totalQty, forKey: "itemQuantity")
let context = CoreDataManager.shared.persistentContainer.viewContext
do {
try context.save()
} catch {
print("Failed to save main context: \(error)")
}
Theoretically this would work just find.. and it does! if I don't use Coredata and just plain UI...
But since I am using CoreData... here is what's actually happening (I bet you can already tell): I am re-using the itemsArray which initial value per item is already 30.00, so when I multiply the price with a the new sender.value now equals to 2 i'll get 60.00 which is great but NOW the price in coredata is 60 and new itemQuantity is 2 so when i click the + on the Stepper it all gets multiplied now three times the updated value, so it all gets messed up... because Im updating the values with the same previously-updated-values.. so.. yea.. I'm stuck : / How can I make this right?

Related

Swift: Remove only the first object from the NSUserDefaults

I create the Bus Ticket Booking App. so I have Dictionary with the Array in it. In which the recent Route search result is save into the NSUserDefaults. Now I want to print that result into the one TableView.
Now in that TableView I only want to show the last 10 That's all I can do perfectly but the problem is every time the result is save in to the UserDefaults so the size of the UserDefaults is increase so I just want to remove the Defaults So every time my array element remove Repeat While loop is call the number of the element in the UserDefaults (If I i have 30 element into it it run 20 times so like). This is what i'm doing for Dictionary.
var arrSearch = [[String:Any]]()
var searchBusVC:SearchBusViewController?
override func viewDidLoad() {
super.viewDidLoad()
if let arr = UserDefault["Search"] {
arrSearch.append(contentsOf: (arr as! [[String:Any]]))
repeat{
arrSearch.removeFirst()
}while (arrSearch.count > 10)
arrSearch.reverse()
}
self.tblSearch.reloadData()
}
So I want to remove the same from the UserDefaults Is it possible? This is my Table View Image.
If you are saving [[String: Any]] in UserDefaults means its like a normal way to remove objects from array. Once you done removing objects from array then save it to UserDefaults.
var recentRecords:[[String: Any]]? {
get {
return UserDefaults.standard.array(forKey:"recentRecord")
}
set {
var trimmed: [[String: Any]] = newValue
// Trim last 10 objects from array
if newValue.count >= 10 {
trimmed = newValue.suffix(10)
}
UserDefaults.standard.set(trimmed, forKey: "recentRecord")
}
}

Swift - Why is my application finding nil in this scenario

I have an tableView which loads cells from a xib file. The cells contain 2 labels, 1 shows the quantity and the second shows the price. The quantity is pulled from a static model and works just fine, and the price is pulled from a model which is populated from the result of a URLSession. Below is my cellForRowAt function which works fine in this scenario:
if indexPath.section == 0 {
let item: BasketModel = cellItems[indexPath.row] as! BasketModel
let ordersCell = Bundle.main.loadNibNamed("OrderTableViewCell", owner: self, options: nil)?.first as! OrderTableViewCell
ordersCell.priceLabel.text = item.price
ordersCell.quantityLabel.text = String(basketStruct.getQty(id: item.id!))
return ordersCell
}
My cell shows as follows Qty: 3 Price: 0.70
Now, the problem I have is, when i alter the line above where I set the price label to the following:
ordersCell.priceLabel.text = String(basketStruct.getQty(id: item.id!) * Int(item.price!)!)
I get the error:
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
What I want, is the qty to be multiplied by the price. However, when I try to use item.price for anything I have to force unwrap it and then I get my error.
How would I go about this ?
It is not that item.price is nil, but Int(item.price!) is nil.
From your question, you said that the price displayed is 0.70, so I suppose item.price must contain the string "0.70".
Well, 0.70 is not a valid Int, so when you try to parse it as an Int, it evaluates to nil.
I think you meant Double(item.price!)!.
As a good practise, you should always check for invalid number strings:
if let price = Double(item.price!) {
// ...
} else {
print("Invalid price: \(item.price!)")
}

Accessing Firebase Data inside unique AutoID

This is my first question and I'm still learning Swift/Xcode/Firebase, so I appreciate your patience. I've been stalking StackOverflow and have found a lot of answers to help with various things, but nothing that makes sense for the problem I've been struggling with for 2 days.
I am writing a program that will save a date picked on a previous viewcontroller and a set of user-entered floats from text fields to a Firebase database, and append each data set as a separate entry instead of overwriting the previous data. Using the first block of code below, I've got this problem solved except I can't find a way to do it without using AutoID. This leaves me with a setup like this in Firebase, but with multiple categories and "optionSelected" sections in each category:
program-name
Category 1
optionSelected
L1cggMnqFqaJf1a7UOv
Date: "21-12-2017"
Variable 1 Float: "12345"
Variable 2 Float: "26.51"
L1ciVpLq1yXm5khimQC
Date: "30-12-2017"
Variable 1 Float: "23456"
Variable 2 Float: "35.88"
Code used to save:
func newWithNewVars() {
let myDatabase = Database.database().reference().child("Category 1").child(optionSelected)
let variable1 = textField1.text
let variable2 = textField2.text
let variable1Float = (textField1.text! as NSString).floatValue
let variable2Float = (textField2.text! as NSString).floatValue
let writeArray = ["Date": textPassedOverDate, "Variable 1 Float": variable1Float, "Variable 2 Float": variable2Float]
myDatabase.childByAutoId().setValue(gasArray) {
(error, reference) in
if error != nil {
print(error!)
}
else {
print("Message saved successfully!")
}
}
}
The problem comes with recalling data. Since the AutoID is unique, I can't figure out how to access the data deeper inside for calculations. Specifically, I want to be able to make a new entry, press the save data button, and have it find the most recent entry in the "optionSelected" section so it can do calculations like subtract the older variable 1 from the new variable 1 and such.
Given the above description, layout, and code used above, what code structure would allow me to find the most recent date and access the data inside the AutoID sections for a specific category and "optionSelected"?
Thank you for your help.
The issue you're having is that you're trying to dig deeper but can't as you don't have a hold of that id. You'll want to use the .childAdded in your reference observation when you want to get inside of a list in your JSON tree when you don't have a hold of that id to get inside - this will be called as many times as there are values inside of Category 1 tree:
let reference = Database.database().reference()
reference.child("Category 1").child("optionSelected").observe(.childAdded, with: { (snapshot) in
let uniqueKey = snapshot.key // IF YOU WANT ACCESS TO THAT UNIQUE ID
print(uniqueKey)
guard let dictionary = snapshot.value as? [String: AnyObject] else { return }
let date = dictionary["date"] as? String
let variableOne = dictionary["Variable 1 Float"] as? Float
let variableOne = dictionary["Variable 2 Float"] as? Float
}, withCancel: nil)
You may also want to avoid using spaces in your database keys to avoid any problems in the near future. I'd stick with the common lowercased underscore practice e.g. "category_1" or "variable_2_float"

why realm database property value do not change?

As above pic, the index is increased one with sequence. when I delete one of index (except for 0), like 3, I hope all index will still in the sequence through 0~5, which means 1 & 2 keep unchanged, 4 decrease to 3, 5->4, 6->5. below is my code:
let defaultRealm = try! Realm()
let currentRealm = self.defaultRealm.objects(CurrentRealmObject.self)
let remainedItems = currentRealm.filter("index > \(indexPath.row)")
for item in remainedItems {
var realmIndex = item.index
print("before \(realmIndex)")
try! self.defaultRealm.write {
realmIndex -= 1
print("update \(realmIndex)")
}
}
After I deleted index 3, the realm database become following:
and print in console is:
before 6
update 5
before 4
update 3
before 5
update 4
see? values are actually updated, but realm database remains the index unchanged, and its sequence become confused(I'd also like to know why --! and how to keep them in the same sequence).
Thanks for your help!
var realmIndex = item.index means that item.index was copied to realmIndex. No matter how many copied values ​​you change, it does not affect the original object. To update the value of Realm, assign it again or directly manipulate the property rather than the copied value.
Assign it again
try! self.defaultRealm.write {
realmIndex -= 1
item.index = realmIndex
}
directly manipulate the property
try! self.defaultRealm.write {
item.index -= 1
}
For the sequence, As same as other databases, Realm does not keep order. If you would like to get results in sequence, you need to explicitly sort using the sorted() method. Or, use Realm's List<T> instead. List<T> keeps the orders.

Performing functions with valueForKey

I am trying to get my app to perform functions. I have two attributes per item (quantity and price) that I want to multiply together and then total for all the didSelectRow items on the list. There is two sections on my tableView. Section 0 is regular and moved to section 1 with didSelectRow. (I only explain this because it comes into play further down)
My code so far is...
`func cartTotalFunc() {
itemFetchRequest().returnsObjectsAsFaults = false
do {
let results = try moc.executeFetchRequest(itemFetchRequest())
print("===\(results)")
// Calculate the grand total.
var grandTotal = 0
for order in results {
let SLP = order.valueForKey("slprice") as! Int
let SLQ = order.valueForKey("slqty") as! Int
grandTotal += SLP * SLQ
}
print("\(grandTotal)")
cartTotal.text = "$\(grandTotal)" as String
} catch let error as NSError {
print(error)
}
}
`
slprice and slqty are strings in Core Data. I am trying to cast them as Int so they will do the arithmetic. I had this working but it totaled every item instead of only the crossed off ones (section 1). I gave it a rest for a while and now when I come back to try to work on it again Xcode is giving me an error of, "can not Could not cast value of type 'NSTaggedPointerString' (0x104592ae8) to 'NSNumber' (0x1051642a0)."
Can anyone help with this, please?