Swift and CoreData / Data Storage
Solution 1
This is how I implemented core data.
A couple of really important notes:
-
You have to add this to your NSManagedObject class:
@objc(MyObject)
You have to add the entity name to your default configuration class in the .xcdatamodel (picture included)
-
You can't simply make an NSManagedObject.
var myObject : MyObject = MyObject()
You have to do this:
let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context: NSManagedObjectContext = appDelegate.managedObjectContext
let entityName: String = "MyObject"
let myEntityDescription = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context)
var myObject = MyObject(entity: myEntityDescription, insertIntoManagedObjectContext: context)
Here is my NSManagedObject. I included two fetch methods as well as a class method for object construction. You may notice that I am taking advantage of the new enum system so that I can easily access my entity names and entity attributes
import UIKit
import CoreData
enum MyObjectPropertyList {
case name
func description() -> String {
switch self {
case .name:
return "name"
}
}
}
@objc(MyObject)
class MyObject: NSManagedObject {
@NSManaged var name: String
//
//// CREATE CLASS OBJECT
//
class func createMyObject (propertyName:MyObjectPropertyList, value:String, context: NSManagedObjectContext) -> MyObject? {
if !value.isEmpty {
let propertyType = propertyName.description()
let entityName = "MyObject"
let request : NSFetchRequest = NSFetchRequest(entityName: entityName)
request.returnsObjectsAsFaults = false
request.predicate = NSPredicate(format: "\(propertyType) = %@", value)
var error: NSError? = nil
var matches: NSArray = context.executeFetchRequest(request, error: &error)
if (matches.count > 1) {
// handle error
return matches[0] as? MyObject
} else if matches.count == 0 {
let entityDescription = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context)
var myObject : MyObject = MyObject(entity: entityDescription, insertIntoManagedObjectContext: context)
myObject.name = value
return myObject
}
else {
println(matches[0])
return matches[0] as? MyObject
}
}
return nil
}
}
//
//// FETCH REQUESTS
//
func myGeneralFetchRequest (entity : CoreDataEntities,
property : MyObjectPropertyList,
context : NSManagedObjectContext) -> AnyObject[]?{
let entityName = entity.description()
let propertyName = property.description()
let request :NSFetchRequest = NSFetchRequest(entityName: entityName)
request.returnsObjectsAsFaults = false
let sortDescriptor : NSSortDescriptor = NSSortDescriptor(key: propertyName, ascending: true)
request.sortDescriptors = [sortDescriptor]
var error: NSError? = nil
var matches: NSArray = context.executeFetchRequest(request, error: &error)
if matches.count > 0 {
return matches
}
else {
return nil
}
}
func myNameFetchRequest (entity : CoreDataEntities,
property : MyObjectPropertyList,
value : String,
context : NSManagedObjectContext) -> AnyObject[]? {
let entityName = entity.description()
let propertyName = property.description()
let request :NSFetchRequest = NSFetchRequest(entityName: entityName)
request.returnsObjectsAsFaults = false
request.predicate = NSPredicate(format: "\(propertyName) = %@", value)
let sortDescriptor :NSSortDescriptor = NSSortDescriptor(key: propertyName, ascending: true)
request.sortDescriptors = [sortDescriptor]
var error: NSError? = nil
var matches: NSArray = context.executeFetchRequest(request, error: &error)
if matches.count > 0 {
return matches
}
else {
return nil
}
}
//
//// PRINT FETCH REQUEST
//
func printFetchedArrayList (myarray:AnyObject[]) {
if myarray.count > 0 {
println("Has \(myarray.count) object")
for myobject : AnyObject in myarray {
var anObject = myobject as MyObject
var thename = anObject.name
println(thename)
}
}
else {
println("empty fetch")
}
}
Here is my view controller
import UIKit
import CoreData
enum CoreDataEntities {
case MyObject
func description() -> String {
switch self {
case .MyObject:
return "MyObject"
}
}
}
class ViewController: UIViewController {
//
//// MOC
//
var managedObjectContext : NSManagedObjectContext = NSManagedObjectContext()
//
//// Text Field
//
@IBOutlet var myTextField : UITextField
//
//// BUTTONS
//
@IBAction func saveButtonPress(sender : UIButton) {
makeEntityAction()
}
@IBAction func fetchButtonPress(sender : UIButton) {
fetchObjectAction()
}
//
//// ACTIONS
//
func makeEntityAction () {
println("-- Make action --")
let value:String = self.myTextField.text
var myObject : MyObject = MyObject.createMyObject(MyObjectPropertyList.name, value : value, context: self.managedObjectContext)!
saveContext(self.managedObjectContext)
}
func fetchObjectAction () {
println("-- Fetch action --")
if let myTotalarray = myGeneralFetchRequest(CoreDataEntities.MyObject, MyObjectPropertyList.name, self.managedObjectContext) {
printFetchedArrayList(myTotalarray)
}
if let mySinglearray: AnyObject[] = myNameFetchRequest(CoreDataEntities.MyObject, MyObjectPropertyList.name, "Bill", self.managedObjectContext) {
println("(-- --)")
printFetchedArrayList(mySinglearray)
}
}
//
//// LOAD & SAVE
//
func loadContext () {
let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context: NSManagedObjectContext = appDelegate.managedObjectContext
self.managedObjectContext = context
}
func saveContext (context: NSManagedObjectContext) {
var error: NSError? = nil
context.save(&error)
}
//
//// LOAD
//
func myLoad () {
loadContext ()
println("Loaded Context")
}
//
//// Life Cycle
//
override func viewDidLoad() {
super.viewDidLoad()
myLoad ()
}
}
Solution 2
All Objective-C frameworks are swift-ready. Swift-friendly headers are automatically generated (on-demand, it appears), and you can access anything from Swift that you can from ObjC.
Solution 3
I had tested use swift to access coredata, please visit the demo code : https://github.com/iascchen/SwiftCoreDataSimpleDemo .
Solution 4
If you wanna have a play around with Swift and CoreData, I've written a framework thats an Active Record style assistant to CoreData.
(note: not a shameless plug :) i actually thought this would be useful for the user).
DanielAsking
Updated on January 08, 2020Comments
-
DanielAsking over 4 years
I'm just learning Objective-C / Cocoa Touch and Core Data. So, what are the new possibilities to implement data storage in iOS App Projects that are written in pure Swift? I really like the language, but as far as I know all core data methods are written in Objective-C. So will the core data classes/methods converted to Swift-Code automatically or will we have to mix up Objective-C Code for Core data and Swift-Code for everything else?
-
Lucas almost 10 yearsWhere can we find the headers? Like the equivalent of the documentation in obj-c.
-
rickster almost 10 yearsLook in the Reference Library. All the docs show both Swift and ObjC syntax for using an API. Look at Using Swift with Cocoa and Objective-C for more info on how to mix languages, and see the
@NSManaged
attribute in particular for working with Core Data. -
Wizard of Kneup almost 10 yearsDo I understand your file correctly? You do not have a working demo?
-
Pirijan almost 10 yearsIt is certainly unclear, but running the demo myself it does seem to work. It looks like @IascCHEN uses autogenerated Obj-C NSManagedObject subclass files rather than a Swift only solution (which I'd prefer)
-
Quaternion almost 10 yearsPreserved comment left in message by user William: You will need to ensure that the text-field is not nil, in addition to that the object you retrieve actually has a name-field. This can be done in conventional if-sentence ways. An example includes: var value:String="default" if(self.myTextField.text != nil) { value=self.myTextField.text }
-
IascCHEN over 9 yearsAfter Xcode 6 beta 3, you can generate swift NSManagedObject, but you should add @objc in the swift code. please check the member.swift file. U can check the running progress from log.