【发布时间】:2021-01-15 13:00:01
【问题描述】:
我有一个带有 Swift/SwiftUI 的应用程序。我使用 ObservableObject 和 JSONDecoder 从我的 Node.JS Express API 获取值以显示在我的应用程序中:
struct DevicesList: Decodable {
var data: [PhilipsHueDevicesListEntry]
}
struct DevicesListEntry: Decodable {
var ID: String
var Name: String
var State: Bool
var Reachable: Bool
}
从 API 获取值并放入上述对象的类:
class GetDevices: ObservableObject {
var didChange = PassthroughSubject<GetDevices, Never>()
var DevicesList = DevicesList(data: []){
didSet {
didChange.send(self)
}
}
init(){
let keychain = KeychainSwift()
let authToken = keychain.get("authToken")!
let bridgeID = keychain.get("hubID")!
var request = URLRequest(url: URL(string: GlobalVariables.HUEGetDevices)!)
request.httpMethod = HTTPMethod.get.rawValue
let headers = [
"auth-token": authToken,
"bridgeID": bridgeID,
"Content-Type": "application/json"]
request.allHTTPHeaderFields = headers
URLSession.shared.dataTask(with: request) { (data, _, _) in
guard let data = data else {return}
let devices = try! JSONDecoder().decode(DevicesList.self, from: data)
DispatchQueue.main.async {
self.DevicesList = devices
}
}.resume()
}
然后在我的应用程序的主屏幕中显示:
@State var devices = GetDevices()
ForEach(devices.DevicesList.data, id: \.ID) { device in
ZStack{
Rectangle()
.cornerRadius(5)
.frame(width: 100, height: 100)
.foregroundColor(Color.orange)
VStack(alignment: .leading){
Text(device.Name)
.multilineTextAlignment(.center)
.frame(width: 100, height: 100)
}
}
....
一切运行良好,直到我向上滑动以将应用程序发送到后台(我假设它再次运行 init() 函数以更新 observableObject)。我收到此错误:
_http_outgoing.js:503
throw new errors.Error('ERR_HTTP_HEADERS_SENT', 'set');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at validateHeader (_http_outgoing.js:503:11)
at ServerResponse.setHeader (_http_outgoing.js:510:3)
at ServerResponse.header (/app-c/node_modules/express/lib/response.js:771:10)
at ServerResponse.send (/app-c/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/app-c/node_modules/express/lib/response.js:267:15)
at ServerResponse.send (/app-c/node_modules/express/lib/response.js:158:21)
at lightDataCallbackFunction (/app-c/app.js:185:32). // <----- This is where the error occurs in my js file
at Socket.socket.on (/app-c/app.js:121:7)
at Socket.emit (events.js:180:13)
at /app-c/node_modules/socket.io/lib/socket.js:528:12
at process._tickCallback (internal/process/next_tick.js:176:11)
发生错误的我的JS文件:
lightDataCallbackFunction = function(data){
if(data['socketID'] == socketID){
if(data['code'] == '208'){
return res.status(200).send(data) // <--- OCCURS HERE
}else{
return res.status(400).send({"data": "", "code": "209", "message": data['message']})
}
}
}
我真的不知道为什么会这样以及发生了什么。我最好的猜测是,当我将应用程序发送到后台时,可观察对象实例再次运行,并且以某种方式相同的服务器端代码试图向我的应用程序发送另一个(相同的)响应?我什至返回响应以退出函数,所以我不明白为什么会发生这种情况?
编辑:
我从下面尝试过 MwcsMac 评论,他提到他通常根本不使用 init() 函数,而是将要进入 init() 函数的代码移动到一个新函数中,然后在通过.onAppear() 加载相关视图时调用该函数。
我已经尝试过了,但是无论出于何种原因,它要么根本不运行该函数,要么它只是不更新我的视图(在我的 SwiftUI 代码中填充我的 ForEach 循环。
【问题讨论】:
-
出于这样的原因,我避免将代码放在
init(){ }中。我将您在init中的代码放入一个函数中,并从需要它的视图中调用该函数。 -
@MwcsMac 当然,每次应用程序进入后台时它都会调用该函数,什么都没有改变?
-
@MwcsMac 我试过你的方法,回家还是崩溃,如果我在需要的视图中再次调用该函数,它只会立即崩溃应用程序
-
您是否尝试过仅在
.onapper { }中触发函数? -
@MwcsMac 是的,我删除了
init()函数,创建了一个新函数并在我认为的onAppear()中调用了该函数,什么也没发生,该函数甚至由于某种原因没有运行我知道onAppear()正在工作,因为我在其中放入了打印语句进行测试??
标签: javascript ios node.js swift swiftui