这里使用webscoket,主要是使用了Starscream这个库,看图片就知道很牛X,那么干就完了。官方开源仓库地址:https://github.com/daltoniam/Starscream?tab=readme-ov-file
安装依赖库
首先,使用 Swift Package Manager 安装 Starscream。在 Xcode 中打开你的项目,选择项目文件,然后在"Swift Packages"选项卡中点击"+"按钮,添加:https://github.com/daltoniam/Starscream
创建Websocket管理器
在 SwiftUI 中使用 Starscream 创建 WebSocket 连接,并实现消息的接收和发送,可以按照以下步骤进行。Starscream 是一个流行的 WebSocket 库,能够轻松地在 iOS 和 macOS 应用中处理 WebSocket 连接:
Swift
import Foundation
import Starscream
class WebSocketManager: ObservableObject {
var socket: WebSocket!
@Published var receivedMessage: String = ""
init() {
// 替换为你的 WebSocket 服务器地址
var request = URLRequest(url: URL(string: "ws://192.168.1.52:8989/echo")!)
request.timeoutInterval = 5
socket = WebSocket(request: request)
socket.delegate = self
socket.connect()
}
func send(message: String) {
socket.write(string: message)
}
func disconnect() {
socket.disconnect()
}
}
extension WebSocketManager: WebSocketDelegate {
func didReceive(event: WebSocketEvent, client: WebSocketClient) {
switch event {
case .connected(let headers):
print("WebSocket connected with headers: \(headers)")
case .disconnected(let reason, let code):
print("WebSocket disconnected with reason: \(reason), code: \(code)")
case .text(let string):
DispatchQueue.main.async {
self.receivedMessage = string
}
case .binary(let data):
print("Received binary data: \(data)")
case .error(let error):
print("WebSocket encountered an error: \(String(describing: error))")
case .ping:
break
case .pong:
break
case .viabilityChanged:
break
case .reconnectSuggested:
break
case .cancelled:
print("WebSocket cancelled")
case .peerClosed:
print("WebSocket peer closed")
}
}
}
创建swiftUI页面控制,实现发送和接收消息:
Swift
//
// StarsView.swift
// mywatch Watch App
//
// Created by song on 2024/6/20.
//
import SwiftUI
struct StarsView: View {
@StateObject private var webSocketManager = WebSocketManager()
@State private var messageToSend: String = ""
var body: some View {
VStack {
Text("R: \(webSocketManager.receivedMessage)")
.padding()
TextField("S", text: $messageToSend)
.padding()
HStack {
Button(action: {
webSocketManager.send(message: messageToSend)
messageToSend = ""
}) {
Text("发")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
Button(action: {
webSocketManager.disconnect()
}) {
Text("断")
.padding()
.background(Color.red)
.foregroundColor(.white)
.cornerRadius(8)
}
}
}
.padding()
}
}
#Preview {
StarsView()
}
实现效果:
可以看到websocket服务器已经收到消息并打印出来了,apple watch模拟器上也收到了消息回复,
而且这个在iPhone和mac或者ipad上都是没有问题的,都可以完美支持,但是就是apple watch需要注意,apple watch真机暂不支持websocket:
但是请注意:模拟器上可以收发消息并一定说明真机上也可以的啊,所以真机测试的时候就会遇到问题,报错:NECP策略限制
nw_endpoint_flow_failed_with_error [C1 192.168.1.52:8989 waiting parent-flow (unsatisfied (Path was denied by NECP policy), interface: ipsec1, ipv4, ipv6, proxy)] already failing, returning
WebSocket receive error: Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo={NSErrorFailingURLKey=http://192.168.1.52:8989/echo, NSErrorFailingURLStringKey=http://192.168.1.52:8989/echo, NSLocalizedDescription=The Internet connection appears to be offline.}
nw_endpoint_flow_failed_with_error [C1 192.168.1.52:8989 failed parent-flow (unsatisfied (Path was denied by NECP policy), interface: ipsec1, ipv4, ipv6, proxy)] already failing, returning
Connection 1: received failure notification
Connection 1: failed to connect 1:50, reason 18,446,744,073,709,551,615
Connection 1: encountered error(1:50)
那这个NECP策略是啥?看官方文档:NETWORK: NWPathMonitor non-functio... | Apple Developer Forums
相信你已经大概了解了,这个NECP策略就是网络管理器,可以控制哪些网络可以使用什么样的网络请求等,之所以在模拟器上可以连接上websocket没有问题,是因为watch os用的是mac电脑的NECP策略,所以可以成功,但是watch真机上是由于存在更低等级的网络控制,所以不成功。
那什么是 Low-Level Networking on watchOS呢?
说白了,就是watch6之前其实啥网络都不支持,但是之后就支持了http和https等,也就是还在一步一步升级中,但是请注意,虽然支持了https等,还是不支持websocket请求的。
再附上watch的网络通讯说明:关于 Apple Watch 上的蓝牙、无线局域网和蜂窝网络 - 官方 Apple 支持 (中国)
当 iPhone 在附近时,Apple Watch 会使用蓝牙,从而节省电量。
如果蓝牙无法使用,Apple Watch 会尝试使用无线局域网。例如,如果有兼容的无线局域网可用,并且 iPhone 不在蓝牙通信范围内,则 Apple Watch 会使用无线局域网。
如果蓝牙和无线局域网都不可用,并且你设置了蜂窝号码,则 Apple Watch 蜂窝网络机型可以接入蜂窝网络。