52

Update for Xcode 8:

In Xcode 8, one needs to go to the Core Data Model Editor and Show the File Inspector. Near the bottom is an option for code generation. Select Swift.

Edit: I found the solution to generate a Swift model from Core Data entity:

On Xcode:

Editor > Create NSManagedOjbect > Click button "Next" > Click button "Next" > Select "Swift" Langage > Click button "Create"


I tried Swift langage by creating a new Swift project on Xcode 6 beta using Core Data.

When I generate my models from my Core Data's entities, Xcode creates Objective-C models.

Is there a way to generate Swift model rather than Obejctive-C model with Core Data ?

Thanks !

Tommie C.
  • 12,895
  • 5
  • 82
  • 100
Jean Lebrument
  • 5,079
  • 8
  • 33
  • 67

7 Answers7

32

Lets have a look on the Objective-C way:

Person.h (Header-File)

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@interface Person : NSManagedObject
@property (nonatomic, retain) NSString *name;
@end

Person.m (Implementation-File)

#import "Person.h"

@implementation Person
@dynamic name;
@end

Swift

The documentation already included in Xcode6-Beta says:

Core Data provides the underlying storage and implementation of properties in subclasses of the NSManagedObject class. Add the @NSManaged attribute before each property definition in your managed object subclass that corresponds to an attribute or relationship in your Core Data model. Like the @dynamic attribute in Objective-C, the @NSManaged attribute informs the Swift compiler that the storage and implementation of a property will be provided at runtime. However, unlike @dynamic, the @NSManaged attribute is available only for Core Data support.

So that is how I would rewrite the above example for Swift (not tested):

Person.swift

import CoreData

class Person: NSManagedObject {

    @NSManaged var name : NSString

}

And according to your question I think the subclass-generation-feature might be not included in Xcode6 yet. Did you made sure that you have chosen "Swift" as programming language when you were creating the Cocoa-Project in Xcode?

Jonathon Horsman
  • 2,303
  • 1
  • 20
  • 18
Dennis Zoma
  • 2,621
  • 2
  • 17
  • 27
  • Thanks for your answer and yes I checked, I chose the Swift langage when I created my project. – Jean Lebrument Jun 04 '14 at 07:30
  • 2
    Yes, I can confirm that the subclass generation feature is not included for swift in this version of Xcode. – Sammio2 Jun 07 '14 at 09:39
  • 1
    `import Cocoa` generated the error "No such module 'cocoa'" for me. I switched it to `import CoreData` and it was happy with that. – Fls'Zen Jun 07 '14 at 19:56
  • You can't import Cocoa from iOS. You are developing for iOS, right? – Dennis Zoma Jun 07 '14 at 19:58
  • 5
    Note: To use this example you must put @objc(Person) before class. Otherwise any attempt to access a Person instance will result in a crash. Thanks for the answer! – hatunike Jun 24 '14 at 23:34
  • 3
    FYI, Xcode 6 beta 3 allows auto-creation of managed-object subclasses (although annoyingly the default is Objective-C, even in a Swift project) – davidf2281 Jul 14 '14 at 11:10
  • Xcode Version 6.1.1 full supported, select your .xcdatamodeld Editor->create NSManagedObject Subclass ... – iluvatar_GR Jan 08 '15 at 17:34
12

You can get Swift model back using NSEntityDescription.insertNewObjectForEntityForName but you must edit your core data model file and not use Person as a Class Entity but <ProjectName>.Person else it returns NSManagedObject...

Using println() you won't see Person instance but something like <_TtC5ProjectName4Person: 0xc9ad5f0> but calling methods on this will prove it's a Person instance for real. I guess it's just the way for Swift to generate unique class names, not conflict and CoreData methods show this internal mechanism.

The Apple documentation says:

Swift classes are namespaced—they’re scoped to the module (typically, the project) they are compiled in. To use a Swift subclass of the NSManagedObject class with your Core Data model, prefix the class name in the Class field in the model entity inspector with the name of your module.

Richard Hulse
  • 10,383
  • 2
  • 33
  • 37
Fabien Penso
  • 341
  • 2
  • 8
  • Arg that had me stumped... Is this documented anywhere? I feel as though this is likely to change before release – Stephen Groom Jul 06 '14 at 16:59
  • I use this method - decorating the class name with the project name - and that works from for running the app, but my Tests that use core data throw an invalid cast method. Any work around for that? – Daniel D Jul 09 '14 at 22:30
  • @DanielD did you find the solution for the casting problem in your test target? Cause that's what I'm struggling with right now... – Goodsquirrel Jun 10 '15 at 19:01
  • @Fabien Penso Can you create example project on Github? – Shmidt Dec 05 '15 at 19:50
11

According to Apple's video regarding What's new In CoreData frame: 38mins (WWDC2014 Session 225), in inspector's Data Model, prefix the class name with the project name. Like projectName.Doctor

I've tried this but what will happen is that the generated managed object class becomes: projectName.swift instead of Doctor.swift. Even the class declaration becomes class projectName: ManagedObject

Solution:

In Data model inspector, just specify the Name & Class of your object to what name you want, example: Doctor

After you generated an object model and selecting Swift, this will create a file (Doctor.swift).

Now, when inserting new records in Core Data, you might an experience error "Class not found, using default NSManagedObject instead" even if you cast the newly inserted object to a correct object name.

To solve this, you just need to add @objc(class name) above the class declaration. See sample below.

import Foundation
import CoreData

@objc(Doctor)
class Doctor: NSManagedObject {
    @NSManaged var name: String
}

Then:

let doctorManagedObject = NSEntityDescription.insertNewObjectForEntityForName("Doctor", inManagedObjectContext: context) as Doctor
doctorManagedObject.name = "John" // you can now use dot syntax instead of setValue

Save context to commit insert.

Zaldy Bughaw
  • 797
  • 8
  • 16
3

I tested @NSManaged, it didn't work. :( . But mixed models files(.h) generated by xcdatamodel, it succeed. please read the doc and code in https://github.com/iascchen/SwiftCoreDataSimpleDemo

IascCHEN
  • 69
  • 4
3

Alternatively, you can just add #import "Person.h" to the bridging header, Project-Bridging-Header.h that Xcode generates for you (if you accepted it's offer to generate). Then you can use all the auto-generated Obj-C as if it were native Swift.

JefferyRPrice
  • 895
  • 5
  • 17
3

Editor -> Create NSManagedObject Subclass works fine for Swift

Simply go through all the usual steps, but when you get to creating the files, choose Language 'Swift' if it's the first time you've used Create NSManagedObject Subclass with a Swift project it'll be defaulting to Objective C

Magoo
  • 2,552
  • 1
  • 23
  • 43
2

For XCode 12.

You can change generating model language. enter image description here

Viktor
  • 1,155
  • 14
  • 23