ali*_*_ix 6 ios swiftui combine observedobject observableobject
我在 SwiftUI 中观察到的对象有问题。我可以在 View 结构上看到观察对象的变化值。但是在类或函数中,即使我更改了 TextField(可观察对象)的文本值,但“self.codeTwo.text 仍然没有改变。
这是我的代码示例(这是我的 ObservableObject)
class settingCodeTwo: ObservableObject {
private static let userDefaultTextKey = "textKey2"
@Published var text: String = UserDefaults.standard.string(forKey: settingCodeTwo.userDefaultTextKey) ?? ""
private var canc: AnyCancellable!
init() {
canc = $text.debounce(for: 0.2, scheduler: DispatchQueue.main).sink { newText in
UserDefaults.standard.set(newText, forKey: settingCodeTwo.userDefaultTextKey)
}
}
deinit {
canc.cancel()
}
}
Run Code Online (Sandbox Code Playgroud)
主要问题是......“self.codeTwo.text”从未改变!
class NetworkManager: ObservableObject {
@ObservedObject var codeTwo = settingCodeTwo()
@Published var posts = [Post]()
func fetchData() {
var urlComponents = URLComponents()
urlComponents.scheme = "http"
urlComponents.host = "\(self.codeTwo.text)" //This one I want to use observable object
urlComponents.path = "/mob_json/mob_json.aspx"
urlComponents.queryItems = [
URLQueryItem(name: "nm_sp", value: "UP_MOB_CHECK_LOGIN"),
URLQueryItem(name: "param", value: "1000|1000|\(Gpass.hahaha)")
]
if let url = urlComponents.url {
print(url)
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, response, error) in
if error == nil {
let decoder = JSONDecoder()
if let safeData = data {
do {
let results = try decoder.decode(Results.self, from: safeData)
DispatchQueue.main.async {
self.posts = results.Table
}
} catch {
print(error)
}
}
}
}
task.resume()
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是视图,我可以捕捉到这个值的变化
import SwiftUI
import Combine
struct SettingView: View {
@ObservedObject var codeTwo = settingCodeTwo()
var body: some View {
ZStack {
Rectangle().foregroundColor(Color.white).edgesIgnoringSafeArea(.all).background(Color.white)
VStack {
TextField("test", text: $codeTwo.text).textFieldStyle(BottomLineTextFieldStyle()).foregroundColor(.blue)
Text(codeTwo.text)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
请帮帮我。
use*_*037 11
ObservedObject仅SwiftUI,你的函数/其他非SwiftUI代码不会作出反应的变化。Sink观察任何发布者的变化。(每个@Published变量都有一个发布者作为包装值,您可以通过使用$符号前缀来使用它。SwiftUI查看未反应类属性的变化:struct是一种值类型,所以当它的任何属性发生变化时,它的值struct也发生了变化class是引用类型,当它的任何属性发生变化时,底层class实例仍然相同。
codeTwoText以@Binding这种方式接受codeTwoText。class Model : ObservableObject {
@Published var name : String //Ensure the property is `Published`.
init(name: String) {
self.name = name
}
}
struct NameView : View {
@Binding var name : String
var body: some View {
return Text(name)
}
}
struct ContentView: View {
@ObservedObject var model : Model
var body: some View {
VStack {
Text("Hello, World!")
NameView(name: $model.name) //Passing the Binding to name
}
}
}
Run Code Online (Sandbox Code Playgroud)
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
let model = Model(name: "aaa")
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
model.name = "bbb"
}
return ContentView(model: model)
}
}
Run Code Online (Sandbox Code Playgroud)
它使用了两个不同的实例SettingCodeTwo- 一个在NetworkNamager另一个 in 中SettingsView,因此如果同时创建,它们不会同步。
这是一种保持这两个实例自同步的方法(这是可能的,因为它们使用相同的存储 - UserDefaults)
使用 Xcode 11.4 / iOS 13.4 进行测试
修改后的代码如下(另请参阅内联重要注释)
extension UserDefaults {
@objc dynamic var textKey2: String { // helper keypath
return string(forKey: "textKey2") ?? ""
}
}
class SettingCodeTwo: ObservableObject { // use capitalised name for class !!!
private static let userDefaultTextKey = "textKey2"
@Published var text: String = UserDefaults.standard.string(forKey: SettingCodeTwo.userDefaultTextKey) ?? ""
private var canc: AnyCancellable!
private var observer: NSKeyValueObservation!
init() {
canc = $text.debounce(for: 0.2, scheduler: DispatchQueue.main).sink { newText in
UserDefaults.standard.set(newText, forKey: SettingCodeTwo.userDefaultTextKey)
}
observer = UserDefaults.standard.observe(\.textKey2, options: [.new]) { _, value in
if let newValue = value.newValue, self.text != newValue { // << avoid cycling on changed self
self.text = newValue
}
}
}
}
class NetworkManager: ObservableObject {
var codeTwo = SettingCodeTwo() // no @ObservedObject needed here
...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7509 次 |
| 最近记录: |