2

I'm a total Swift/IOS newbie and there's something about CoreData that I simply can't understand.

I have a class with some non-optional properties that are initialized by a designated initializer. Then, if I set that class to inherit from NSManagedObject, then suddenly I get the error

Stored property X requires an initial value or should be @NSManaged.

Why does Swift suddenly think my properties are not initialized, even though they clearly are?

Also, I read that @NSManaged "tells the compiler that the storage and implementation of the properties will be handled by CoreData", but what does that even mean?

Any answers would be appreciated..

user884248
  • 2,134
  • 3
  • 32
  • 57
  • Have you added any of the other parts of the core data stack and model? Why do you want this class to be a managed object? – Wain Aug 20 '16 at 10:00

1 Answers1

2

I was actually just reading about this yesterday.

Yes, it kinda really acts like @dynamic -- technically it might be identical even. Semantically there is a slight difference:

@dynamic says 'compiler, don't check if my properties are also implemented. There might be no code you can see but I guarantee it will work at runtime'

@NSManaged now says 'compiler, don't check those properties as I have Core Data to take care of the implementation - it will be there at runtime'

so you could even say: @NSManaged is syntactic sugar that is a more narrow version of dynamic :)

taken from this question

The big push with swift was to make the language extremely safe, as in this case, checking if the properties are implemented at compile time. If I understand correctly, CoreData doesn't quite conform to these compile time checks, thus adding in @NSManaged lets the compilers know that the variables will be taken care of.

From Apple:

You use the @NSManaged attribute to inform the Swift compiler that Core Data provides the storage and implementation of a declaration at runtime.

Community
  • 1
  • 1
random
  • 8,568
  • 12
  • 50
  • 85
  • I wrote a long comment but deleted it - these little Swift oddities are slowly starting to sink in. So, what you're saying is that NSManagedObject causes its subclasses to be unable to determine if a property is really implemented in the subclass? That's odd, considering that what triggers this warning is... that the properties ARE IMPLEMENTED. OK, so let's say I set these properties to be @NSManaged. What else do I have to do? How do I "implement these properties at run time", considering that his whole affair is nonsense and that the properties ARE, IN FACT, IMPLEMENTED? :-) – user884248 Aug 19 '16 at 15:24
  • I think it has to do with how the swift compiler deals with optionals. Swift is a type safe language and the CoreData stack still being in obj-c which is not technically type safe, the `@NSManaged` is a way to bridge those two worlds. This is my understand but would love for validation from someone much smarter than myself. – random Aug 19 '16 at 15:24
  • I think you may have a misunderstanding of implementation. Just because you have the variable declared doesn't mean it's implemented. When the swift compiler looks at a variable it has to either be optional or set. One of the two. A `NSMangedObject` subclass doesn't have that capability out of the box since it's inheriting from an obj-c base which is not type safe. You use the @NSManaged attribute to inform the Swift compiler that Core Data provides the storage and implementation of a declaration at runtime. @user884248 hope that helps! – random Aug 19 '16 at 15:28
  • Is this related to the fact the Objective-C uses separate header files and code files? (= separate interface and implementation?) – user884248 Aug 19 '16 at 15:36
  • No not at all, you can move all variables from a `.h` to a `.m` in obj-c if they don't need to be public. If fact it's proper style to keep private variables in the `.m` of a obj-c class. When the swift compiler looks at a variable it says, "I have to know what this is...now". The obj-c compiler looks at a variable and says, "meh, I don't care what it is, but! if it isn't set at runtime you'll crash". The `@NSManaged` tells the swift compiler, "I get it, you need to know now but just trust me it'll be there when we run". The swift compiler just tries to keep you safe :) – random Aug 19 '16 at 15:42
  • 1
    Thanks Random. That's a lot of help. – user884248 Aug 19 '16 at 19:15