I've been struggling with getting the information entered in an NSPredicatEditor from session to session in a Swift project.
Any guidance or samples would be greatly appreciated.
What I've got so far.
A predicate editor that is functional implemented in an Action Sheet.
Bound predicate to an NSArrayController also bound to a CoreData Table.
A method to generate Row Templates based on CoreData Table Attributes.
What is not working.
A bound predict variable to the predicateditor getting error on not
being able to match the predicate to a row template also at the
awakefromnib seems to be where this is checked the row templates are
not initialised (nil )at this point from the InterfaceBuilder
What I want to be able to do
Using the NSUSerDefaults persist the contents of the predicate editor so that when the application is re-started this editor has the data last entered.
Load the previously saved predicate by setting the editor's objectValue property.
predicateEditor.objectValue = predicate
After setting up the predicate editor, you typically send it a objectValue message to restore a saved predicate. source
It sounds like you may have a complicated setup involving Interface Builder, array controllers, Core Data, bindings, etc. Try it through code instead: load the row templates, then load the predicate.
Related
I have a ViewController with a 'Note' object as an instance variable. This variable is set before the ViewController appears.
The Note object contains a customFields NSMutableDictionary<String, String>.
I bind each value of the dictionary to a NSTextField of the dictionary in viewWillAppear :
newTextField.bind(.value, to: self, withKeyPath: "note.customFields.\(key)", options: nil)
The textField correctly displays the value from note.customFields.\(key).
BUT, if the user edits that value and saves, the change is not reflected in the dictionary.
The save() (basically a managedobjectcontext.save()) method has been tested with other fields (bound to other non-dictionary instance variables) and works properly.
Is there a reason why the dictionary does not receive the updated value?
Thanks for the help :-)
EDIT: here is the definition of customFields in the model:
The issue here is the combination of mutable type (here NSMutableDictionary) and Core Data.
This post helped: Core Data not saving transformable NSMutableDictionary
And this article helped as well: https://medium.com/#rohanbhale/hazards-of-using-mutable-types-as-transformable-attributes-in-core-data-2c95cdc27088
Solution summary
As proposed in the first link up-mentioned, I tried informing Core Data of changes in my NSMutableDictionary using note.valueDidChange(forKey: "customFields") but it did not work properly.
So I ended up using the second proposition in the first link, which is the same as the solution proposed in the second linked:
Use a NSDictionary as transformable type
When you need to modify this dictionary, use mutableDict = dictionary.mutableCopy(), and then save back to the nsdictionary : dictionary = mutableDict.copy()
For the specific case of NSTextField binding, the bindings will work for displaying the value, but for updating the value, you have to do it without bindings (whenever your view will disappear or when textfield ends editing)
Hope that helps!
xcode v:9.2
I am trying to load user information from the database to set as placeholder text. I have tested this code on a simpler project that does not have segment views, and it works fine. I did some research and I think it might be a hierarchical issue. I am struggling to understand how I can make the textfield values load so that the locations they point to are connected when I try to access them and set placeholder values.
GetCurr retrieves database values and sends them to completion handler function to write placeholder value. When run, "setPH = nil"
Calls GetCurr for email
Completion handler that sets placeholder text
loadUserView should tell when to load the values of this particular segment
I know it's not my IBOutlets because they are all connected and as previously said, this code works perfectly fine in a simpler app that does not have segment views.
I figured it out! I connected the segments to uiviews that had their own uiviewcontroller class, as subclasses of the parent base class. It also makes my code cleaner and prettier!
Useful:
https://docs.swift.org/swift-book/LanguageGuide/Inheritance.html
https://cocoacasts.com/managing-view-controllers-with-container-view-controllers/
I'm trying to set up a view-based table in Swift using bindings. All of the examples I've seen use a datasource/delegate setup.
I have an array of Flag objects which has two properties - flagName: String and flagImage: NSImage. I have an NSArrayController managing this array.
If I set up a cell-based table, and bind one column to arrangedObjects.flagImage and the other to arrangedObjects.flagName, I get a table displaying images and names, and I can use the array controller's add and remove methods, so there are no problems with my datasource or my array controller.
I have been following the instructions in Apple's TableView Programming Guide to bind my view-based table to my array controller:
tableView Content binding: FlagController.arrangedObjects
textField Value binding: TableCellView.objectValue.flagName
imageView Value binding: TableCellView.objectValue.flagImage
(IBs autocomplete is not happy with the paths for objectValue.flagName respectively flagImage; it doesn't feel that there should be any completion whatsoever and says it can't resolve the path, so it looks as if the problem is with the tableView's content.)
If I do this, my table has a number of rows that corresponds to the number of elements that my array controller is managing at that moment (I have two simple setups, one object vs. 50 objects, so it's clear that something is bound). What I don't get is a display; and selecting a table row does not seem to send back a message to my flagController.
What am I missing? Has anyone been able to make this work? I've had no problems with other bindings in Swift so far, but I'm starting to think that the sudden reappearance of datasource examples is not unrelated to this.
It sounds like you've failed to implement the delegate method -tableView:viewForTableColumn:row:. That's a common cause of blank tables.
You don't actually have to implement that if you make sure the identifier of the table column and the identifier of the table cell view are the same in IB.
Otherwise, the method can just do this:
- (NSView*) tableView:(NSTableView*)tableView viewForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row
{
return [tableView makeViewWithIdentifier:#"TheIdentifierOfYourTableCellView" owner:self];
}
(It could also do more, if desired.)
I have a sample code wherein:
I am unable to understand how data flows from database to reports because there is no place to set or fetch data explicitly. It is all done through custom objects.
Even we are not able to fetch data through console using NSLog as it has ENUM keys
All objects are custom objects so if we put it in NSLogs we get structure like < CustomObject-hexcode>. Many of the classes again comprise of objects from other classes.
Even if I try to debug code by putting breakpoint, then after few steps it show Hexadecimal codes
I wont be able to put sample code as it is a whole project containing lot of files.
Can you please let me know what kind of approach has been used? It looks like some sort of encapsulation.
Thanks!
Write categories that implement the - (NSString* ) description method for each custom object that displays all variables the custom obejects hold, you can there translate each of the enum values to strings. Then you can use NSLog to output objects and get readable results.
you need to debug application. and for this "All objects are custom objects so if we put it in NSLogs we get structure like < CustomObject-hexcode>"
you need to integrate a category class in your project. Search on google for override description of nsobject. You will get nslog in proper format.
It sounds like some kind of custom ORM with serialization / deserialization etc. Euuuwww.
I've implemented a small proof-of-concept app using Core Data to accept some object attribute values from the user via text fields and it's all working great thanks to information found here and in the iPhone Core Data Recipes app. But I'm at the point where I need to display object validation errors to the user and I can't find a recommended way of handling this. The code in the Recipe app just logs the error and says to "Replace this implementation with code to handle the error appropriately." Great, thanks.
I'm sure there are a multitude of ways to interpret, parse and transmit the validation error information to the user but what I'd like to know is if there are some best practices or a pattern that someone has implemented that I could follow. Where should the validation code like [newObject valdiateForInsert&error]; be placed? In NSManagedObject subclasses? In the UIViewController that handles the screen the enables the object to be added? Maybe in an app-wide ValidationController?
All the validation errors are returned in the NSError's userInfo, which is a NSDictionary of various NSValidation keys and values. Is there a good way of translating this error info into something that would be helpful to the user? For example, I have a rule in my Core Data model that a certain attribute can only be 3 characters long. If in the process of saving or updating an object I get a validation error, I need to parse out the NSError userInfo and find values for the NSValidationErrorKey (the name of the attribute), the NSValidationErrorValue (the value on the object that caused the error) and the NSValidationErrorPredicate (the rule that was violated, which in this case returns length <= 3.
Is there a good, generally accepted way of gathering and munging this data into something that can be passed back to the user? I'm currently pulling the NSError info into strings and then falling through a series of conditional statements for each attribute that I'm validating, and it's so ugly that I kinda want to puke when I look at it. There has to be a better, cleaner way to consume Core Data validation errors and pass a readable version to the user.
Validations are not there for the user. They are there so the code can maintain the integrity of the object graph. Validation methods are not called by the managed object context until the time at which context is saved. That time might be very distant from the time of input.
However, you can call an objects validation methods directly before you set an attribute. The validation methods have the form:
- (BOOL)validateTimeStamp:(id *)valueRef error:(NSError **)outError;
Suppose you have an attribute name for a managed object subclass PeopleMO. The validation method to check for an empty string might look like:
- (BOOL)validateName:(id *)valueRef error:(NSError **)outError{
BOOL isValid=NO;
NSString *toTest=(NSString *) valueRef;
if (![toTest isEqualToString:#""]) {
isValid=YES;
}
return isValid;
}
You could call it anywhere like:
NSString *newName=// some UI element text
PersonMO *newPerson=//.. insert new PersonMO object
if ([newPerson validateName:newName error:nil]) {
newPerson.name=newName;
}else{
//... inform user name is invalid
// ... possibly delete newPerson object from context
}
This is most useful where you have situations in which the validity of the value of one attribute depends on one or more other attributes of the same object.