Xcode NSManagedObject subclass contains optionals when they are marked as non-optional
"Optional" means something different to Core Data than it does to Swift.
- If a Core Data attribute is not optional, it must have a non-nil value when you save changes. At other times Core Data doesn't care if the attribute is nil.
- If a Swift property is not optional, it must have a non-nil value at all times after initialization is complete.
Making a Core Data attribute non-optional does not imply that it's non-optional in the Swift sense of the term. That's why generated code makes these properties optional-- as far as Core Data is concerned, it's legal to have nil values except when saving changes.
Swift + CoreData: Cannot Automatically Set Optional Attribute On Generated NSManagedObject Subclass
The optional checkbox in the Core Data Model Editor has been existing before Swift and its optionals where introduced. Apple states about it in its Core Data Programming Guide:
You can specify that an attribute is optional — that is, it is not
required to have a value. In general, however, you are discouraged
from doing so — especially for numeric values (typically you can get
better results using a mandatory attribute with a default value — in the
model — of 0). The reason for this is that SQL has special comparison
behavior for NULL that is unlike Objective-C's nil. NULL in a database
is not the same as 0, and searches for 0 will not match columns with
NULL.
Thus, using Swift and Xcode 8, optional checkbox is (still) not related to the fact that you defined your properties as optionals or not in your managedObject subclasses. And don't expect optional checkbox to have any impact on your NSManagedObject
subclasses properties optional type when you create them using Editor > Create NSManagedObject Subclass.
That said, every time I need a property to have its optional checkbox checked in the Model Editor, I immediately put its NSManagedObject
Subclass declaration as an optional.
Addendum
Mogenerator is able to automatically toggle your NSManagedObject
subclass properties from non-optional to optional every time you change this option for each of your Entity's attribute in the Data Model Inspector and rebuild your project.
SwiftUI core data optional and non-optional properties
When you create your entity the default setting for Boolean and Double is to use scalar (primitive) types and they are non-optional because Objective-C (which is what Core Data is based on) can't handle optional scalar types.
This is how they are defined in code
@NSManaged public var boolean: Bool
@NSManaged public var number: Double
If you uncheck to use scalar type (Inspector Cmd-alt-0) then the underlying type would be NSNumber instead and they would be optional
@NSManaged public var number: NSNumber?
@NSManaged public var boolean: NSNumber?
How does Core Data codegen decide whether to make a property optional?
Core Data is still rooted in Objective-C. So the primitives (bool
, int
, float
, etc.) will be non-optionals, and the objects will be optionals.
Some data can be either an object or a primitive. For example, someone's age could be a NSNumber
or a NSInteger
. If you prefer that such a variable be backed by a primitive, then you can check the scalar
box for the property in your model.
Core data | automatically generated String and Date attributes are optional even when not marked in swift
Two options
- Edit the
MyManagedObject
to make them non-optional. This means you need to maintain this class yourself and do any changes both in the core data model and the class - Create a protocol (or sub class) with same attributes (you need to give them new names) but non-optional and implement this protocol in a separate extension to get and set original attributes and then use this protocol rather than
MyManagedObject
in your code.
If your data model is stable and won't be changed that much the first option is probably best.
Core Data optional attributes and properties with Swift rules
I think that if the Swift team at Apple would read your question, they would smile and say: "Good question! Another example of how Swift is helping developers to question and improve their code."
My approach to this is:
Let Core Data be Core Data. Attributes can be null. If proper operation requires an attribute to be not null, you may wish to validate this prior to insertion. But, since Core Data is a persistence framework, I assume that these objects are being saved to the disk, and data from the disk should never be trusted … it could be corrupt, or some unforseen future version of your app or an app extension could either intentionally or unintentionally cause some attributes to be null.
Let Swift be Swift. A major design goal of Swift was to protect you from such unexpected nulls. As you have recognized, force unwrapping is discouraged. Instead, use
if let
orguard let
. These are explained in Apple's Swift book, although you can find dozens of blog posts like this one which are more to the point.
Swift Core Data Usage in Xcode
Answers:
Creating the subclasses manually treates the optionals not accurately. Check any attribute and remove the question mark in the class if it's non-optional in the model.
Scalar Swift optional types (
Int?
,Double?
,Bool?
) cannot be represented in Objective-C. I recommend to declare them as non-optional.Never mind, it has no effect where the classes are located, the main thing is that the file name is black (valid) in the Project Navigator and the target membership is assigned correctly.
in the Codegen Manual / None case you are responsible that the types in the model match the types in the classes otherwise you could get unexpected behavior. Any change in the class must be done also in the model and vice versa. However you can replace suggested ObjC classes like
NSSet
orNSDate
with native Swift typesSet
orDate
without changing the type in the model.
Xcode generate NSManagedObject Subclass issue
So I also ran in this issue. You have to disable automatical code generation if you want to create the NSManagedObjects by yourself. So there are different ways. First way is go to your model and changed the Toolversion to xCode 7.3.
In every entity you can set the Codegen to Manual/None like in the Screenshot.
Clean your project, and try again!
I hope this was helpful.
Xcode 8 generates broken NSManagedObject subclasses for iOS 10
I finally got mine to work. Here is what I did. (Flights is one of my entities)
I setup the xcdatamodeld as follows
And then the entity as
Then I used Editor -> Create NSManagedObject Subclass
This creates two files for my flights entity
Flights+CoreDataProperties.swift
Flights+CoreDataClass.swift
I renamed Flights+CoreDataClass.swift to Flights.swift
Flights.swift is just
import Foundation
import CoreData
@objc(Flights)
public class Flights: NSManagedObject {
}
Flights+CoreDataProperties.swift is
import Foundation
import CoreData
extension Flights {
@nonobjc public class func fetchRequest() -> NSFetchRequest {
return NSFetchRequest(entityName: "Flights");
}
@NSManaged public var ...
}
This appears to work for me.I could not get Codegen to work in any other way, even though I tried many of the suggestions that were out there.
Also this had me scratching my head for a while and I add it as an assist. Don't forget with the new Generics version of the FetchRequest you can do this
let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: "Flights")
Related Topics
Exhaustive Condition of Switch Case in Swift
Get Last Image from Photos.App
Invalid Update: Invalid Number of Rows in Section 0
How to Create an Umbrella Framework in iOS Sdk
Receiver (<Viewcontroller>) Has No Segue with Identifier 'Addsegue'
How to Fix "No Valid 'Aps-Environment' Entitlement String Found for Application" in Xcode 4.3
Creating a Shadow for a Uiimageview That Has Rounded Corners
Dismiss Keyboard on Touch Anywhere Outside Uitextfield
Volunteermatch API Objective C
How to Get an Iso 8601 Date on iOS
Callback Method If User Declines Push Notification Prompt
iOS Memory Allocation - How Much Memory Can Be Used in an Application
iOS 7 -- Navigationcontroller Is Setting the Contentinset and Contentoffset of My Uiscrollview
Custom Init for Uiviewcontroller in Swift with Interface Setup in Storyboard
Programmatically Creating an Expanding Uitableviewcell
Scroll Uitextfield Above Keyboard in a Uitableviewcell on a Regular Uiviewcontroller