当前位置: 动力学知识库 > 问答 > 编程问答 >

ios - Realm Exception - updates on Realm objects, persisted or not

问题描述:

I am using Realm in my app.

I want to use the same viewController for update / insert a meal object.

Here is DayOverviewController, which displays meals that user had on a specific date.

This DayOverviewController segues to NewMealTableViewController, in two scenarios - a new meal is added, or a meal is clicked - to be edited.

I get a Realm exception when a new meal should be added, more exactly I get it when I should return to DayOverviewController ( save button is pressed, meal is added to Realm, but mealTable.reloadData() - from viewWillAppear, in DayOverviewController crashes before calling cellForRowAtIndexPath.)

It seems that somehow transaction is not closed before calling popViewControllerAnimated - in NewMealTableViewController.

Exception:

Terminating app due to uncaught exception 'RLMException', reason: 'Attempting to modify object outside of a write transaction - call beginWriteTransaction on an RLMRealm instance first.'

I didn't managed to find out what line of code is causing this exception.

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()

}

}

网友答案:

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()
分享给朋友:
您可能感兴趣的文章:
随机阅读: