可选的委托方法不是可选的

时间:2018-10-13 11:47:06

标签: swift delegates optional

我的此类apiHandler具有以下委托方法:

@objc protocol apiHandlerDelegate: class {
    @objc optional func didGetMessages(_ sender:apiHandler)
    @objc optional func didGetEvents(_ sender:apiHandler)
    @objc optional func didLogin(success:Bool, sender:apiHandler)
}

我的viewControllers之一取决于didGetEvents,所以我这样做

class myViewController: UIViewController, apiHandlerDelegate

现在,以某种方式,在myViewController中,我还需要实现

func didLogin(success: Bool, sender: apiHandler) {
    // do nothing
}

否则该应用将崩溃,返回

  

[myApp。 myViewController didLoginWithSuccess:sender:]:无法识别   选择器发送到实例0x7f90ac01b410'

我是否误解了可选部分?我希望能够仅实现我的viewController所需的那些委托方法

编辑//////

因此,在我的apiHandler中,我进行了REST调用,并在完成代码块中这样调用didLogin:

let urlString = String(format:"%@/api/sessions/current", baseUrl)
                    Alamofire.request(urlString, headers: headers)
                        .responseJSON { response in
                            self.Login(completion: { (success) in
                                self.delegate?.didLogin!(success: success, sender: self)
                                completion(true)
                            })
                    }

要知道的重要是: 1) didGetMessages didGetEvents 的行为是可选的,即,我不需要在作为apiHandler委托的viewControllers中实现它们 2)didLogin以某种方式需要实现,否则应用程序崩溃

1)和2)之间的主要区别是didLogin有一个完成块。我需要在ViewControllers中具有布尔值

4 个答案:

答案 0 :(得分:2)

我认为,如果您从Swift代码中调用didLoginWithSuccess以获取可选功能,则需要使用可选链接:

apiHandler.didLoginWithSuccess?()

如果您从Objective-C代码调用didLoginWithSuccess,则需要检查对象是否响应给定的选择器:

if ([apiHandler respondsToSelector:@selector(didLoginWithSuccess:)])
{
    // then call func
}

答案 1 :(得分:2)

您可能需要更改此行:

self.delegate?.didLogin!(success: success, sender: self)

收件人:

self.delegate?.didLogin?(success: success, sender: self)

答案 2 :(得分:1)

您可以通过以下操作轻松地使其成为可选对象,而无需使用任何ObjectiveC代码:

protocol apiHandlerDelegate: class {
    func didGetMessages(_ sender:apiHandler)
    func didGetEvents(_ sender:apiHandler)
    func didLogin(success:Bool, sender:apiHandler)
}

extension apiHandlerDelegate {
    func didGetMessages(_ sender:apiHandler) { } // Empty implementation to make it optional
    func didGetEvents(_ sender:apiHandler) { } // Empty implementation to make it optional
    func didLogin(success:Bool, sender:apiHandler) { } // Empty implementation to make it optional
}

有关更多信息,请查看以下链接:https://medium.com/@ant_one/how-to-have-optional-methods-in-protocol-in-pure-swift-without-using-objc-53151cddf4ce

答案 3 :(得分:1)

  

我是否误解了可选部分?我希望能够仅实现我的viewController所需的那些委托方法

{this.state.categories.filter(searchingFor(this.state.search)) .map((category) => { return <Category key={category.id} categoryId={category.id} categoryName={category.name} /> })} 与协议有关,仅表示编译器不会坚持要求采用协议的类实现这些方法。相反,如果您无法实现标记为optional的方法,则编译器将发出错误。

但是,如果您的代码尝试调用尚未实现的required方法,则会在此看到未实现的选择器运行时错误。如果使用optional方法创建协议,则应在调用它之前检查对象是否实现了该方法,例如:

optional

换句话说,编译器不会阻止您调用可选方法。您必须确保所调用的可选方法确实存在。