Update textfields to CoreData without destroying unchanged data - core-data

When I change any textfield on my update form with new information ONLY that change is saved. All other previously saved data for the entity is lost in the process.
func updateDog (
id: String,
dogName: String,
activeStatus: Int16,
breed: String,
//etc (about 30 attributes below here )
)
{
let fetchDog: NSFetchRequest<Dog> = Dog.fetchRequest()
fetchDog.predicate = NSPredicate(format: "id == %#", id)
do {
let dog = try self.moc.fetch(fetchDog).first
dog?.dogName = dogName
dog?.activeStatus = activeStatus
dog?.breed = breed
//etc
if self.fetchDog(dogName: dogName)?.hasChanges ?? true {
try self.moc.save()
}
} catch
let error as NSError {
print(error)
}
There are no errors messages, but any attributes already stored, which are left unchanged during the updating are lost in the self.moc.save process. Only the edited fields are updated.
I want it to ignore any attribute that has not been altered and simply update the changed data. I've been going around in circles but cannot achieve the correct behaviour. I am not very experienced as have only been learning to code for a few months, and my advancing years probably add to my struggles to grasp the problem I'm having. Any help is gratefully recieved

Related

disable/hide UISearchBar when datasource is nil

I want to make sure that no search bar is displayed when the datasource of my table view is empty. (Makes sense, no? shouldn't that be default behaviour?)
Here's a piece of my code that tries (currently uncommented) different things to accomplish that, but somehow it doesn't work.
Can anybody advise me what I'm doing wrong? Let me know if you need more snippets.
messagesArray=loadMessages()
DispatchQueue.main.async {
if (self.messagesArray.count==0){
self.noMessageview.isHidden=false
//self.searchController.searchBar.isHidden = true
//self.searchController.isActive = false
} else{
self.noMessageview.isHidden=true
//self.searchController.searchBar.isHidden = false
//self.searchController.isActive = true
}
self.spinner.stopAnimating()
self.refreshControl.endRefreshing()
self.tableView.reloadData()
}
UPDATE:
I declare the search controller like this:
let searchController = UISearchController(searchResultsController: nil)
and in the ViewDidLoad I do:
navigationItem.searchController = searchController
I believe you are using iOS 11 because of setting UISearchController from navigationItem, Thus you can use the following code to remove it:
if #available(iOS 11.0, *) {
self.navigationItem.largeTitleDisplayMode = .never;
self.navigationItem.searchController = nil
} else {
// Fallback on earlier versions
self.navigationItem.titleView = nil
};
I had some problem and i think its iOS 11 bug, when removing the UISearchController, the view doesn't get adjusted thus i had to call this right before removing UISearchController.
self.navigationItem.largeTitleDisplayMode = .never;
Thats all.

Updating time and date in wit-ai weather example

I am trying to extend the wit-ai weather example by adding wit/datetime to the mix.
For example a user might type "How cold will it be in Berlin in 1 hour?" and the weather bot will bring back the data for the weather in 1 hour in Berlin.
So far this works, but when I try to setup missingDate in order to ask the date if it's missing it behaves kind of funny.
A dialogue would be:
- How cold will it be in Berlin?
- In what time?
- In 1 hour.
Instead, after the 1 hour step, I get asked again for the location which is in the context, but instead is triggered again.
My action is named getForecast({context, entities}) and I have defined it as below:
actions:
[...],
getForecast({ context, entities }) {
console.log(`The current context is: ${JSON.stringify(context)}`);
console.log(`Wit extracted ${JSON.stringify(entities)}`);
// extract entity
var location = firstEntityValue(entities, "location");
var date = firstEntityValue(entities, "datetime");
// if the entity exists, do a remote weather call.
if (date) {
context.date = date;
delete context.missingDate;
} else {
context.missingDate = true;
delete context.date;
delete context.forecast;
}
if (location) {
context.forecast = '38 degrees';
context.location = location;
delete context.missingLocation;
} else {
context.missingLocation = true;
delete context.forecast;
}
// return the context object
return Promise.resolve(context);
}

Need help filtering core data in Swift 3

I can't seem to find any good documentation or tutorials that pertain to filtering core data in Swift 3.
I have the following code:
let tempVar: String = "abcdef"
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do {
/* Need code to modify the fetchRequest, so that it only pulls results where the "projectID" field is equal to whatever is stored in the tempVar variable. */
cstProjectDetails = try context.fetch(CSTProjectDetails.fetchRequest())
} catch {
print("There was an error fetching CST Project Details.")
}
Basically, I am just trying to do add a simple filter to the fetchRequest, so that it only pulls results from "cstProjectDetails" where the "projectID" field is equal to the contents of a previously set variable (in this case, "tempVar").
Any ideas?
Edit: The checked answer did the trick for me, but I had to make a quick adjustment to the code for the request initializer. Here is the code that I ended up with:
do {
let request: NSFetchRequest<CSTProjectDetails> = CSTProjectDetails.fetchRequest()
request.predicate = NSPredicate(format: "projectID == %#", cstProjectID)
cstProjectDetails = try context.fetch(request)
print(cstProjectDetails)
} catch {
print("There was an error fetching CST Project Details.")
}
You need a predicate attached to the request:
let request = CSTProjectDetails.fetchRequest()
request.predicate = NSPredicate(format: "projectID == %#", tempVar)
cstProjectDetails = try context.fetch(request)

Fetch Request Result, Core Data & Swift 3

Now that NSFetchResultsController and NSFetchRequest are Generics in Swift 3, there have been a few changes in the initialization. I used the migrator (which was great!) and everything compiles fine. But the app crashes when I try and retrieve attributes the Swift 2 way.
I have thoroughly researched this problem.
There are few examples of how to initialize NSFetchResultsController and NSFetchRequest, but the various responses on StackOverflow are competing or currently inadequate when explaining the retrieval. Apple's documentation, too, is clear but not working.
Here is my code where Person is the Entity:
// MARK: - Initialize Fetch Results
var fetchedResultsController = NSFetchedResultsController<Person>()
func setFetchRequest() -> NSFetchRequest<Person> {
do {
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = Giver.fetchRequest()
let fetchResult = try moc?.fetch(fetchRequest)
// CANNOT FIGURE OUT WHAT GOES HERE e.g.
// person.name = fetchResult.first (this does not work)
// person.name = fetchResults (this does not work)
let sortDescriptor = SortDescriptor(key: "names", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]
} catch {
print("Error with request: \(error)")
}
return setFetchRequest()
}
// MARK: - Retrieve Fetch Request
func getFetchRequest() -> NSFetchedResultsController<Giver> {
fetchedResultsController = NSFetchedResultsController(fetchRequest: setFetchRequest(), managedObjectContext: moc!, sectionNameKeyPath: nil, cacheName: nil)
return fetchedResultsController
}
At the moment, there is no error, save the yellow triangle indicating that "fetchResult" has not been used. I am trying to fetch a few attributes: name: String, age: Int, photo: BinaryData. How would I retrieve these attributes?
I realize Swift 3 is still in beta. Just frustrated experiencing the pangs of source-breaking changes.

Azure Mobile server update script w/ complex field type

I've got a complex data type "AzureTemplate" containing a list of children "AzureField". I've implemented my read and insert on the server side according to this article. Works great.
Needing an update as well, I copy/pasted the insert into the update so it does the same thing, but using update instead. So my update looks like this:
function update(item, user, request) {
// remove complex child object, make copy first
var fields = item.fields;
if (fields) {
delete item.fields;
}
request.execute({
success: function () {
var templateId = item.id; // "foreign key"
var fieldsTable = tables.getTable('AzureFields');
if (fields) {
// update the child fields
var updateNextField = function (index) {
if (index >= fields.length) {
// done updating fields, respond to client
request.respond();
} else {
var field = fields[index];
field.templateId = templateId;
// *** THE ID LOGGED HERE LOOKS FINE ***
console.log("updating field w/ id ", field.id);
fieldsTable.update(field, {
success: function () {
updateNextField(index + 1);
}
});
}
};
// kick off the loop saving each field
updateNextField(0);
} else {
// no fields. no need to do anything else
request.respond();
}
}
});
}
The log that prints the ID of the child "field" shows a valid field id (I save them on the client side when reading them). But I get an error that says:
Error in script '/table/AzureTemplate.update.js'. Error: Invalid id value specified. AzureTemplate/update Tue Jan 27 2015, 10:11:31 AM
I put a console.log() at the top of the AzureField.update, but that never shows up, so it's not getting in there. Also, when I update a single child "Field" directly from the client it works fine. So the AzureField.update is working. Any ideas?
var fieldsTable = tables.getTable('AzureFields');
... my table name is AzureField, not AzureFields. The above code works, hopefully it helps someone.
I have misnamed a table before and got a meaningful error about "table not existing". Not sure why the error in this case is totally unrelated.

Resources