2

I was wondering if someone could explain the concept of "cast" or "casting" to me regarding programming and also help me with the issue of getting "Swift dynamic cast failed" when trying to execute this code:

import UIKit
import CoreData

class vcMain: UIViewController {
    
    @IBOutlet var txtUsername: UITextField!
    @IBOutlet var txtPassword: UITextField!
    
    @IBAction func btnSave(){
        //println("Save button pressed \(txtUsername.text)")//Adds the text written, in the console
        var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
        var context:NSManagedObjectContext = appDel.managedObjectContext
        
        var newUser = NSEntityDescription.insertNewObjectForEntityForName("Users", inManagedObjectContext: context) as NSManagedObjectContext
        newUser.setValue("Test Username", forKey: "username")
        newUser.setValue("Test Password", forKey: "password")
        
        context.save(nil)
        
        println(newUser)
        println("Object Saved.")
        
        
    }
    
    @IBAction func btnLoad(){
        //println("Load button pressed \(txtPassword.text)")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

I'm following a tutorial on YouTube but cant figure out why its not working for me!

Nimantha
  • 6,405
  • 6
  • 28
  • 69

3 Answers3

7

This line looks wrong:

var newUser = NSEntityDescription.insertNewObjectForEntityForName("Users", inManagedObjectContext: context) as NSManagedObjectContext

You're casting to a NSManagedObjectContext when you probably meant to cast to a NSManagedObject, so the line should be:

var newUser = NSEntityDescription.insertNewObjectForEntityForName("Users", inManagedObjectContext: context) as NSManagedObject
Jack Lawrence
  • 10,664
  • 1
  • 47
  • 61
  • Can you help me with this please? : http://stackoverflow.com/questions/28042105/swift-dynamic-cast-failed-swift-dynamiccastclassunconditional – Nate Uni Jan 21 '15 at 04:06
2

I agree with Jack Lawrence's answer.

We are looking at the function NSEntityDescription.insertNewObjectForEntityForName("Users", inManagedObjectContext: context) which, from the documentation, will return a objC type, id, which kinda translates to Swift as an AnyObject. This is to say the computer doesn't know what it is, but we do, because we read the documentation:

insertNewObjectForEntityForName:inManagedObjectContext: Creates, configures, and returns an instance of the class for the entity with a given name.

Return Value A new, autoreleased, fully configured instance of the class for the entity named entityName. The instance has its entity description set and is inserted it into context.

Anyway, you can be safe to assume it is returning a type NSManagedObject, or some subclass of it.

Now about casting:

Most of this is from the Swift iBook. So you already know that type casting / downcasting in swift is done by the as operator. Because downcasting can fail, the type cast operator comes in two forms. 1) Forced as and 2) Optional as?

Basically the differnce is, use as? when you are not sure if the downcast will succeed, and use as when you are certain it will. Here is an example, where I have an array of type AnyObject called Vehicles..., which contains two different classes, Car and Truck, of which there are 5 cars and 2 trucks.

var carCount = 0
var truckCount = 0
for vehicle in vehicles{
    if let car = car as? Car
    {
        carCount++
    } else
    if let truck = truck as? Truck
    {
        truckCount++
    }
}

At the end of this my counts are correct, and I have not thrown an error. But, trying to access any one of the elements of vehicles, like vehicles[i] as Car would be dangerous, because it might be a truck, and you are forcefully saying that it is a car. Runtime error!

Anyway I hope that explains it a bit. If not, check out the chapter on type casting in the Swift iBook, page 391.

Ethan
  • 1,567
  • 11
  • 16
0

For anyone else out there with a similar problem. There is a little gotcha here.

If you are trying to generate a custom NSManagedObject subclass using the NSEntityDescription.insertNewObjectForEntityForName(Entity, inManagedObjectContext: context) method, then make sure that the swift class has the @objc() header added to the class. Otherwise you'll encounter a dynamic class cast failure also.

user2294382
  • 871
  • 3
  • 11
  • 25
  • You don't need to use the `@objc` attribute here. See "Implementing Core Data Managed Object Subclasses" in https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/WritingSwiftClassesWithObjective-CBehavior.html#//apple_ref/doc/uid/TP40014216-CH5-XID_55 – Jack Lawrence Sep 14 '14 at 17:11