Attempting to work with Booleans in core data - swift

Started working with booleans trying to save them within core data and figured I could do a simple true/false save object but after reading I am unsure of whether or not they added the ability to do this in swift or not. I read another post Swift + CoreData: Can not set a Bool on NSManagedObject subclass - Bug?. Reading through it led me to believe that they changed this so that it should be able to save simple booleans based on the edit from the first answer.
So I created the class with Bool instead of NSNumber, and tried to set the object true and save the object. It doesn't seem to work. So my question is do you have to set the object with NSNumber still?
The issue I am facing is that when I try to recall the data using a fetch request after saving the Bool as true, with the default value set to No which should = false if I understand correctly, I should be able to recall which attribute is true through the getter that I created as a var that loops to check what the object is and returns it as a string. This however isn't working.

Related

Deleting Core Data elements with unwrapped optionals

I have a Core Data Entity with a Date attribute (e.g. current_date. Technically, in the Class which Core Data generates for that Entity, this attribute is optional (#NSManaged public var current_date: Date?). However, in my app this Date is always provided, which is why in the View I am displaying this fetched Entity via a list, I am force unwrapping it with current_date!. This all works fine so far. However, I have added an onDelete to that list to be able to delete single elements and now I am getting a bug Fatal error: Unexpectedly found nil while unwrapping an Optional value. Seems to be some problem related to the deletion process - as said, that value in the data is actually never empty. Does anyone know what is the problem here?
Your code may not set current_date to nil. But if you
Delete a managed object object
Save changes
Try to use that same managed object reference
...then current_date is nil, because that's something Core Data does. This error message suggests that you are attempting to use the object after deleting it and saving changes. Ideally you should fix that, because you won't have valid data anyway. You should also avoid force-unwrapping anyway, because using it is a way of specifically requesting app crashes any time you use it.

Cocoa bindings only working one way (NSMutableDictionary)

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!

does anyone have a working example of a fetched-property in core-data?

I have tried to use fetched properties a couple of times, and although it seems to be the right approach, it never works.
In my latest attempt I added the fetched-property to my entity, selected the other entity in the model as the 'destination', and set the predicate to a condition that I know is valid.
Problem 1: When the NSManagedObject-class for the entity is generated it does not include anything for the fetched-property. After some searching I added the declaration for it in the .h file and the #dynamic statement for it in the .m file (yes, I know it's an NSArray * type).
Problem 2: Even after that, when I access this property in code I get an exception being thrown that states something to the effect that the fetch-request does not have an entity. I am assuming that the 'entity' would be the one specified as the 'destination' and it is, in fact, there.
So, I'd like someone to provide a concrete working example (iOS platform) where a fetched-property is defined in the model, declared in a NSManagedObject-derived class, and actually used from code.
At this point I am giving up on this time-waster and simply implementing the fetch-request code myself.
Here's my relevant bits of code (including bits you've already mentioned):
My example has a 'Card' object that has a 1->many relationship with a 'Stats' object. Each 'Stats' object has an 'outcome' that can be 1-4. My fetched property is a simple one to give my 'Card' object an array of 'Stats' objects that are of 'outcome'=1 only.
I wanted to use the fetched property so that I could easily get hold of 'Card' objects that had more than a certain number and kind of 'Stats' objects.
So, in the 'Card' object I put the Fetched Property 'statsOfTypeOne', with Destination set to 'Stats'.
In the predicate for this fetched property I put
(SELF.outcome=1) AND (SELF.card=$FETCH_SOURCE)
'SELF' is the 'stats' record, and $FETCH_SOURCE magically becomes the 'Card' object when executed.
As you did, I put the following in the .h and .m files for the 'Card' object:
#property (nonatomic, retain) NSArray *statsOfTypeOne;
#dynamic statsOfTypeOne;
Then in my code I used:
[self.managedObjectContext refreshObject:cardInstance mergeChanges:YES];
[cardInstance valueForKey:#"statsOfTypeOne"]
to get at the array (although cardInstance.statsOfTypeOne should be fine). Without the refresh object it wasn't updating the Fetched property (as per the manual).
I think that's everything that I did to make it work. Let me know if it works for you.
Peter
Adding to #Peter's answer. Here's how I got it working in Swift 2.0 and Xcode 7:
import Foundation
import CoreData
#objc(Card)
class Card: NSManagedObject {
#NSManaged var statsOfTypeOne: [Stat]
}
And then, to read the fetched property:
managedObjectContext.refreshObject(someCard, mergeChanges: true)
// This works and returns [Stat] type
someCard.statsOfTypeOne
// So does this
someCard.valueForkey("statsOfTypeOne") as! [Stat]
Have you taken a look at this previous question: Xcode 4 Core Data: How to use fetched property created in Data Model editor
Read through the accepted answer and all of the comments. It sounds like they have it sorted out.

iPhone - Core Data Bool Values?

I have a BOOL in my core data.
I want the value to be null unless i set it to either YES, or NO.
Is it possible to do this?
in my code how can i check to see if the value has not been set yet or not?
In my nsmanagedObject i use NSNumber for my BOOL, in my core data mdoel i have BOOL.
CoreData allows you to set default values.
A Bool can contain "YES", "NO" , "None".
Setting the default value to "None" makes the returned value "null" which is exactly what i needed.
If you set Boolean as the attribute type in your model, that means it will be implemented using NSNumber.
I'm not sure why you'd want to return no value instead of NO, I'd actually recommend you don't. You'll have a much easier time with data integrity if you just set a false default value.
However, if you absolutely insist, you can just check if the attribute is nil or not to see if it was assigned a value yet.
The correct answer is yes, and there is real meaning to use 'yes' 'no' and a different 'none', which means the data is intact. In Core Data there is good reason sometimes to check against 'none', especially if you'd like to debug a database. In Core Data you can use:
[myManagedObject setValue: nil forKey:#"attributeOfMyManagedObject"];
and if check your SQL database behind your Core Data you will see 'NULL' if you use default settings.

Best way to use my singleton

I started to develop my singleton class but I have a problem.
What I want to do is have a search objects containing the values of the search form that I could use in several views.
I want to have the ability to get the singleton in any view in order to perform the search or build the search form.
So I have a set of values with a boolean for each to know if the variable has been initialized by the user or not, cause not all the search fields needs to be filled in.
For example :
NSString name= Bob;
BOOL nameFilled =True;
NSString adress= nil;
BOOL adressFilled=false;
NSNumber numberOfChilds = 0;
BOOL numberOfChildsFilled = false;
So my problem is that I can't retain the boolean in my header file because it's not a class.
How can I do, is there a better solution than what I presented above?
Hope I have been clear
You dont need to have this BOOLean value to see if it is filled, why not just use the object itself to see if it has been initialized so something like
if(name==nil)
//this means i t hasnt been initialized
else
//this means it has
Instead of using int, use NSNumber. Then, for objects that haven't been specified, use 'nil', which is distinct from an NSNumber with 0 as a value.
You don't need to #retain BOOL or other primitive types in Objective-C - you only need use that for object types.
Seriously, don't implement a singleton. It isn't necessary for this application. You should have a model class to handle this.
Try using dependancy injection and/or plist files to save the information. You'll have a much better time debugging and extending functionality.