Ios 如何用RxSwift中的DelegateProxy替换协议?

Ios 如何用RxSwift中的DelegateProxy替换协议?,ios,swift,rx-swift,Ios,Swift,Rx Swift,我开始意识到使用RxSwift的好处,并尝试将其合并到我的代码中,但我不确定我是否理解DelegateProxy的用法 目前在我的代码中,我有以下内容: struct SampleModel: Decodable { var first_name: String var last_name: String init(first_name: String, last_name: String) { self.first_name = first_n

我开始意识到使用
RxSwift
的好处,并尝试将其合并到我的代码中,但我不确定我是否理解
DelegateProxy
的用法

目前在我的代码中,我有以下内容:

struct SampleModel: Decodable
{
    var first_name: String
    var last_name: String

    init(first_name: String, last_name: String)
    {
        self.first_name = first_name
        self.last_name = last_name
    }
}

class ViewModel
{
    var model: SampleModel

    public var fullName: String {
        return model.first_name + model.last_name
    }

    init(model: SampleModel)
    {
        self.model = model
    }
}
我使用的协议和委托如下:

protocol NetworkDelegate
{
    func dataReceived(data: [Decodable]?, error: Error?)
}

class Network: NSObject
{
    var databaseLink = String()

    var networkDelegate: NetworkDelegate!

    init(databaseLink: String)
    {
        super.init()

        self.databaseLink = databaseLink
    }

    func getDatabaseData<T: Decodable>(model: T.Type)
    {
        guard let url = URL(string: databaseURL) else {
            return
        }

        request(url).responseJSON { (json) in
            switch json.result
            {
                case .success:
                    guard let data = json.data else {
                        return
                    }

                    do
                    {
                        let models = try JSONDecoder().decode([T].self,
                                                              from: data)

                        self.networkDelegate.dataReceived(data: models,
                                                          error: nil)
                    }
                    catch let jsonErr
                    {
                        print(jsonErr)
                    }

                case .failure(let error):
                    self.networkDelegate.dataReceived(data: nil,
                                                      error: error)
            }
        }
    }
}

extension ViewController: NetworkDelegate
{
    func dataReceived(data: [Decodable]?, error: Error?)
    {
        guard let models = data else {
            return
        }

        for model in models
        {
            guard let myModel = model as? SampleModel else {
                return
            }

            viewModels.append( ViewModel(model: myModel) )
        }
    }
}

var viewModels = [ViewModel]()
weak var networkDelegate: NetworkDelegate?

override func viewDidLoad()
{
    super.viewDidLoad()

    let network = Network(databaseLink: "some url")
    network.networkDelegate = self
    network.getDatabaseData(model: SampleModel.self)
}
然而,我后来对如何实现其余的功能和像原来那样使用感到有点困惑:

let network = Network(databaseLink: "some url")
network.networkDelegate = self
network.getDatabaseData(model: SampleModel.self)

我怎样才能做到这一点?谢谢。

DelegateProxy
应该在与依赖于
委托的Cocoa API集成时使用

如果你要走Rx的路,把一切都看成是一连串的事件

让我们看看如何将您的代码转换为可观察的:

func getDatabaseData<T: Decodable>() -> Observable<[T]>
{
    guard let url = URL(string: databaseURL) else {
        return .error(NetworkServiceErrors.missingDatabaseURL)
    }

    return Observable.create { observer in
        self.request(url).responseJSON { (json) in
            switch json.result {
            case .success:
                guard let data = json.data else {
                    return observer.onError(NetworkServiceErrors.noData)
                }

                do
                {
                    let models = try JSONDecoder().decode([T].self,
                                                          from: data)

                    observer.onNext(models)
                }
                catch let jsonErr
                {
                    observer.onError(NetworkServiceErrors.parsingError(jsonErr))
                }

            case .failure(let error):
                observer.onError(NetworkServiceErrors.someError(error))
            }
            observer.onCompleted()

            return Disposables.create { /* usually some code to cancel the request */ }
        }
    }
}
这只是一个基本示例,我还没有测试代码,但它应该能让您了解您可以做什么


您可以查看
Moya
(一个网络库)和
RxMoya
,以了解更高级的实现或获得灵感。

委托代理依赖于objc消息调度来拦截github.com/ReactiveX/RxSwift/issues/1442#issuecomment-335475647
func getDatabaseData<T: Decodable>() -> Observable<[T]>
{
    guard let url = URL(string: databaseURL) else {
        return .error(NetworkServiceErrors.missingDatabaseURL)
    }

    return Observable.create { observer in
        self.request(url).responseJSON { (json) in
            switch json.result {
            case .success:
                guard let data = json.data else {
                    return observer.onError(NetworkServiceErrors.noData)
                }

                do
                {
                    let models = try JSONDecoder().decode([T].self,
                                                          from: data)

                    observer.onNext(models)
                }
                catch let jsonErr
                {
                    observer.onError(NetworkServiceErrors.parsingError(jsonErr))
                }

            case .failure(let error):
                observer.onError(NetworkServiceErrors.someError(error))
            }
            observer.onCompleted()

            return Disposables.create { /* usually some code to cancel the request */ }
        }
    }
}
class MyListViewModel {
    // inputs
    let loadData: AnyObserver<Void>

    // outputs
    let myModels: Driver<[SampleModel]>

    private let network = Network(databaseLink: "some url")

    init() {
        let loadData = PublishRelay<Void>()
        self.loadData = loadData.asObserver()

        self.myModels = loadData.flatMapLatest { _ -> Driver<[SampleModel]>
            return network.getDatabaseData().asDriver(onErrorJustReturn: [])
        }
    }
}
let viewModel = MyListViewModel()
let disposeBag = DisposeBag()

func viewDidLoad() {
    super.viewDidLoad()

    bindViewModel()
}

func viewWillAppear() {
    super.viewWillAppear()

    // trigger loading of your data
    viewModel.loadData.onNext(())
}

func bindViewModel() {
    // some button that reloads data
    button.rx.tap.subscribe(viewModel.loadData).disposed(by: disposeBag)

    // will log all events but you should actually use it to drive the content of a tableview for example
    viewModel.myModels.debug().drive().disposed(by: disposeBag)
}