2014-10-28 60 views
0

我一直在尝试设置,看起来应该是什么,一个简单的应用程序允许用户使用价格更新食品和存储价格的地方。我知道的主要问题是试图将Swift与Objective-C混合,尽管苹果还没有找到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

错误消息指出,“名”,“存储”和“价格”是字符串性能的核心数据实体的 ,但你让他们定义为[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的生成被管理对象的子类 (编辑 - >创建NSManagedObject子类......在Xcode菜单)。

+0

使用Swift核心数据确保非可选项总是合适的吗?当然,声明为'可选'的核心数据属性应该有一个Swift可选类型aka'?'。关于什么 '!'是否需要其他类型? (因为awakeFromNIB过程对于IBOutlets而言) – GoZoner 2014-10-28 22:21:38

+0

@GoZoner:不幸的是,Xcode确实(仍然)不会为可选属性生成正确的代码,您必须添加!要么 ?手动。比较http://stackoverflow.com/questions/25661120/check-if-property-is-set-in-core-data。 – 2014-10-29 06:17:11

+0

非常感谢你的工作!在评论时一定错过了! – jmuir31 2014-10-29 21:39:37