我在我的应用程序中使用Realm。
我想使用相同的viewController进行更新/插入餐对象。

这是DayOverviewController,它显示用户在特定日期吃的饭。

这个DayOverviewController可以选择NewMealTableViewController,在两种情况下-添加新餐点或单击餐点-进行编辑。
当应该添加新的进餐时,我收到一个Realm异常,更确切地说,当我应该返回DayOverviewController时,我得到了它(按下保存按钮,将进餐添加到Realm中,但是在ViewOverviewController中,来自viewWillAppear的餐表。调用cellForRowAtIndexPath。)

似乎在NewMealTableViewController中调用popViewControllerAnimated之前,某种方式的事务未关闭。

例外:Terminating app due to uncaught exception 'RLMException', reason: 'Attempting to modify object outside of a write transaction - call beginWriteTransaction on an RLMRealm instance first.'我没有找出导致此异常的代码行。

class DayOverviewController: UIViewController{
  @IBOutlet weak var mealTable: UITableView!
  let realm = try! Realm()
  var meals: Results<Meal>!
  var selectedMeal: Meal?

  override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    getMealsFromDay(selectedDate){
      self.mealTable.reloadData()
    }
  }

  override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "NewMeal" {
      let meal = Meal()
      meal.date = selectedDate
      let newMealController = segue.destinationViewController as! NewMealTableViewController
      newMealController.meal = meal
      newMealController.kindOfController = .InserterController
    }

    if segue.identifier == "EditMeal" {
      if let meal = selectedMeal{
        let updaterController = segue.destinationViewController as! NewMealTableViewController
        updaterController.meal = meal
        updaterController.kindOfController = .UpdaterController
      }
    }
  }
}

extension DayOverviewController: UITableViewDataSource, UITableViewDelegate{

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("mealCell", forIndexPath: indexPath) as! MealOverviewCell
    cell.typeOfMealLabel.text = meals[indexPath.row].dishType
    cell.foodItemsLabel.text = meals[indexPath.row].foodItems
    cell.feedbackLabel.text = EmonjiCalculator.getEmonji(Array(meals[indexPath.row].reactions))
    return cell
  }

  func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    selectedMeal = meals[indexPath.row]
    performSegueWithIdentifier("EditMeal", sender: self)
  }
}

extension DayOverviewController{
   func getMealsFromDay(selectedDate: NSDate, completionBlock : () -> Void ) {
     let dayStart = NSCalendar.currentCalendar().startOfDayForDate(selectedDate)
     let dayEnd: NSDate = {
       let components = NSDateComponents()
       components.day = 1
       components.second = -1
       return NSCalendar.currentCalendar().dateByAddingComponents(components, toDate: dayStart, options: NSCalendarOptions())!
      }()
     self.meals = realm.objects(Meal).filter("date BETWEEN %@", [dayStart, dayEnd])
     completionBlock()
   }

   func deleteMeal(meal: Meal){
     realm.beginWrite()
     realm.delete(meal.reactions)
     realm.delete(meal)
     try! realm.commitWrite()
   }
}


enum TypeOfController{
  case UpdaterController
  case InserterController
}

class NewMealTableViewController: UITableViewController, UITextViewDelegate{

  let realm = try! Realm()
  var meal: Meal!
  @IBOutlet weak var foodItemsTextView: UITextView!
  var kindOfController: TypeOfController!

  override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    switch segue.destinationViewController {
      case let controller as MealSelectorTableViewController:
        controller.delegate = self
      case let controller as ReactionTableViewController:
        controller.reactionDelegate = self
        controller.meal = meal
      default: break
   }
}

  func saveMeal(saveButton: UIBarButtonItem){
    if kindOfController == .InserterController {
      insertNewMeal(){
        self.navigationController?.popViewControllerAnimated(true)
      }
    }
  }

  func textViewDidEndEditing(textView: UITextView) {
    if kindOfController == .UpdaterController{
      updateMeal{
        self.meal.foodItems = textView.text
      }
    } else {
      meal.foodItems = textView.text
    }
  }
}

extension NewMealTableViewController{

  func updateMeal(updateBlock: ()->()){
    try! realm.write(){
      updateBlock()
    }
  }

  func insertNewMeal(completionBlock: () -> ()){
    meal.id = NSUUID().UUIDString
    realm.beginWrite()
    realm.add(meal)
    try! realm.commitWrite()
    completionBlock()
  }
}

最佳答案

看起来这是您的代码的这一部分:

} else {
  meal.foodItems = textView.text
}

它应该在updateMeal()方法的闭包内部。

编辑2:

我建议:
} else {
    try! realm.write(){
        meal.foodItems = textView.text
    }
}


realm.beginWrite()
meal.id = NSUUID().UUIDString
realm.add(meal)
try! realm.commitWrite()
completionBlock()

07-24 09:16