【问题标题】:How to edit realm object and save editing?如何编辑领域对象并保存编辑?
【发布时间】:2019-05-15 08:34:34
【问题描述】:

我有 2 个控制器:TableViewController 和 ViewController。 TableViewController 负责显示所有数据,View Controller 负责创建新数据。 现在我想让ViewController 中的当前数据也可以编辑。当我们点击数据时,我们需要切换到ViewController,并将所有默认值替换为当前值。当我们更改并单击保存时,我们会返回到TableViewController,我们已经看到了更改。

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
}

但是当我尝试将当前数据发送到下一个 ViewController 时,我得到了错误:

*** 由于未捕获的异常“RLMException”而终止应用程序,原因:“尝试在写入事务之外修改对象 - 首先在 RLMRealm 实例上调用 beginWriteTransaction。”


我猜我对Category 有疑问。看看我的模型:

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需要监控未来需要的事务状态。其中0是费用,1是收入。 我想最大的问题是我通过enum 创建了类别。 我需要根据controlStatus 更改具有类别的数组。 现在这是我的类别模型:

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.
    }
}
}

【问题讨论】:

  • realm.write { ... }
  • @vpoltave 不,这些是不同的问题。
  • 那么究竟什么时候抛出异常:你能使用堆栈跟踪来显示导致它的行吗?我在这段代码中看不到任何问题。您正在使用 addTableViewController.defaultTransaction = item 将项目传递给第二个 VC,这很好,但现在在 realm.write 块之外的 VC 中无法编辑。我怀疑崩溃是由上面未包含的一些编辑代码引起的 - AddTableViewController 中还有哪些其他代码?它可能在viewDidLoad 中,或者您可以在其他地方编辑defaultTransaction - 这是您无法做到的。 editData 怎么称呼?
  • @ChrisShaw 我开始猜测可能是什么问题。当我注释掉categories 时,item 就通过了。很可能我在转移Category 时遇到问题。你能帮我解决这个问题吗?

标签: ios swift uitableview realm


【解决方案1】:

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

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

【讨论】:

  • 你的意思是,我在ViewController中按“保存”时应该使用这种方法吗?
  • 是的。保存时,在此块中进行。检查领域文档以获取示例
  • 但是如何将当前数据从TableViewController 传递到ViewController
  • 您可以根据应用的架构使用任何模式来实现这一点。有使用回调的委托模式,然后有使用通知的观察者模式等。
  • 你可能不这么理解我。当我点击 currentData 时,我不知道如何开始编辑。
【解决方案2】:

来自领域doc

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-08
    相关资源
    最近更新 更多