swift - How Should My Code Run When using SwiftUI And Websockets
问题描述
I am making a client that connect to a websocket and shows different pages. I am looking for help on how I should order my code. First the user logs in and it connects them to the websocket to verify and if they are authorized it will continue, if not it will show an error.
TLDR My code need to somehow connect to a websocket, go to a new page, and show info. My code also needs to alert the user about any errors.
var request = URLRequest(url: URL(string: "wss://link")!)
struct LoginView: View {
@State private var loggedIn = false
@State private var loginCode = ""
var body: some View {
NavigationView {
VStack(spacing: 30) {
NavigationLink(destination: newView().navigationBarHidden(true), isActive: $loggedIn) { EmptyView() }
HStack {
Image(systemName: "person").foregroundColor(.gray)
TextField("Login Code", text: $loginCode)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
.frame(width: 300)
.offset(y: -75)
})
.buttonStyle(ContainedButtonStyle())
.offset(y: -50)
}
.navigationBarTitle("Log In")
}
}
}
func connectToSocket(loginCode: String) {
request.addValue("Bearer \(loginCode)", forHTTPHeaderField: "Authorization")
let ws = WebSocket(request: request)
struct newView: View {
@State private var accountsCheckedShown = false
let username = "MarcoD1337"
let games = 5
let lives = 10
let money = "$5/$5"
let status = "Ready For Cashout"
var body: some View {
NavigationView {
TabView {
ZStack {
List{
HStack {
ZStack {
Circle().fill(Color(red: 0.913, green: 0.737, blue: 0.447, opacity: 1))
.frame(maxWidth: 50, maxHeight: 50)
Text("")
.font(.largeTitle)
.multilineTextAlignment(.center)
}
VStack(alignment: .leading) {
Text(username)
.font(.title)
.fontWeight(.bold)
.minimumScaleFactor(0.25)
Text("Games: \(games)")
.minimumScaleFactor(0.5)
Text("Lives: \(lives)")
.minimumScaleFactor(0.5)
Text("\(money) Available")
.minimumScaleFactor(0.5)
Text("Status: \(status)")
.minimumScaleFactor(0.5)
}
.padding()
}
}
.navigationTitle("Accounts")
}
.tabItem {
Image(systemName: "star")
Text("User Info")
}
}
}
}
}
ws.event.open = { }
ws.event.message = { message in
let msg = JSON(message)
if msg["type"] == "" { }
}
ws.event.error = { error in
//errorLoginView(error: "\(error)")
}
}
解决方案
I've used WebSocket(StarScream) in a Swift demo app.
I'd recommend using a standalone state object (@ObservableObject
or @EnvironmentObject
)to handle websocket. Think of it as a shared websocket service.
In this service, you publish a couple of events based on your needs.
E.g.;
enum LoginState {
case initial, authOK, authFail
}
final class Websocket: ObservableObject {
@Published var state: LoginState = .initial
// implement websocket callbacks
// e.g.; change state to .authFail in error handler
}
Your LoginView simply observes state changes:
struct LoginView: View {
@ObservedObject var ws = Websocket()
var body: some View {
// setup websocket as needed
switch ws.state { // supported in Xcode 12 as I recall, use if otherwise
case .authOK:
// some view
// other cases
}
}
}
This is the overall picture, you need to fill in the implementation yourself.
I think this is sufficient to get you started on the right track.
推荐阅读
- javascript - 将返回组匹配的 Javascript RegEx.exec 转换为 Python
- java - 读入 WAV 文件并计算 RMS
- c# - 输入字符串的格式不正确。视觉工作室 2017
- python - 无法在 PyCharm 和 Visual Studio 2017 中运行相同的 python 文件
- ios - 如何检测 SKSpriteNode 何时命中另一个 SKSpriteNode?
- sql-server - Entity Framework 6 中的可更新视图
- angular - 放置请求是 404 未找到
- amp-bind - 如何在 AMP 日期选择器上获取当前日期?
- sql - SQL列出两个日期之间的重复日期,结束日期为下一个开始日期
- excel - 最后一场比赛的行位置