2
votes

Ok, just starting to look at Swift and trying to use a Coredata model and SQLfile from an existing Obj-C program.

  • Created new swift Coredata project
  • replaced the coredata model with the existing model
  • pointed program to sql data file
  • Created Swift NSMangagedObject Subclass

Run program, get an error that class types don't match.

  • Remove Swift NSMangedObject Subclass and created Objective-C version

Run program, no issues, fetch executes nicely.

I want to eventually rewrite the program in swift, but I'll have to deal with old SQL data files. Is there a way to get this to work without having to blend the two languages?

I have not tried this, but is this something lightweight migration would do?

-[EDIT]---

Error message is in console:

"fatal error: NSAarry element failed to match the Swift Array Element type"

fetch Code:

 let request = NSFetchRequest(entityName: "Account")
 var error:NSError?=nil
 var fetchResults = managedObjectContext?executeFetchRequest(request, error: &error)! as [Account]

 for aAccount in fetchResults {
 println(aAccount.name)
 }

This code does works - IF the NSManagedObject Subclass (Account) IS Obj-C

This code does NOT work - IF the NSManagedObject subclass (Account) IS Swift - This is when I get the error.

The NSManagedObject Subclass is generated through "Create NSMangedObject Subclass" in XCode.

The CoreData Model and the SQL data file are from a previous, functioning, program when 100% Obj-C.

-[EDIT 2]-------

Unless I did something wrong, it is type cased...

 var fetchResults = ...(request, error: &error)! as [Account]

To test, I changed the above to:

 var fetchResults = ...(request, error: &error)! as [NSManagedObject] 

with this change the following works - as you would expect:

 for aAccount in fetchResults {

        println(aAccount.valueForKey("name")!)     
 }

The following DOES NOT work (added it inside the for-in loop):

 if let account = aAccount as? Account {
            println(account.name)
 }

So, it will NOT let me cast to the Swift Account Class. I used Xcode's "Create ManagedObject Subclass" to create the Swift subclass.

-[EDIT 3]-----

XCode Version: 6.1

Account.swift file:

 import Foundation
 import Coredata

 class Account: NSManagedObject {

 @NSManaged var name: String
 @NSManaged var number: String
 @NSManaged var type: String
 @NSManaged var status: String

 }

If I create an Obj-C version of Account (Account.h and Account.m), add them to the Bridging-Header, remove the .swift version, everything works.

1
Please give more info. Code. Compiler Error Messages. etc... - Darko
What I immediately noticed is that your class name is Accout but your entity name is Account (note the missing 'n') - David Berry
typo when putting it into SO, was on two different computers, so I couldn't cut-n-paste - Spelling is correct in program. - littleDrummerBoy

1 Answers

0
votes

You need to cast the NSManagedObject in fetchedResults to your Swift class in order to access the properties of the Swift class directly.

for aAccount in fetchResults {
 println(aAccount.name)   // NOT GOING TO WORK
 } 

aAccount will be a NSManagedObject so you must cast this to your Swift class in order to access it's property via the Swift class (aAccount.name). Otherwise you have to access the property like this

aAccount.getValueForKey("Name")

Alternately try this

for managedObject in fetchResults {
 if let account = managedObject as? Account {
     println(account.name)   
  }
 } 

Here is one of my Swift model classes, try adding the @objc()

import Foundation
import CoreData

@objc(AssetX)
class AssetX: BaseNode {

    @NSManaged var childCostTotal: NSNumber
    @NSManaged var dateOfManufacture: NSDate
    @NSManaged var dateOfPurchase: NSDate
    @NSManaged var dateOfValuation: NSDate
    @NSManaged var invoice: NSAttributedString
    @NSManaged var make: String
    @NSManaged var model: String
    @NSManaged var photo: NSAttributedString
    @NSManaged var purchaseCost: NSNumber
    @NSManaged var serialNo: String
    @NSManaged var valuationCost: NSNumber
    @NSManaged var category: AssetCategory
}

The base class is:

import Foundation
import CoreData

@objc(BaseNode)
class BaseNode: NSManagedObject {

    @NSManaged var canCollapse: NSNumber
    @NSManaged var canExpand: NSNumber
    @NSManaged var details: NSAttributedString
    @NSManaged var displayName: String
    @NSManaged var isExpanded: NSNumber
    @NSManaged var isLeaf: NSNumber
    @NSManaged var isSelectable: NSNumber
    @NSManaged var isSpecialGroup: NSNumber
    @NSManaged var reminderDate: NSDate
    @NSManaged var reminderPeriod: String
    @NSManaged var sortIndex: NSNumber
    @NSManaged var status: NSNumber
    @NSManaged var children: NSSet
    @NSManaged var linkedTo: People
    @NSManaged var parent: BaseNode

    var found:Bool = false

}