简体   繁体   中英

How to edit realm object and save editing?

I have 2 Controllers: TableViewController and ViewController. TableViewController is responsible for displaying all data, View Controller is responsible for creating new data. Now I want to make it possible to edit the current data also in ViewController . When we click on data, we need to switch to the ViewController and replace all default values with the current values. When we change and click save, we go back to TableViewController , where we already see the change.

class OperationsViewController: UITableViewController {

// MARK: - Stored Properties
var transactions: Results<Transaction>!
var sections = [(date: Date, items: Results<Transaction>)]()

// MARK: - UITableViewController Methods
override func viewDidLoad() {
    super.viewDidLoad()
    transactions = realm.objects(Transaction.self)
}

override func viewWillAppear(_ animated: Bool) {
    super .viewWillAppear(animated)
    assembleGroupedTransactions()
    tableView.reloadData()
  }
}

// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let indexPath = tableView.indexPathForSelectedRow {
        let section = sections[indexPath.section]
        let item = section.items[indexPath.row]
        print(item)
        if segue.identifier == "editOrDeleteOperationCell" {
            let addTableViewController = segue.destination as! AddTableViewController
            addTableViewController.defaultTransaction = item
        }
    }
  }
}

// MARK: - User Interface
extension OperationsViewController {

@discardableResult private func assembleGroupedTransactions() -> Array<Any> {
    // fetch all Items sorted by date
    let results = realm.objects(Transaction.self).sorted(byKeyPath: "date", ascending: false)

    sections = results
        .map { item in
            // get start of a day
            return Calendar.current.startOfDay(for: item.date)
        }
        .reduce([]) { dates, date in
            // unique sorted array of dates
            return dates.last == date ? dates : dates + [date]
        }
        .compactMap { startDate -> (date: Date, items: Results<Transaction>) in
            // create the end of current day
            let endDate = Calendar.current.date(byAdding: .day, value: 1, to: startDate)!
            // filter sorted results by a predicate matching current day
            let items = results.filter("(date >= %@) AND (date < %@)", startDate, endDate)
            // return a section only if current day is non-empty
            return (date: startDate, items: items)
    }
    return sections
}

But when I trying to send current data to next ViewController I get error:

*** 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 guess that I have problem with Category . Look on my model:

class Transaction: Object {

@objc dynamic var controlStatus = 0

@objc dynamic private var privateCategory: String = Category.consumption.rawValue
var category: Category {
    get { return Category(rawValue: privateCategory)! }
    set { privateCategory = newValue.rawValue }
}

@objc dynamic var amount = "0"
@objc dynamic var date = Date()
@objc dynamic var note = ""
}

controlStatus needs for monitors the status of the transaction that will be needed in the future. Where 0 is the expense, 1 is the income. The big problem I suppose is that I created categories by enum . I need to change the arrays with categories depending on the controlStatus . Now is this my model of Category:

indirect enum Category: String {
case income = "+"
case consumption = "-"

case salary = "salary"
case billingInterest = "billingInterest"
case partTimeJob = "partTimeJob"

etc.
}

extension Category: RawRepresentable {
typealias RawValue = String

init?(rawValue: RawValue) {
    switch rawValue {
    case "+": self = .income
    case "-": self = .consumption

    case "salary": self = .salary
    case "billingInterest": self = .billingInterest
    case "partTimeJob: self = .partTimeJob
    case "pleasantFinds": self = .pleasantFinds
    case "debtRepayment": self = .debtRepayment

    case "noCategories": self = .noCategories
    case "food": self = .food

    etc. 

    default:
        return nil
    }
}

var rawValue: RawValue {
    switch self {
    case .salary:
        return "salary"
    case .billingInterest:
        return "billingInterest"
    case .partTimeJob:
        return "partTimeJob"
    case .pleasantFinds:
        return "pleasantFinds"
    case .debtRepayment:
        return "debtRepayment"

    case .noCategories:
        return "noCategories"
    case .food:
        return "food"
    case .cafesAndRestaurants:
        return "cafesAndRestaurants"
    etc.
    }
}
}

您需要将领域写事务包含在写块中

try realm.write({ () -> Void in realm.add(object, update: true) })

From Realm doc

try! realm.write {
    realm.add(myDog)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM