首页 > 解决方案 > 在 SwiftUI 中检索和保存时转换 Realm 属性的值

问题描述

我有一个FlightRealm 类,其duration属性是Int. 它将飞行的持续时间存储为分钟数。

class Flight: Object, ObjectKeyIdentifiable{
  @objc dynamic var duration = 0
}

我将一个Flight对象作为一个对象传递ObservedRealmObject给一个编辑它的子视图。用户可以将时间输入为HHMM(130 = 1 小时 30 分钟) 或#.#(1.5 小时)。我有一些扩展可以将这些时间中的任何一个从 a 转换为String存储为 an 的分钟数,然后再转换Int回来。

但我遇到的问题是绑定我的TextField. 我无法duration直接绑定到属性,因为我需要将它从时间格式转换为分钟数。

struct MyView: View {
  @ObservedRealmObject var flight: Flight
  @AppStorage("timeDisplayHHMM") var timeDisplayHHMM = false
  
  var body: some View{
    TextField(timeDisplayHHMM ? "HHMM": "#.#", text: $flight.duration)
  }
}

我尝试了几种不太有效的不同方法。

尝试 1

我创建了一个@State我设置的变量,.onAppear然后我将值保存在里面,.onChange如下所示:

@State var duration = ""

TextField(...)
  .onChange(of: duration, perform: { value in
    //Save duration using my view model
    model.saveDuration(flight: $flight, duration: duration)
  })
  .onAppear(){
    //Get value
    duration = flight.duration.timeDisplay //"timeDisplay" is my conversion Int extension.
  }

这很好用,但它依赖于onAppear保持其值更新。因此,如果duration我的 Realm 中发生更改,除非用户使视图再次出现,否则 UI 将不会更新。

尝试 2

我尝试创建自定义绑定,并从 Realm 属性设置绑定的值,然后将其保存在 setter 中。这在用户键入时行为不规律,因为值在他们完成键入之前已保存和更新。

例如,如果他们输入,1.那么它会快速将其保存为 1 小时,然后1.0在他们完成输入之前值更新为1.5

private var durationBinding: Binding<String> {
  Binding<String>(get: {
    //Set binding value
    flight.duration.timeDisplay
  }, set: {
    //Save
    model.saveDuration(flight: $flight, duration: $0)
  })
}

我怎样才能获得绑定到StringRealm 属性的好处,同时仍然将值转换为/从Int?

标签: swiftswiftuirealmcombine

解决方案


推荐阅读