Swift将订阅、正确的流程和体系结构选择结合起来
比如说: •我的应用程序是套接字服务器的客户端 •我可以自由编写套接字客户端实现,以适应我喜欢的Swift将订阅、正确的流程和体系结构选择结合起来,swift,combine,Swift,Combine,比如说: •我的应用程序是套接字服务器的客户端 •我可以自由编写套接字客户端实现,以适应我喜欢的Combine 我已经实现了两个解决方案,一个是使用CurrentValueSubject(非常简单),另一个是使用自定义订阅和自定义发布服务器,我对此不确定。我真的不知道用Combine处理服务器消息时,哪种方法是连接代码的最好方法 这是我的密码: 为了模拟套接字服务器,我创建了一个假的SocketServerManager,它每隔N秒生成一些事件: protocol SocketServerMan
Combine
我已经实现了两个解决方案,一个是使用CurrentValueSubject
(非常简单),另一个是使用自定义订阅和自定义发布服务器,我对此不确定。我真的不知道用Combine处理服务器消息时,哪种方法是连接代码的最好方法
这是我的密码:
为了模拟套接字服务器,我创建了一个假的SocketServerManager
,它每隔N
秒生成一些事件:
protocol SocketServerManagerDelegate{
func newEvent(event:String)
}
class SocketServerManager {
let timing: Double
var timerHandler:Timer? = nil
var delegates:[SocketServerManagerDelegate] = []
init(timing:Double){
self.timing = timing
}
func start(){
// Just start a timer that calls generateEvent to simulate some events
timerHandler = Timer.scheduledTimer(withTimeInterval: timing, repeats: true){
[weak self] _ in
self?.generateEvent()
}
timerHandler?.fire()
}
private func generateEvent(){
let events = ["New Player", "Player Disconnected", "Server Error"]
let currentEvent = events.randomElement
for delegate in delegates{
delegate.newEvent(event: currentEvent)
}
}
}
自定义发布者和订阅
我的自定义订阅保留对服务器管理器实例和订阅服务器的引用。
此外,它还实现了一个SocketServerManager
委托。因此,当服务器有一个新事件时,它会调用订阅,该订阅现在可以在订阅服务器上发送接收
事件(这是我有很多疑问的选择…
您如何看待这个实现?对我来说,这似乎很笨拙,但我真的不知道如何将事件从服务器管理器连接到订阅者 我会采用以下简单易管理的方法(在我看来,这不是“代表”的正确位置) 完全可测试的模块:消费者是SwiftUI视图。使用Xcode 11.2/iOS 13.2进行测试,但我看不到任何平台限制 演示: 这是一个令人费解的想法代码。请在线查找其他注释
import SwiftUI
import Combine
protocol SocketServerManagerDelegate{
func newEvent(event:String)
}
class SocketServerManager {
// transparent subject that manages subscribers/subscriptions
let publisher = PassthroughSubject<String, Never>()
let timing: Double
var timerHandler:Timer? = nil
init(timing:Double){
self.timing = timing
}
func start(){
// Just start a timer that calls generateEvent to simulate some events
timerHandler = Timer.scheduledTimer(withTimeInterval: timing, repeats: true){
[weak self] _ in
self?.generateEvent()
}
timerHandler?.fire()
}
func stop(){
publisher.send(completion: .finished) // notifies all that finished
}
private func generateEvent(){
let events = ["New Player", "Player Disconnected", "Server Error"]
guard let currentEvent = events.randomElement() else { return }
publisher.send(currentEvent) // send to all subscribers
}
}
// usage
class ViewModel: ObservableObject {
private let server = SocketServerManager(timing: 1)
private var cancellables = Set<AnyCancellable>()
func setup() {
guard cancellables.isEmpty else { return } // already set up
// add one example subscriber
server.publisher
.assign(to: \.value1, on: self)
.store(in: &cancellables)
// add another example subscriber
server.publisher
.sink(receiveValue: { value in
self.value2 = value
})
.store(in: &cancellables)
server.start()
}
@Published var value1: String = "<unknown>"
@Published var value2: String = "<unknown>"
}
// view demo
struct TestSocketServerPublisher: View {
@ObservedObject var viewModel = ViewModel()
var body: some View {
VStack {
Text("Observer1: \(viewModel.value1)")
Divider()
Text("Observer2: \(viewModel.value2)")
}
.onAppear {
self.viewModel.setup()
}
}
}
struct TestSocketServerPublisher_Previews: PreviewProvider {
static var previews: some View {
TestSocketServerPublisher()
}
}
导入快捷界面
进口联合收割机
协议SocketServerManagerDelegate{
func newEvent(事件:字符串)
}
类SocketServerManager{
//管理订阅服务器/订阅的透明主题
让publisher=PassthroughSubject()
让我们看看时机:加倍
var timerHandler:计时器?=nil
初始(定时:双精度){
自我计时=计时
}
func start(){
//只需启动一个调用generateEvent的计时器来模拟一些事件
timerHandler=Timer.scheduledTimer(withTimeInterval:Timeing,repeats:true){
[弱自我]uu-in
self?.generateEvent()
}
timerHandler?.fire()
}
函数停止(){
publisher.send(完成:。已完成)//通知所有已完成的
}
私有函数generateEvent(){
let events=[“新玩家”、“玩家断开连接”、“服务器错误”]
guard let currentEvent=events.randomElement()else{return}
publisher.send(currentEvent)//发送给所有订阅者
}
}
//用法
类ViewModel:ObservableObject{
private let server=SocketServerManager(计时:1)
private var cancelables=Set()
函数设置(){
guard Cancelables.isEmpty else{return}//已设置
//添加一个示例订阅服务器
server.publisher
.assign(给:\.value1,开:self)
.store(在:&可取消项中)
//添加另一个示例订阅服务器
server.publisher
.sink(receiveValue:{中的值
self.value2=值
})
.store(在:&可取消项中)
server.start()
}
@已发布的变量值1:String=“”
@已发布的变量值2:String=“”
}
//查看演示
结构TestSocketServerPublisher:视图{
@ObservedObject var viewModel=viewModel()
var body:一些观点{
VStack{
文本(“Observer1:\(viewModel.value1)”)
分隔器()
文本(“Observer2:\(viewModel.value2)”)
}
奥纳佩尔先生{
self.viewModel.setup()
}
}
}
结构TestSocketServerPublisher\u预览:PreviewProvider{
静态var预览:一些视图{
TestSocketServerPublisher()
}
}
// PUBLISHER CODE ----------
func receive<S>(subscriber: S)
where S:Subscriber,
EventsPublisher.Failure == S.Failure,
EventsPublisher.Output == S.Input {
let subscription = EventSubscription(sub:subscriber, server: self.server)
server.delegates.append(subscription)
subscriber.receive(subscription: subscription)
}
import SwiftUI
import Combine
protocol SocketServerManagerDelegate{
func newEvent(event:String)
}
class SocketServerManager {
// transparent subject that manages subscribers/subscriptions
let publisher = PassthroughSubject<String, Never>()
let timing: Double
var timerHandler:Timer? = nil
init(timing:Double){
self.timing = timing
}
func start(){
// Just start a timer that calls generateEvent to simulate some events
timerHandler = Timer.scheduledTimer(withTimeInterval: timing, repeats: true){
[weak self] _ in
self?.generateEvent()
}
timerHandler?.fire()
}
func stop(){
publisher.send(completion: .finished) // notifies all that finished
}
private func generateEvent(){
let events = ["New Player", "Player Disconnected", "Server Error"]
guard let currentEvent = events.randomElement() else { return }
publisher.send(currentEvent) // send to all subscribers
}
}
// usage
class ViewModel: ObservableObject {
private let server = SocketServerManager(timing: 1)
private var cancellables = Set<AnyCancellable>()
func setup() {
guard cancellables.isEmpty else { return } // already set up
// add one example subscriber
server.publisher
.assign(to: \.value1, on: self)
.store(in: &cancellables)
// add another example subscriber
server.publisher
.sink(receiveValue: { value in
self.value2 = value
})
.store(in: &cancellables)
server.start()
}
@Published var value1: String = "<unknown>"
@Published var value2: String = "<unknown>"
}
// view demo
struct TestSocketServerPublisher: View {
@ObservedObject var viewModel = ViewModel()
var body: some View {
VStack {
Text("Observer1: \(viewModel.value1)")
Divider()
Text("Observer2: \(viewModel.value2)")
}
.onAppear {
self.viewModel.setup()
}
}
}
struct TestSocketServerPublisher_Previews: PreviewProvider {
static var previews: some View {
TestSocketServerPublisher()
}
}