I updated my iOS app project recently to iOS 10. Now I'm trying to change the Core Data Model of my app but the new NSManagedObject subclasses which Xcode generates are broken. I also tried to fix the subclasses manual but this doesn't work.
The minimum tools version for the Core Data Model is set to Xcode 7.0 and code generation language is set to Swift.
This is the code which Xcode generates:
import Foundation
import CoreData
import
extension Group {
@nonobjc public class func fetchRequest() -> NSFetchRequest {
return NSFetchRequest(entityName: "Group");
}
@NSManaged public var name: String?
@NSManaged public var platform: NSNumber?
@NSManaged public var profiles: NSOrderedSet?
}
// MARK: Generated accessors for profiles
extension Group {
@objc(insertObject:inProfilesAtIndex:)
@NSManaged public func insertIntoProfiles(_ value: SavedProfile, at idx: Int)
@objc(removeObjectFromProfilesAtIndex:)
@NSManaged public func removeFromProfiles(at idx: Int)
@objc(insertProfiles:atIndexes:)
@NSManaged public func insertIntoProfiles(_ values: [SavedProfile], at indexes: NSIndexSet)
@objc(removeProfilesAtIndexes:)
@NSManaged public func removeFromProfiles(at indexes: NSIndexSet)
@objc(replaceObjectInProfilesAtIndex:withObject:)
@NSManaged public func replaceProfiles(at idx: Int, with value: SavedProfile)
@objc(replaceProfilesAtIndexes:withProfiles:)
@NSManaged public func replaceProfiles(at indexes: NSIndexSet, with values: [SavedProfile])
@objc(addProfilesObject:)
@NSManaged public func addToProfiles(_ value: SavedProfile)
@objc(removeProfilesObject:)
@NSManaged public func removeFromProfiles(_ value: SavedProfile)
@objc(addProfiles:)
@NSManaged public func addToProfiles(_ values: NSOrderedSet)
@objc(removeProfiles:)
@NSManaged public func removeFromProfiles(_ values: NSOrderedSet)
}
Edit: These are the specific errors which Xcode gives:
1. Group+CoreDataProperties.swift:13:1: Expected identifier in import declaration (the empty import)
2. Group+CoreDataProperties.swift:13:11: 'Group' is ambiguous for type lookup in this context
3. Group+CoreDataProperties.swift:15:16: Cannot specialize non-generic type 'NSFetchRequest'
4. Group+CoreDataProperties.swift:26:11: 'Group' is ambiguous for type lookup in this context
4. Group+CoreDataProperties.swift:43:82: 'SavedProfile' is ambiguous for type lookup in this context
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<Flights> {
return NSFetchRequest<Flights>(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<NSFetchRequestResult> = NSFetchRequest(entityName: "Flights")
I believe the reason you encountered those errors after generating the NSManagedObject subclass files may be related to the Codegen option that was selected at the time your data model changed.
I do not think this is a bug. At least not in Xcode 8.1 (8B62).
I encountered a similar issue and fixed it by changing the Codegen option to "Manual/None" and leaving the Module option as "Global Namespace". I then generated my NSManagedObject subclass files. However, depending on your situation, you may not even need to generate the NSManagedObject subclasses.
Below are more details on the entity Codegen options based my review of Apple's documentation, the Apple developer's forum and testing with my own project.
Option 1: "Class Definition"
Think of this as the "plug and play" option
Use the model editor to create the entities and associated attributes that you want Core Data to manage.
Do not use the NSMangagedObject subclass generator. The required files are automatically generated for you by Xcode (however they do not show up in your project navigator).
If you do generate the NSManagedObject files, Apple tells you that these files should not be edited in the header comments of said files. If you do need to edit these files, then this is good sign that you need to use another Codegen option.
Leave the default Class options for your entity (Module = Global Namespace and Codegen = Class Definition)
If you need to override methods of the NSManagedObject, you can create an extension using the Name under the Class option.
// Optional extension in Entity.swift extension Entity { // Override NSManagedObject methods }
Options 2: "Manual/None"
Similar to Option 1, except that you can see and edit the NSManagedObject subclass files.
Use the model editor to create the entities and associated attributes that you want Core Data to manage.
Before using the NSManagedObject subclass generator, set the Codgen option to "Manual/None" for the entity. The Module option should be Global Namespace.
After you add/remove/update an attribute, you have two choices: (1) Manually update the NSManagedObject files that were generated for you OR (2) Use the NSManagedObject subclass generator again (this will only update the Entity+CoreDataProperties.swift file).
Again, if you need to override and methods from NSManagedObject, you can create an extension. The extension should be created in the Entity+CoreDataClass.swift file and not the Entity+CoreDataProperties.swift file (this file could be updated due to model editor changes).
// Optional extension in Entity+CoreDataClass.swift extension Entity { // Override NSManagedObject methods }
Option 3: "Category/Extension"
Use this option if you have custom properties that do not need to be managed by Core Data.
Use the model editor to create the entities and associated attributes that you want Core Data to manage.
Ensure the Module option is set to Current Product Module and the Codegen option is set to "Category/Extension".
Create your own NSManagedObject subclass with the properties that you will self manage.
Do not use the NSMangagedObject subclass generator. The required files are automatically generated for you by Xcode (however they do not show up in your project navigator).
// Subclass NSManagedObject in Entity.swift class Entity: NSManagedObject { // Self managed properties }
// Optional extension in Entity.swift extension Entity { // Override NSManagedObject methods }
You can try these steps
- Select the .xcdatamodeld file in Xocde Project Navigator
- In the Data Modul Inspector, make sure Codegen : Manual/None
- Then Edit -> Create NSManagedObject Subclass
- Clean product and rebuild
Is that work? If not
Make sure you all class has not the same name with Entities. You can find these class in Build Phases -> Compile Sources. Rename the class or Entities if they duplicated
Or
You can run this command to in your project folder to get more error info
xcodebuild -verbose
I got this message when i have this problem
duplicate symbol _OBJC_CLASS_$_RandomList in:
xxxx/RandomList.o
xxxx/RandomList+CoreDataClass.o
RandomList.h and RandomList+CoreDataClass.h have a same symbol when compiling
I think that why Xcode did not warn you, but Compiler will throw error
Hope this will help you
Delete the 3rd import
statement because it's empty.
Note: I don't know why this happens but I guess it's a bug in Xcode 8. Just delete it and it will work fine.
I just had a problem where I just added a Person entity in my model to the Core Data template. Then generated the NSManagedObject subclass for for that and it won't compile, giving me a Linker Error. Turns out I am supposed to change the Codegen option to Manual/None to make it work (see bottom-right part of the picture).
I think it is a xcode issue, where xcode generates wrong syntax for core data category class.
I am creating a nsmanageobjectsubclass
for one entity AgentDetails
Here xcode create wrong code structure in AgentDetails+CoreDataClass.h
and AgentDetails+CoreDataClass.m
. Those have a code structure like:
And
So it is having duplicate interface issue as AgentDetails.h
have same interface.
Now to fix this you have to change the code in AgentDetails+CoreDataClass.h
and AgentDetails+CoreDataClass.m
like this:
In Data Model Inspector select Current Product Module under 'Module' and Manual/None under 'Codegen'. (This allows you to edit subclass files and to regenerate CoreDataProperties.swift when you modify your attributes under the same entity.)
You can then choose Create NSManagedObjectSubclass under Editor menu. Xcode will create 2 files for you YourEntity+CoreDataClass.swift and YourEntity+CoreDataProperties.swift. Notice if you don't have the latest Xcode (8.2.1), any optional/nonoptional properties that you set in your Model Inspector will not show up correctly. You can edit in YourEntity +CoreDataProperties.swift file.
Xcode 8.1 seems to be generating Model Class internally. Just delete the 2 classes created and you will still be able to use the entities in your code.
Here's the error message I was receiving
<unknown>:0: error: filename "Recipe+CoreDataProperties.swift" used twice: '/Users/Rick/Desktop/Devslop/Rick Recipe/Recipe+CoreDataProperties.swift' and '/Users/Rick/Library/Developer/Xcode/DerivedData/Rick_Recipe-cctgjudvqobxlwetbcwmzrgxigwg/Build/Intermediates/Rick Recipe.build/Debug-iphonesimulator/Rick Recipe.build/DerivedSources/CoreDataGenerated/Rick_Recipe/Recipe+CoreDataProperties.swift'
<unknown>:0: note: filenames are used to distinguish private declarations with the same name
Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1
Also, if you add NSManagedObject subclass yourself, don't forget to follow the following step: Go to '.xcdatamodeld' -> Choose the entity -> Show data model inspector -> Codegen -> Choose 'Manual/None'
This worked for me.
I found this Post from David Atkinson which is helpful in some way. If I generate the code the way David described. I just get the code with some Syntax errors and if I fix the errors everything works like before. There are no missing files starting with '.' any more.
The syntax errors i Have to correct are - the unnecessary import - and some public properties which are not intended to be public in my code
I am running the latest Xcode 8.1 beta (8T47) build.
According to the error log (see below), two copies of the autogenerated files are created. One copy is put in your Xcode project folder (the one visible in your directory on the left hand side toolbar of Xcode), and a second copy is created in your DerivedData folder for your project:
/Users/<your name>/Library/Developer/Xcode/DerivedData/<your app>-axhtnodotznxnrenefflktnxfeal/Build/Intermediates/<your app>.build/Debug-iphonesimulator/<your app>.build/DerivedSources/CoreDataGenerated/<your app>/<class name>+CoreDataProperties.swift
/Users/<your name>/Library/Developer/Xcode/DerivedData/<your app>-axhtnodotznxnrenefflktnxfeal/Build/Intermediates/<your app>.build/Debug-iphonesimulator/<your app>.build/DerivedSources/CoreDataGenerated/<your app>/<class name>+CoreDataClass.swift
Deleting the copies in your Xcode project directory will fix all issues, but proves pointless as you can no longer edit these files...
I wouldn't say this is a solution, rather just a half-assed way to get the project to build. Hopefully this bug will be addressed soon.
For me, I created CocoaTouch classes by subclassing of NSManagedObject
manually. I set the module as Current Product Module and Codegen as Category/Extension and it works well.
In my particular case, I had added CoreData to an existing project which already had a Model class by the same name as my entity. Deleting the old Model class fixed the problem, as its type was colliding with the new CoreData Entity class.
I'm putting my grain of salt given that I can see a lot of answers that solve the problem but are lacking the real reason behind what's really happening here.
I stumbled upon this very same issue and by doing a quick research I was able to find that:
Until Xcode 7, the default behavior for a Core Data entity was that the developer had to manually create and maintain the changes of the corresponding NSManagedObject subclasses. (This could, and still can be accomplished by making use of the editor menu selecting the "Create NSManagedObject subclass.." option).
Starting from Xcode 8, Apple has included a new setting right in the Data Model Inspector named Codegen to manage and maintain the NSManagedObject subclasses. The default value for this setting is "Class Definition" which tells Xcode to generate the NSManagedObject subclasses based on our defined entities in compile time and put them in the derived data folder.
Having our NSManagedObject subclasses within the project + the ones Xcode automatically generates lead us to the real reason behind the "Multiple commands produce..." compiling time error as we now have duplicated managed objects models!!!
The solution then is to use either one or another, not both! I personally prefer to have my managed object models within the project so I have changed this "Codegen" setting to "Manual/None". If you are not adding logic to the models I bet you could opt by removing your project's managed object models and let Xcode do its thing based on the "Class Definition" value for the mentioned setting. This is the right way to deal with this issue.
You can find a great article explaining all of this in detail here:
https://medium.com/@kahseng.lee123/core-data-codegen-explained-462c30341041
What you need to do is set the CodeGen to Category/Extension before you execute the Create NSManagedObject subclasses.
I have a Flights Entity and these settings in the Data Model Inspector worked for me :
Set the Name to nothing(You will see some grayed out text of "NSManagedObject"). The default will be written as "Flights" just remove that.
Nothing in the module."Global Namespace" greyed out is what you will see.
Codegen to Manual/None.
Then Goto Editor -> Create NSManagedObject Subclass to create the swift files
Rename the Flights+CoreDataClass.swift to just Flights.swift
Here's the link to the Screenshot(For some reason imgur was rejecting it :( ) https://drive.google.com/file/d/0B8a3rG93GTRedkhvbWc5Ujl4Unc/view?usp=sharing
After I renamed the following:
From: YourEntity+CoreDataClass.swift To: YourEntity.swift
and
From: YourEntity+CoreDataProperties.swift To: YourEntityCoreDataProperties.swift
then it works. It looks like "+" is causing the problem.
来源:https://stackoverflow.com/questions/39657231/xcode-8-generates-broken-nsmanagedobject-subclasses-for-ios-10