i want to update data after editing. for that i need the previous data.
but in my case after editing, the variable that hold the previous value are replaced by the present value.
how can i hold the previous value??
if itemToEdit == nil{
item = TestDataModel()
else{
item = itemToEdit
selectedItemToEdit = itemToEdit
// print(selectedItemToEdit?.title)
print(item.title)
// print(itemToEdit?.title)
}
if let title = titleField.text {
item.title = title
print(item.title)
}
// print(selectedItemToEdit.title!)
print(itemToEdit?.title!)
if let price = pricefield.text {
item.price = (price as NSString).doubleValue
print(item.price)
}
if let details = detailsField.text {
item.details = details
print(item.details)
}
itemToEdit, is that which i want to edit/ update. that's why i stored it in selectedItemToEdit. in item, i have stored the data after editing.
i need both the previous value and the present value that i entered in textfield.
how can i get that one.please any one help....
What you're doing when you try to save previous information is simply creating a new variable that points to the same object. When the object changes, it doesn't matter what variable you use to examine it, you will see the changes in that one object.
Here's a playground sample that should give you an idea of the difference between having two objects vs. having two pointers to the same object.
class MyData {
var title = "Default"
init() {
}
init(source: MyData)
{
title = source.title
}
}
var d1 = MyData()
var d2 = d1
var d3 = MyData(source: d1)
d1.title = "changed"
print(d2.title)
print(d3.title)
yeah i solved the problem:
i just declared a variable of string type as bellow:
var selectedItemToEdit: string!
selectedItemToEdit = itemToEdit.title
i passed that string type variable and the edited variable to the save function.
Related
In view model I try to call two functions one of them create new list "addNewList" and in side this function I create a new sublist "addMainSublist" as shown in the code bellow, the "addNewList" function work perfectly. Also, when I try to call the "addMainSublist" inside "addNewList" the error in the photo shown inside "PersistenceController" file when I try to save the new sublists in CoreData, I call the "addNewList" inside SwiftUI view and take "moc" parameter from "#Environment(.managedObjectContext) private var managedObjectContext" property in the SwiftUI view.
Note: as you see in the code bellow I use the same "managedObjectContext" to save both new list and new sublist, when I erase all content in the simulator and try to create new list the error did not show but in the second try the error shown again.
func addNewList(moc: NSManagedObjectContext, mainLists: FetchedResults<ListOfTasks>, favoriteLists: FetchedResults<ListOfTasks>) {
let newList = ListOfTasks(context: moc)
newList.id = UUID()
newList.addedDate = addedDate
newList.title = title
newList.icon = icon
newList.color = Color.set(stringfor: color)
newList.origin_Group = origin_Group
if origin_Group == nil {
newList.state = ListState.list.rawValue
newList.index = Int16(mainLists.count)
newList.isFavorite = isFavorite
newList.favoriteIndex = Int16(isFavorite ? favoriteLists.count : 0)
}else{
if let wrappedGroup = origin_Group {
newList.state = ListState.sublist.rawValue
newList.index = Int16(wrappedGroup.listsArray.count-1)
newList.isFavorite = false
newList.favoriteIndex = 0
}
}
newList.isLocked = isLocked
newList.isArchived = isArchived
PersistenceController.shared.save()
addMainSublist(to: newList, moc: moc)
}
func addMainSublist(to newList: ListOfTasks, moc: NSManagedObjectContext) {
let mainSublist = Sublist(context: moc)
mainSublist.origin_List = newList
mainSublist.id = UUID()
mainSublist.addedDate = Date()
mainSublist.index = 0
mainSublist.title = "\(title)_MainSublist"
mainSublist.isExpanded = false
mainSublist.isArchived = false
PersistenceController.shared.save()
}
Error Photo
The answer by Joakim Danielson who gives me the note about "compare", the problem is using sort description "list.title" to fetch all sublists in the SwiftUI view for debugging, and when I change that the error is gone, thanks for "Joakim Danielson" for his valuable note.
Not the issue specifically here but in case on your search you come across this same error, check if you have your "one to many" or "one to one" relationship set correctly. That was my case where I forgot to change it to "one to many" when I set up the relationship between two entities. That solved my error.
class Employee{
var id:Int
var name:String
var salary:Int
init(){
self.id=0
self.name=""
self.salary=0
}
func getInfo(){
self.name=readLine()!
self.id=Int(readLine()!)!
self.salary=Int(readLine()!)!
}
}
var count=0
var flag="y"
var empData:[Employee]=[]
repeat{
count+=1
empData[count]=Employee()
empData[count].getInfo()
flag=readLine()!
}while(flag=="y") `
I have a class Employee with properties id , nam and salary. The function getInfo() is used to get information from user. I want to read data until the flag!="y" . I am getting index out of range error.
What is the right way of inputting data? Can we index the objects ?
You need to append to your array to make it increase in size. Replace
empData[count]=Employee()
with
empData.append(Employee())
to avoid index out of range error
Update
To make your code a little less horrible I would do
repeat {
var employee = Employee()
employee.getInfo()
empData.append(employee)
flag=readLine()!
}while( flag == "y" )
The subscript operator cannot be used to add elements to an array index which doesn't exist yet. You either need to initialize the array with an element count if you know at the time of initialization how many elements your array will have or use the append operator to add new elements to the array after the last index.
You don't even need the count variable, as you can simply access empData.last safely after calling append and adding a new Employee to the Array.
var flag="y"
var empData:[Employee]=[]
repeat {
empData.append(Employee())
empData.last!.getInfo()
flag=readLine()!
} while(flag=="y")
I would advise you to seriously reconsider your implementation as it is really unsafe at the moment. You are not validating user input in any way, hence your getInfo function can easily cause runtime errors if the user input is not in the expected form. Moreover, creating an empty initializer for Employee doesn't make sense, you could simply create a failable initializer, where you read the input and if the input is not of the correct form, make the initializer return nil.
class Employee{
let id:Int
let name:String
let salary:Int
init?(){
guard let name = readLine() else { return nil }
self.name = name
guard let idString = readLine(), let id = Int(idString) else { return nil }
self.id = id
guard let salaryString = readLine(), let salary = Int(salaryString) else { return nil}
self.salary = salary
}
}
var flag="y"
var empData:[Employee]=[]
repeat {
if let employee = Employee() {
empData.append(employee)
} else {
// Display error message to the user
}
flag=readLine() ?? ""
} while(flag=="y")
Here is my JSON response for a particular API.
Case 1
ChallengeConfiguration = {
AnswerAttemptsAllowed = 0;
ApplicantChallengeId = 872934636;
ApplicantId = 30320480;
CorrectAnswersNeeded = 0;
MultiChoiceQuestion = (
{
FullQuestionText = "From the following list, select one of your current or previous employers.";
QuestionId = 35666244;
SequenceNumber = 1;
},
{
FullQuestionText = "What color is/was your 2010 Pontiac Grand Prix?";
QuestionId = 35666246;
SequenceNumber = 2;
}
)
}
The key "MultiChoiceQuestion" returns an array with two questions. So here is my code.
let QuestionArray:NSArray = dict1.objectForKey("ChallengeConfiguration")?.objectForKey("MultiChoiceQuestion") as! NSArray
Case 2
ChallengeConfiguration =
{
AnswerAttemptsAllowed = 0;
ApplicantChallengeId = 872934636;
ApplicantId = 30320480;
CorrectAnswersNeeded = 0;
MultiChoiceQuestion = {
FullQuestionText = "From the following list, select one of your
current or previous employers.";
QuestionId = 35666244;
SequenceNumber = 1;
}
}
For Case 2 my code does not work and app crashes because it returns a dictionary for that specific Key. So how could I write a generic code that would work for all objects?
It looks like the key can contain either an array of dictionary values or a dictionary, so you just need to try casting to see which one you have.
so I would likely do it like this:
if let arr = dict1.objectForKey("ChallengeConfiguration")?.objectForKey("MultiChoiceQuestion") as? Array {
// parse multiple items as an array
} else if let arr = dict1.objectForKey("ChallengeConfiguration")?.objectForKey("MultiChoiceQuestion") as? [String:AnyObject] {
// parse single item from dictionary
}
You should never really use ! to force unwrap something unless you are completely certain that the value exists and is of the type you are expecting.
Use conditional logic here to test the response and parse it safely so that your app doesn't crash, even in failure.
I'm fetching data from a weather API. I'm not sure how to access the description?
"weather": <__NSSingleObjectArrayI 0x608000012910>(
{
description = "overcast clouds";
icon = 04n;
id = 804;
main = Clouds;
}
)
I tried:
print(weatherDict["weather"]!.description!)
It just gave me this:
(
{
description = "overcast clouds";
icon = 04n;
id = 804;
main = Clouds;
}
)
How do I properly access the description?
weather contains an array of dictionaries.
description is a key in the first item of the array.
The code unwraps weather safely and checks if the array is not empty:
if let weatherArray = weatherDict["weather"] as? [[String:Any]],
let weather = weatherArray.first {
print(weather["description"]) // the value is an optional.
}
I'm having trouble understanding why my ordered set is only saving 1 entry.
my code is as follows:
let newInovice = NSEntityDescription.insertNewObjectForEntityForName("Invoice", inManagedObjectContext: managedObjectContext) as! InvoiceMO
let itemDetail = NSEntityDescription.insertNewObjectForEntityForName("InvoiceDetail", inManagedObjectContext: managedObjectContext) as! InvoiceDetailMO
// Data Entry
// Add invoice number to Invoice
newInovice.invoiceNumber = getInvoiceNum()
newInovice.date = invoiceDate
// Create mutable set to add details
for items in details {
itemDetail.detail = items[PropKeys.itemDescription]
let item = items[PropKeys.itemPrice] ?? "0"
let itemDouble = { return Double(item) ?? 0 }()
itemDetail.price = itemDouble
let quantity = items[PropKeys.itemQuantity] ?? "1"
let quantityInt = { return Int(quantity) ?? 0 }()
itemDetail.quantity = quantityInt
print("This is the item detail before insertion: \(itemDetail)")
newInovice.mutableOrderedSetValueForKey("invoiceDetails").addObject(itemDetail)
subtotal += itemDouble * Double(quantityInt)
}
print("details.Count = \(details.count)")
print("Start Mutable \(newInovice.invoiceDetails?.count) End Mutable Set")
// Save the Data
do {
try newCustomer.managedObjectContext?.save()
} catch {
print(error)
}
I've read through the docs and it seems like I'm doing this correctly but it only adds one entry to the ordered set even though I've iterated through the array of objects.
Here is my debugger showing the entries before they are added and the count of the managed object after adding the objects.
debuggerWindow
my relationships are set up as follows:
relationships
You are only creating one InvoiceDetail outside your for loop. Obviously, you will have to create one for each detail that is contained in the data array.