是否可以在 SwiftUI 中提供服务并将数据推送到视图并更新 UI?
Posted
技术标签:
【中文标题】是否可以在 SwiftUI 中提供服务并将数据推送到视图并更新 UI?【英文标题】:Is it possible to have a Service in SwiftUI and push data to a View and update the UI? 【发布时间】:2019-07-18 17:42:17 【问题描述】:我有一个获取数据并将数据发送到后端的服务文件。是否可以将推送数据从服务推送到视图并让 UI 像 @State 一样获取更改(不像全局变量)。
@EnviornmentObject 不能以只读方式工作 全局变量不起作用,因为不通知 UI
import SwiftUI
import SocketIO
import Combine
let manager = SocketManager(socketURL: URL(string: "http://localhost:30000/ios")!, config: [.log(true), .compress])
let socket = manager.defaultSocket
class Socket: BindableObject
let didChange = PassthroughSubject<Socket,Never>()
var sliderValue: Float = 6
willSet
print(newValue)
didChange.send(self)
static let sharedInstance = Socket()
init()
socket.on(clientEvent: .connect) data, ack in
print("socket connected")
self.sliderValue = 8
func establishConnection()
socket.connect()
func closeConnection()
socket.disconnect()
主页视图:
import SwiftUI
struct HomeView : View
@EnvironmentObject var socketData: Socket
var body: some View
VStack
Text("Hello World")
Slider(value: $socketData.sliderValue, from: 0.0, through: 10.0)
Text(String(socketData.sliderValue))
【问题讨论】:
哇。@EnvironmentObject
是正确的。更新模型,发给UI,yada,yada。问题是另外一回事 - 请记住,@State
是针对单个 View
的局部变量。所以也许......您是否正确更新了模型状态? Ae 你正在处理一个UIKit
的前景,以寻求非常不同的东西吗?你为什么说环境变量是只读的?他们不是。请向我们展示更多要复制的代码。
我以为我读到它是只读的。我是 swift 新手,但我更新了答案
不要发布一个可能没有帮助的冗长答案,而是看看这个答案 - ***.com/questions/56725084/… - Slider
正在更新 BindableObject
,它是 @EnvironmentObject
或@ObjectBinding
一个。 (是的,现在在 beta 4 中,它需要 willSet
PassthruoghSubject。欢迎来到 Swiftui 的前沿!)
我按照那里告诉的那样做了,但是当套接字连接时,用户界面没有更新
你是在主线程上更新模型吗?这是使用BindableObject
的唯一警告——也是为什么我不确定这些是否有帮助的原因。 (我不使用套接字,但知道它们是什么——我自 1984 年以来一直在 IT 987654336@ 可能有用吗?)
【参考方案1】:
我仍然有无法从套接字获取数据但正常字符串工作的问题我将为这个问题打开一个新问题: How to fix 'Cannot convert value of type '[Any]' to type 'String' in coercion' error in swift
我确实不得不使用 didSet 这里是代码:
let manager = SocketManager(socketURL: URL(string: "http://localhost:30000/ios")!, config: [.log(true), .compress])
let socket = manager.defaultSocket
class Socket: BindableObject
let didChange = PassthroughSubject<Socket,Never>()
var days: String = "Loading..."
didSet
didChange.send(self)
static let sharedInstance = Socket()
init()
socket.on(clientEvent: .connect) data, ack in
print("socket connected")
socket.on("dailyWeather") data, ack in
print("just a test")
self.days = "cur"
func establishConnection()
socket.connect()
func closeConnection()
socket.disconnect()
【讨论】:
【参考方案2】:您可以使您的 Socket 具有 messagePublisher
以便使用传入消息更新子视图。
class Socket
static let sharedInstance = Socket()
public let messagePublisher = PassthroughSubject<Message, Never>()
init()
socket.on(clientEvent: .connect) data, ack in
print("socket connected")
let message = data as! Message
messagePublisher.send(message)
然后让您的孩子像这样订阅传入的消息:
Socket.sharedInstance.assign(to: \.message, on: messageModel)
其中MessageModel
符合BindableObject
协议
【讨论】:
我必须在哪里添加这一行?Socket.sharedInstance.assign(to: \.message, on: messageModel) @TobiasBauer 您可以将其添加到您想使用套接字的子视图中。DemoView
可能有一个属性 @ObjectBinding var model: MessageModel
。并且MessageModel
应该有一个属性message
,您可以在其中分配套接字。
我更新了上面的代码,但是我有这个错误:无法将类型'WritableKeyPath以上是关于是否可以在 SwiftUI 中提供服务并将数据推送到视图并更新 UI?的主要内容,如果未能解决你的问题,请参考以下文章