Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I get the this string "85:ABC ,83:CFD" after downloading from a web service.I need to store these values to CoreData table TABLE_JOBTITLE. I have the below code
var designationDictionaryArray = results.componentsSeparatedByString(",")
var index: Int = 1
for item in designationDictionaryArray
{
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("TABLE_JOBTITLE",
inManagedObjectContext:managedContext)
let job = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext: managedContext)
job.setValue(String(index), forKey: "column_Id")
job.setValue(String(item.componentsSeparatedByString(":")[0]), forKey: "column_Server_Id")
job.setValue(String(item.componentsSeparatedByString(":")[1]), forKey: "column_Job_Name")
print("Column_Id")
print(index)
print("Column_Server_Id")
print(String(item.componentsSeparatedByString(":")[0]))
print("column_Job_Name")
print(String(item.componentsSeparatedByString(":")[1]))
do {
try managedContext.save()
print("saved job title")
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
self.desiginationArray.append(item.componentsSeparatedByString(":")[1])
index = index + 1
}
I am able to iterate through each data but the when i store it in the table..It get stored like below
coulmn_Id column_ServerId column_Job_Title
1 83 CFD
1 83 CFD
Could anyone help me with corrected code or reason for this bizarre behavior please..
I suspect one of two things:
The value in result is not as you expect.
The manner in which you are checking the output is faulty.
I lean towards the latter as I do not see any way both entities could be assigned the same column ID in a single run through.
Put breakpoints up top to check the value of results and the array returned from results.componentsSeparatedByString(",").
Show the code you used to iterate through the table to check it. My bet is that you are not showing the true output. What is the output from the print lines within the loop? If it looks something like this:
Column_Id
1
Column_Server_Id
85
column_Job_Name
ABC
Column_ID
2
Column_Server_ID
83
Column_ID
CFD
Then I'd say, for sure, you are not properly reading back your results from Core Data. Let us see where you are getting that final table.
I don't know what the problem was the same code worked as it should.
Related
I recently managed to catch an extremely rare exception in my code and was hoping folks here could help me understand it. I have a game which is tracking elapsed time and persisting the value to Core Data every second. At the same time a user could be playing the game and causing the score to update, which is also saved in Core Data. I suspect that I should be serializing saves, but at the moment I'm not. Everything works great 99.99% of the time, but once in a while the call to context.save() throws an exception.
I have a merge policy set as so:
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
And here's how I save elapsed time. The same pattern is used for updating a player's score.
func saveElapsedTime() {
let container = (UIApplication.shared.delegate as! AppDelegate).persistentContainer
container.performBackgroundTask() { (context) in
let storedGame = context.object(with: self.storedGameID) as! StoredGame
storedGame.elapsedTime = Int32(self.elapsedTime)
do {
try context.save()
} catch let nserror as NSError {
print("saveElapsedTime: failed to save: \(nserror). userInfo: \(nserror.userInfo).")
}
}
}
The rare error I was able to catch looks like this:
Error Domain=NSCocoaErrorDomain Code=133020 "Could not resolve merge changes."
<snip>...with oldVersion = 463 and newVersion = 463...<snip>
I've seen plenty of posts where the old and new versions are off by one or a small number, and people recommend setting a merge policy which is different than the default. I'm guessing that in my case where oldVersion == newVersion it's because multiple threads are trying to save at the exact same time. Can someone confirm this just by looking at the error message? Should I be serializing all saves using an OperationQueue like in this example: NSPersistentContainer concurrency for saving to core data?
Thanks in advance.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I basically have this issue where this Reporting API only allows me to call it once each 90 seconds.
I'm building an app where I get the data each time you open it, to get the latest data, but I somehow need to stop the app from calling the API if it was before 90s wait and show cached data, how can I do this?
Each time you go to ping the API compare the current time to the last time it was done. Kinda like this:
// set defaults for storage
let userDefaults = UserDefaults.standard
// set time
let date = Date()
//Check Storage
if let theDate = userDefaults.object(forKey: "date") as? Date {
// on successful load compare times
if date.timeIntervalSince(theDate) > 90000 /* I think it runs in milliseconds so I put 90 seconds worth there*/ {
// do API call here
// save time
userDefaults.set(date as! Any, forKey: "date")
} else {
print("too soon")
} else {
// data not successfully loaded
// try to ping API here too
// save time
userDefaults.set(date as! Any, forKey: "date")
}
I am building an app that incorporates Firebase and need to be able to be able to add/and or set data at the top of the my database. Currently whenever I add data it places it randomly under the parent node. I've seen some Objective C answers to this but they haven't really made to much sense. Sorry for the lack of code, but I don't know where exactly where to start on this issue. Any help would be great!
When you say it is getting placed 'randomly' under the parent, I think this is the childByAutoId() method getting called. While the name of the nodes appears randomly (e.g. -K6tdghsbci7g8), it will actually ensure that data is added under a given parent node in order. This is very useful for adding new data to lists. For example:
let pointlessData:String = "some data"
ref.childByAutoId().setValue(pointlessData)
// creates a new ordered child node under the `ref` with "some data" as the value
There isn't really a way to order the nodes back to front in this fashion, although you could order negatively by timestamp by adding a negative timestamp to each node you add then order your results using ref.queryOrderedByChild("negativeTimestamp") such that the values you get are the newest first.
let path = FirebaseBaseUrl + "dialogs/" + self.receiverId + "/" + self.senderId
let chilRef = FIRDatabase.database().referenceFromURL(path)
let refChild = chilRef.childByAutoId()
let dic = NSMutableDictionary()
dic .setValue(text, forKey: "text")
dic .setValue(FIRServerValue.timestamp(), forKey: "timestamp")
dic .setValue(true, forKey: "your")
refChild.updateChildValues(dic as [NSObject : AnyObject]) { (error, ref) in
if(error != nil){
print("Error",error)
}else{
print("\n\n\n\n\nAdded successfully...")
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Is there a way I can fetch contacts using the Contacts framework without an attribute?
Example:
myContactArray = unifiedContactsNotCalled("John")
PS: I know that line is nothing like the real code, it's just a serving suggestion for illustrative purposes 😉
Before I outline how to find those that don't match a name, let's recap how one finds those that do. In short, you'd use a predicate:
let predicate = CNContact.predicateForContacts(matchingName: searchString)
let matches = try store.unifiedContacts(matching: predicate, keysToFetch: [CNContactFormatter.descriptorForRequiredKeys(for: .fullName)]) // use whatever keys you want
(Obviously, you'd wrap that in a do-try-catch construct, or whatever error handling pattern you want.)
Unfortunately, you cannot use your own custom predicates with the Contacts framework, but rather can only use the CNContact predefined predicates. Thus, if you want to find contacts whose name does not contain "John", you have to manually enumerateContacts(with:) and build your results from that:
let formatter = CNContactFormatter()
formatter.style = .fullName
let request = CNContactFetchRequest(keysToFetch: [CNContactFormatter.descriptorForRequiredKeys(for: .fullName)]) // include whatever other keys you may need
// find those contacts that do not contain the search string
var matches = [CNContact]()
try store.enumerateContacts(with: request) { contact, stop in
if !(formatter.string(from: contact)?.localizedCaseInsensitiveContains(searchString) ?? false) {
matches.append(contact)
}
}
I'm parsing data from a JSON file that has approximately 20000 objects. I've been running the time profiler to figure out where my bottlenecks are and speed up the parse and I've managed to reduce the parse time by 45%, however according to the time profiler 78% of my time is being taken by the context.save() and much of the heavy portions throughout the parse are sourcing from where I call NSEntityDescription.insertNewObjectForEntityForName.
Does anyone have any idea if theres any way to speed this up? I'm currently batching my saves every 5000 objects. I tried groupings of 100,1000,2000,5000,10000 and I found that 5000 was the most optimal on the device I'm running. I've read through the Core Data Programming Guide but have found most of the advice it gives is to optimizing fetching on large numbers of data and not parsing or inserting.
The answer could very well be, Core Data has its limitations, but I wanted to know if anyone has found ways to further optimize inserting thousands of objects.
UPDATE
As requested some sample code on how I handle parsing
class func parseCategories(data: NSDictionary, context: NSManagedObjectContext, completion: ((success: Bool) -> Void)) {
let totalCategories = data.allValues.count
var categoriesParsed = 0
for (index, category) in data.allValues.enumerate() {
let privateContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
privateContext.persistentStoreCoordinator = (UIApplication.sharedApplication().delegate as! AppDelegate).persistentStoreCoordinator!
privateContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
//Do the parsing for this iteration on a separate background thread
privateContext.performBlock({ () -> Void in
guard let categoryData = category.valueForKey("category") as? NSArray else{
print("Fatal Error: could not parse the category data into an NSArray. This should never happen")
completion(success: false)
return
}
let newCategory: Categories?
do {
let newCategory = NSEntityDescription.insertNewObjectForEntityForName("Categories", inManagedObjectContext: privateContext) as! Categories
newCategory.name = category.valueForKey("name") as? String ?? ""
newCategory.sortOrder = category.valueForKey("sortOrder") as? NSNumber ?? -1
SubCategory.parseSubcategories(category.valueForKey("subcategories") as! NSArray, parentCategory: newCategory, context: privateContext)
} catch {
print("Could not create the Category object as expected \(error)")
completion(success: false)
}
do {
print("Num Objects Inserted: \(privateContext.insertedObjects.count)") //Num is between 3-5k
try privateContext.save()
} catch {
completion(success: false)
return
}
categoriesParsed+=1
if categoriesParsed == totalCategories{
completion(success: true)
}
})
}
}
In the above code, I look through the top level data objects which I call a "Category", I spin off background threads for each object to parse concurrently. There are only 3 of this top level object, so it doesn't get too thread heavy.
Each Category has SubCategories, and several other levels of child objects which yield several thousand objects each getting inserted.
My core data stack is configured with one sqlite database the standard way that is configured when you create an app with CoreData
One reason is that you're saving the managed object context in each single iteration, which is expensive and not needed. Save it after the last item has been inserted.