簡體   English   中英

嘗試保存核心數據對象時出錯

[英]Error when trying to save Core Data objects

我一直在嘗試建立一個看起來應該是這樣的簡單應用程序,該應用程序允許用戶使用價格更新食品並存儲找到價格的地方。 我知道的主要問題是,即使Apple尚未解決Swift的缺點,並且仍在不斷變化中,它仍試圖將Swift與Objective-C融合在一起。

無論如何,我已經如下設置了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).'

我究竟做錯了什么?

錯誤消息表明“名稱”,“商店”和“價格”是您的Core Data實體的String屬性,但是您已將它們定義為[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生成托管對象子類(Xcode菜單中的編輯器->創建NSManagedObject子類...)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM