Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift将订阅、正确的流程和体系结构选择结合起来_Swift_Combine - Fatal编程技术网

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()
    }
}