调用协议的变异函数生成“没有成员'functionName'”错误

时间:2018-12-23 17:52:33

标签: ios swift struct swift-protocols

这是我的协议:

protocol RequestLocationAuthorizationPresenterProtocol {
    mutating func handleLoad(for view: RequestLocationAuthorizationViewProtocol)
    func handleGivePermissionAction()
}

这是我的协议实现:

struct RequestLocationAuthorizationPresenter: RequestLocationAuthorizationPresenterProtocol {
    private let interactor: RequestLocationAuthorizationInteractorProtocol
    private let router: RequestLocationAuthorizationRouterProtocol
    private weak var view: RequestLocationAuthorizationViewProtocol!

    init(with interactor: RequestLocationAuthorizationInteractorProtocol,
     router: RequestLocationAuthorizationRouterProtocol) {
        self.interactor = interactor
        self.router = router
    }

    mutating func handleLoad(for view: RequestLocationAuthorizationViewProtocol) {
        self.view = view
    }

    func handleGivePermissionAction() {
        self.interactor.requestAuthorization { result in
            switch result {
            case .success:
                self.router.goToWeatherView()
            case .error:
                self.view.presentAlert(with: "Error", message: "The app needs your location in order to work.")
            }
        }
    }
}

当我在View类上调用函数“ handleLoad”时,它可以完美编译。但是,当我从模拟结构调用它时,出现了以下错误:“类型为'RequestLocationAuthorizationPresenterProtocol?的值?没有成员'handleLoad'“

这是我的视图类:

class RequestLocationAuthorizationView: UIViewController {
    private let presenter: RequestLocationAuthorizationPresenterProtocol

    init(with presenter: RequestLocationAuthorizationPresenterProtocol) {
        self.presenter = presenter
        super.init(nibName: "RequestLocationAuthorizationView", bundle: .main)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func presentAlert(with title: String, message: String) {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        self.present(alert, animated: true, completion: nil)
    }

    @IBAction func givePermissionButtonPressed(_ sender: Any) {
        self.presenter.handleGivePermissionAction()
    }
}

这是我的模拟结构:

class RequestLocationAuthorizationViewMock: RequestLocationAuthorizationViewProtocol {
    private let expectation: XCTestExpectation!
    private let expectedTitle: String!
    private let expectedMessage: String!
    private let presenter: RequestLocationAuthorizationPresenterProtocol!

    init(with expectation: XCTestExpectation? = nil,
         expectedTitle: String? = nil,
         expectedMessage: String? = nil,
         presenter: RequestLocationAuthorizationPresenterProtocol? = nil) {
        self.expectation = expectation
        self.expectedTitle = expectedTitle
        self.expectedMessage = expectedMessage
        self.presenter = presenter
    }

    func callPresenterHandleLoad() {
        self.presenter.handleLoad(for: self)
    }

    func callPresenterHandleGivePermissionAction() {
        self.presenter.handleGivePermissionAction()
    }

    func presentAlert(with title: String, message: String) {
        if title == self.expectedTitle && message == self.expectedMessage {
            self.expectation.fulfill()
        }
    }
}

当我将实现更改为类而不是结构并删除 muting 字时,它也可以正常工作。我试图寻找类似的错误,但是我没有运气。我在使用Xcode 10.1并使用Swift Compiler 4.2。

欢迎对此问题发表任何想法。

2 个答案:

答案 0 :(得分:0)

presenter是可选的(即使隐式未包装的可选也是可选的),您也必须为可选链接添加一个问号

func callPresenterHandleLoad() {
    self.presenter?.handleLoad(for: self)
}

但是错误有误导性,现在您得到了真正的错误

  

不能对不可变值使用变异成员:“ presenter”是一个“ let”常量

因此,您必须声明主持人为var有效,并且-强烈建议-作为常规可选内容

private var presenter: RequestLocationAuthorizationPresenterProtocol?

答案 1 :(得分:0)

更仔细地研究这个问题之后,我意识到我正在尝试将一个变异函数称为一个常量值(let),这就是为什么它不起作用的原因。这里的问题是编译器给我一个无意义的错误。我将属性从let更改为var,现在可以使用了。