Realm Exception - 更新 Realm 对象,持久化与否

Realm Exception - updates on Realm objects, persisted or not

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

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

This DayOverviewController 转至 NewMealTableViewController,在两种情况下 - 添加新餐或点击餐 - 进行编辑。 当应该添加新餐时,我得到一个 Realm 异常,更确切地说,我应该 return 到 DayOverviewController 时得到它(按下保存按钮,餐被添加到 Realm,但是 mealTable.reloadData() - 来自 viewWillAppear,DayOverviewController 在调用 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()