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()
我在我的应用程序中使用 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()