尝试保存Core Data对象时出错

时间:2014-10-28 20:04:06

标签: ios objective-c core-data swift

我一直在尝试设置一个简单的应用程序,它允许用户以价格更新食品并存储价格。我知道的主要问题是试图将Swift与 Objective-C 融合在一起,尽管Apple还没有解决Swift的问题,而且它一直在变化。

无论如何,我已将AllowedTableViewController设置如下

class AllowedTableViewController: UITableViewController {

    var myAllowedList : Array<AnyObject> = []

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewDidAppear(animated: Bool) {

        let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        let context: NSManagedObjectContext = appDel.managedObjectContext!
        let freq = NSFetchRequest(entityName: "FoodAllowed")

        myAllowedList = context.executeFetchRequest(freq, error: nil)!
        tableView.reloadData()
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        if segue.identifier == "update" {

            var indexPath: NSIndexPath = self.tableView.indexPathForSelectedRow()!
            var selectedItem: NSManagedObject = myAllowedList[indexPath.row] as NSManagedObject
            let IVC: AllowedViewController = segue.destinationViewController as AllowedViewController

            IVC.name = selectedItem.valueForKey("name")as String
            IVC.store = selectedItem.valueForKey("store")as String
            IVC.price = selectedItem.valueForKey("price")as String
            IVC.existingItem = selectedItem
            }
    }

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

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // #warning Potentially incomplete method implementation.
        // Return the number of sections.
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete method implementation.
        // Return the number of rows in the section.
        return myAllowedList.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        //Configure the Cell

        let CellID: NSString = "Allowed"

        var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(CellID) as UITableViewCell


        var data: NSManagedObject = myAllowedList[indexPath.row] as NSManagedObject
            cell.textLabel.text = (data.valueForKeyPath("name")as String)

        var pri = data.valueForKeyPath("price")as String
        var str = data.valueForKeyPath("store")as String
        cell.detailTextLabel?.text = "\(pri) name/s - \(str)"
        return cell
    }

    //Override to support conditional editing of the table view
    override func tableView(tableView: UITableView?, canEditRowAtIndexPath indexPath: NSIndexPath?) -> Bool {
        //Return NO if you do not want the specified item to be editable
        return true
    }

    //Override to support editing the table view
    override func tableView(tableView: UITableView?, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath?) {

        let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        let context: NSManagedObjectContext = appDel.managedObjectContext!

        if editingStyle == UITableViewCellEditingStyle.Delete {

            if let tv = tableView {
            context.deleteObject(myAllowedList[indexPath!.row] as NSManagedObject)
            myAllowedList.removeAtIndex(indexPath!.row)
            tv.deleteRowsAtIndexPaths([indexPath!.row], withRowAnimation: UITableViewRowAnimation.Fade)
            }

            var error: NSError? = nil
            if !context.save(&error) {
                abort()
            }
        }       
    }
}

视图控制器中的用户可编辑文本字段代码如下。

{

class AllowedViewController: UIViewController {

    @IBOutlet var textFieldname: UITextField!
    @IBOutlet var textFieldstore: UITextField!
    @IBOutlet var textFieldprice: UITextField!


    var name: String = ""
    var store: String = ""
    var price: String = ""

    var existingItem: NSManagedObject!

    override func viewDidLoad() {
        super.viewDidLoad()

        if existingItem == nil {
            textFieldname.text = name
            textFieldstore.text = store
            textFieldprice.text = price

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

    func saveTapped(sender: AnyObject) {

        //Reference to our app delegate

        let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate

        //Reference NS Managed Object Context

        let contxt: NSManagedObjectContext = appDel.managedObjectContext!
        let en = NSEntityDescription.entityForName("FoodAllowed", inManagedObjectContext: contxt)!
         //Check if item exists

        if (existingItem != nil) {
            existingItem.setValue(textFieldname.text as String, forKey: "name")
            existingItem.setValue(textFieldstore.text as String, forKey: "store")
            existingItem.setValue(textFieldprice.text as String, forKey: "price")

        }else {

        //Create instance of pur data model and intialize

        var newItem = DataModel(entity: en, insertIntoManagedObjectContext: contxt)

        //Map our properties

        newItem.name = [textFieldname.text]
        newItem.store = [textFieldstore.text]
        newItem.price = [textFieldprice.text]


        //Save our content

        contxt.save(nil)
        println(newItem)

        //Navigate back to root view controll

        self.navigationController?.popToRootViewControllerAnimated(true)
        }
    }

     func cancelTapped(sender: AnyObject) {

        //Navigate back to root view controll

        self.navigationController?.popToRootViewControllerAnimated(true)
       }

      override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        // Dispose of any resources that can be recreated.
        }
   }

}

我的NSManaged DataModel是

{

@objc(DataModel)
class DataModel: NSManagedObject {

    //properties feeding the attributes in our entity
    //must match the entity attributes

    @NSManaged var name: [String]
    @NSManaged var store: [String]
    @NSManaged var price: [String]

}

}

当我在模拟器中运行应用程序时,我收到以下错误

'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "name"; desired type = NSString; given type = Swift._NSSwiftArrayImpl; value = (Apples).'

我做错了什么?

1 个答案:

答案 0 :(得分:1)

错误消息表明&#34; name&#34;,&#34; store&#34;和&#34;价格&#34;是 String 属性 您的Core Data实体,但您已将它们定义为[String],即数组 字符串。它应该是

@objc(DataModel)
class DataModel: NSManagedObject {

    @NSManaged var name: String
    @NSManaged var store: String
    @NSManaged var price: String

}

因此

newItem.name = textFieldname.text // not: [textFieldname.text]
// ...

更好的是,让Xcode生成托管对象的子类 (编辑器 - &gt;在Xcode菜单中创建NSManagedObject子类...)。