Необязательный метод делегата, необязательный - PullRequest
0 голосов
/ 13 октября 2018

У меня есть этот класс 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

EDIT //////

Итак, в моем 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 ведут себя опционально, т.е. мне не нужнореализовать их в viewControllers, которые являются делегатами apiHandler. 2) didLogin так или иначе НУЖЕН быть реализованным, в противном случае приложение вылетает

. Основное различие между 1) и 2) состоит в том, что у didLogin есть блок завершения.Мне нужно иметь логическое значение в моих ViewControllers

Ответы [ 4 ]

0 голосов
/ 13 октября 2018

Возможно, вам потребуется изменить эту строку:

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

Кому:

self.delegate?.didLogin?(success: success, sender: self)
0 голосов
/ 13 октября 2018

Вы можете легко сделать это необязательным, выполнив следующие действия без кода 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

0 голосов
/ 13 октября 2018

Не понимаю ли я необязательную часть?Я хочу иметь возможность просто реализовать те методы делегата, которые необходимы для моего viewController

Что касается протоколов, optional просто означает, что компилятор не будет настаивать на том, чтобы классы, которые принимают протоколреализовать эти методы.Напротив, компилятор выдаст ошибку, если вам не удастся реализовать методы, помеченные required.

Однако, если ваш код попытается вызвать метод optional, который не был реализован, вы получитеневыполненная ошибка времени выполнения селектора, которую вы видите здесь.Если вы создаете протокол с optional методами, вы должны проверить, что объект реализует этот метод, прежде чем вызывать его, например:

if someObject.responds(to:Selector("didLoginSuccess:sender:") {
    someObject.didLogin(success:... sender:...)
}

Другими словами, компилятор не будет препятствовать вам вызов необязательный метод;вам нужно убедиться, что дополнительные методы, которые вы вызываете, действительно существуют.

0 голосов
/ 13 октября 2018

Я думаю, что если вы вызываете didLoginWithSuccess из кода Swift для дополнительных функций, вам нужно использовать необязательную цепочку:

apiHandler.didLoginWithSuccess?()

Если вы вызываете didLoginWithSuccess из кода Objective-C, вам нужно проверить, является ли объектотвечает на данный селектор:

if ([apiHandler respondsToSelector:@selector(didLoginWithSuccess:)])
{
    // then call func
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...