Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data Codegen fail in Xcode 8

I have an iOS app containing a Core Data model with 6 entities. The entity Name is set up as follows:

Class Name: Name

Module: Current Product Module

Codeine: Class Definition

(all 5 other entities are set up similarly).

Problem 1 (fixed itself but leaving for posterity)

Code IS generated in the derived data folder… not as ~class definitions as expected, but as extensions instead (named like Name+CoreDataProperties.swift. It doesn't seem to matter whether the Codegen is set to Class Definition or Category/Extension - I still get the same result.

OK, hold that thought - all of a sudden both the class and extension files ARE now being generated… it looks like you need to delete the project's derived data folder and restart Xcode in between updates. Ignore Problem 1

Problem 2

Generated files ignore the data model Optional flag setting for String attributes and relationships - they are all generated as optionals

Problem 3 (fixed itself but leaving for posterity)

Ordered relationships are generated as OrderedSet (and a compilation error) rather than NSOrderedSet (can't change them as they get re-generated)

Workaround for me was to temporarily add to the project… public typealias OrderedSet = NSOrderedSet

OK, now the compiler error has gone, and OrderedSet seems to be recognised. Ignore Problem 3.

Problem 4

None of the above really matters, because the compiler can't find the files it's just generated. For the Name entity above:

:0: error: no such file or directory: '/Users/ashleymills/Library/Developer/Xcode/DerivedData/-grfqveelvqtlydbpwjmfdietnrss/Build/Intermediates/.build/Debug-iphonesimulator/.build/DerivedSources/CoreDataGenerated//.Name+CoreDataClass.swift' :0: error: no such file or directory: '/Users/ashleymills/Library/Developer/Xcode/DerivedData/-grfqveelvqtlydbpwjmfdietnrss/Build/Intermediates/.build/Debug-iphonesimulator/.build/DerivedSources/CoreDataGenerated//.Name+CoreDataProperties.swift'

It's looking in derived data for files .Name+CoreDataClass.swift and .Name+CoreDataProperties.swift - notice the '.' at the front of the file names. (As a temp fix I added the generated files into the project)

I assume I'm doing something wrong, as if this was the case for everyone, no-one would be able to build a Core Data project… or are these bugs that need raising?

Cheers Ash

(Also raised on Apple dev forums)

like image 462
Ashley Mills Avatar asked Aug 11 '16 13:08

Ashley Mills


6 Answers

Regarding Problem 1, setting the Codegen popup in the Inspector for an entity in an .xcdatamodel is supposed to work like this:

Category/Extension tells Xcode to generate one file, ClassName+CoreDataGeneratedProperties.

Class Definition tells Xcode to generate two files, the above-named file, plus ClassName+CoreDataClass.

However, there appears to be a bug, in Xcode 8.2. If, after changing one of these popups, you simply Build (⌘B) or Run (⌘R), your changes will not take effect. For example, if you changed from Class Definition to Category/Extension and even manually deleted the second file, it will reappear. You may even find that the popup reverts back to the original setting.

In order for changes in these popups to become effective, you must

  1. Save (⌘S) the .xcdatamodel file.
  2. Close all project windows.
  3. Re-open the project.

During the next build (which may occur automaticallly when the project opens if you have an @IBInspectable in a storyboard), the affected files in Derived Data will be generated or deleted to conform to your new setting.

UPDATE 2016-12-22: Thank you for the comment, Ashley. I've now written up and submitted this to Apple Bug Reporter: 29789727. Update 2017-02-08: Apple has closed 29789727 as it supposedly duplicates 21205277.

like image 169
Jerry Krinock Avatar answered Oct 24 '22 12:10

Jerry Krinock


Problem 4 can be fixed (at least in the latest beta, v. 6) by selecting all the entities you want auto-generated, and then in the inspector clearing the Class -> Module field so that it defaults to "Global namespace".

like image 37
Carl F. Hostetter Avatar answered Oct 24 '22 11:10

Carl F. Hostetter


Regarding problem 2: Core Data's "optional" flag has nothing to do with the Swift concept of an optional. They are unrelated and do not mean the same thing. Marking a Core Data attribute as non-optional does not imply that it's non-optional as Swift defines the term. The difference is:

  • Swift non-optionals must have non-nil values at all times.
  • Core Data non-optionals must have non-nil values when you save changes, but Core Data neither knows nor cares whether they're nil at other times.

Problem #4 sounds like Xcode getting its state confused, and may be fixed by voodoo like manually clearing the derived data folder (again, I know). I can't currently reproduce it, but that doesn't mean it's not a bug in the current beta.

like image 34
Tom Harrington Avatar answered Oct 24 '22 10:10

Tom Harrington


It's actually pretty easy to fix it.

Go to configuration:

enter image description here

Then delete the points. These are only there in older projects. The import statements are fixed after this and you are good to go.

You also should put your models to the Global namespace. Mine were in a extra namespace, but i have no idea why.

Apples approch is that you can use this in a custom framework.

This feature is pretty nice, if you get it working ;)

like image 39
Tob Avatar answered Oct 24 '22 11:10

Tob


Looks like Xcode 8.2.1 won't turn off codegen. But you can manually delete codeGenerationType="category" from .xcdatamodel contents file.

Close Xcode, delete codeGenerationType, delete DerivedData folder and rebuild.

Will wait for fix in future releases.

like image 37
AlKozin Avatar answered Oct 24 '22 12:10

AlKozin


I got completely stuck with Problem 4 and none of the above worked for me. I use code generation. To resolve it I did the following steps:

  1. I opened the .xcdatamodel / content file in a text editor. (In Xcode right-click your .xcdatamodel and choose "Open in external editor"
  2. In the XML file I made sure that each entity has codeGenerationType="class"
  3. Close and reopened Xcode Cleared my derrived data folder
  4. It still refused to do the Code Generation, so I then generated each Entity manually (Editor, Create NSManageObject Subclasses, select all entities)
  5. Build the project. Now it also did the Code Generation and compiler errors appeared saying that the Entity filenames were used twice.
  6. Deleted the Manually created NSManagedObject subclasses created in step 5.
  7. After that the project built again successfully and the problem disappeared.

PS: If you choose to Manually create your NSManageObject subclasses rather then using Code Generation, then make sure you remove codeGenerationType="class" from your entities in the XML file in step 2.

like image 40
Bocaxica Avatar answered Oct 24 '22 10:10

Bocaxica