领域异常 - 对Realm对象的更新,是否持久

时间:2016-04-25 08:01:58

标签: ios swift segue fetch realm

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

这是DayOverviewController,显示用户在特定日期的用餐情况。

这个DayOverviewController在两个场景中转换为NewMealTableViewController - 添加新餐或点击用餐 - 进行编辑。 当我应该添加一顿新餐时,我会得到一个Realm异常,更确切地说,当我应该返回DayOverviewController时,我会得到它(按下保存按钮,用餐添加到Realm,但是来自viewWillAppear的mealTable.reloadData() - 在DayOverviewController崩溃之前调用cellForRowAtIndexPath。)

似乎在调用popViewControllerAnimated之前,在NewMealTableViewController中没有关闭事务。

例外: 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()
  }
}

1 个答案:

答案 0 :(得分:1)

It looks like it's this part of your code:

} else {
  meal.foodItems = textView.text
}

It should be inside the closure for method updateMeal().

EDIT 2:

I suggest:

} else {
    try! realm.write(){
        meal.foodItems = textView.text
    }
}

and

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