Состав прокотола на том же свойстве - PullRequest
0 голосов
/ 07 февраля 2020

Есть ли способ достичь этого?

protocol VCProtocol1: UIViewController {
    var viewModel: VMProtocol1? { get set }
}

protocol VCProtocol2: UIViewController {
    var viewModel: VMProtocol2? { get set }
}

class VC: UIViewController, VCProtocol1, VCProtocol2 {
    var viewModel: (VMProtocol1 & VMProtocol2)?
}

Что я хочу сделать, так это создать композицию на ViewController, чтобы избежать повторной реализации одного и того же кода в нескольких ViewController.

Редактировать:

Точнее говоря, проблема в том, что я хочу, чтобы мое свойство viewModel было разделено между обоими протоколами, потому что в конечном итоге я хочу реализовать что-то вроде этого:

- Просмотр модели

protocol VMProtocol1 {
    func vmTest1()
}

protocol VMProtocol2 {
    func vmTest2()
}

class ViewModel: VMProtocol1, VMProtocol2 {
    func vmTest1() { }
    func vmTest2() { }
}

- Просмотр контроллера

protocol VCProtocol1: UIViewController {
    var viewModel: VMProtocol1 { get set }

    func vcTest1()
}

extension VCProtocol1 {
    func vcTest1() {
        // This is the key point, I want to be able to refer to my viewModel property internally in each protocol.
        self.viewModel.vmTest1() 
    }
}

protocol VCProtocol2: UIViewController {
    var viewModel: VMProtocol2 { get set }
}

class VC: UIViewController, VCProtocol1, VCProtocol2 {
    var viewModel: (VMProtocol1 & VMProtocol2)?
}

1 Ответ

1 голос
/ 07 февраля 2020

Это на самом деле невозможно. Одна сущность, которая реализует несколько протоколов, которые объявляют одно и то же свойство (здесь viewModel), но с другим типом, просто невозможна в Swift.

Самое близкое, что вы можете сделать, это использовать протокол, который определяет тип viewModel в качестве связанного типа и предоставьте условные расширения (это заставит вас использовать обобщенную c реализацию).

Обратите внимание, что это сложная реализация, требующая хорошего знания generi c протоколы. Я не рекомендовал бы использовать такой сложный дизайн, не понимая точно, что вы делаете.

Просмотр модели

protocol VMProtocol1 {
    func vmTest1()
}

protocol VMProtocol2 {
    func vmTest2()
}

class ViewModel: VMProtocol1, VMProtocol2 {
    func vmTest1() { }
    func vmTest2() { }
}

Реализация

protocol VCProtocolBase {
    associatedtype ViewModel
    var viewModel: ViewModel { get }
}

protocol VCProtocol1: VCProtocolBase {
    func vmTest1()
}

protocol VCProtocol2: VCProtocolBase {
    func vmTest2()
}

extension VCProtocolBase where Self: VCProtocol1, Self.ViewModel: VMProtocol1 {
    func vmTest1() {
        viewModel.vmTest1()
    }
}

extension VCProtocolBase where Self: VCProtocol2, Self.ViewModel: VMProtocol2 {
    func vmTest2() {
        viewModel.vmTest2()
    }
}


final class VC<ViewModel: VMProtocol1 & VMProtocol2>: VCProtocolBase, VCProtocol1, VCProtocol2 {
    var viewModel: ViewModel

    init(viewModel: ViewModel) {
        self.viewModel = viewModel
    }
}

VC(viewModel: ViewModel()).vmTest1()
VC(viewModel: ViewModel()).vmTest2()

Идея заключается в том, чтобы полагаться на универсальные и условные расширения, чтобы обеспечить реализации по умолчанию для VCProtocolX, который является ролью VCProtocolBase.

...