Делегаты быстро?
Как можно сделать делегат, т.е. NSUserNotificationCenterDelegate
в swift?
Ответы
Ответ 1
Это не отличается от obj-c.
Во-первых, вы должны указать протокол в своем объявлении класса, например:
class MyClass: NSUserNotificationCenterDelegate
Реализация будет выглядеть следующим образом:
// NSUserNotificationCenterDelegate implementation
func userNotificationCenter(center: NSUserNotificationCenter, didDeliverNotification notification: NSUserNotification) {
//implementation
}
func userNotificationCenter(center: NSUserNotificationCenter, didActivateNotification notification: NSUserNotification) {
//implementation
}
func userNotificationCenter(center: NSUserNotificationCenter, shouldPresentNotification notification: NSUserNotification) -> Bool {
//implementation
return true
}
Конечно, вы должны установить делегат. Например:
NSUserNotificationCenter.defaultUserNotificationCenter().delegate = self;
Ответ 2
Здесь небольшая помощь делегатам между двумя контроллерами представлений:
Шаг 1. Сделайте протокол в UIViewController, который вы будете удалять/будет отправлять данные.
protocol FooTwoViewControllerDelegate:class {
func myVCDidFinish(_ controller: FooTwoViewController, text: String)
}
Шаг 2. Объявите делегат в отправляющем классе (то есть UIViewcontroller)
class FooTwoViewController: UIViewController {
weak var delegate: FooTwoViewControllerDelegate?
[snip...]
}
Шаг 3: используйте делегат в методе класса для отправки данных методу приема, который является любым методом, использующим протокол.
@IBAction func saveColor(_ sender: UIBarButtonItem) {
delegate?.myVCDidFinish(self, text: colorLabel.text) //assuming the delegate is assigned otherwise error
}
Шаг 4: Принять протокол в принимающем классе
class ViewController: UIViewController, FooTwoViewControllerDelegate {
Шаг 5: Внедрите метод делегата
func myVCDidFinish(_ controller: FooTwoViewController, text: String) {
colorLabel.text = "The Color is " + text
controller.navigationController.popViewController(animated: true)
}
Шаг 6: Установите делегат в файле prepareForSegue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "mySegue" {
let vc = segue.destination as! FooTwoViewController
vc.colorString = colorLabel.text
vc.delegate = self
}
}
И это должно сработать. Это, конечно, только фрагменты кода, но вы должны дать вам эту идею. Для подробного объяснения этого кода вы можете перейти к моей записи в блоге:
segues и делегаты
Если вас интересует, что происходит под капотом с делегатом, я писал об этом здесь:
под капотом с делегатами
Ответ 3
Делегаты всегда путали меня, пока я не понял, что делегат - это просто класс, который выполняет некоторую работу для другого класса. Это похоже на то, что у кого-то еще есть для вас вся грязная работа, которую вы не хотите делать сами.
Я написал небольшую историю, чтобы проиллюстрировать это. Прочтите его на игровой площадке, если хотите.
Когда-то...
// MARK: Background to the story
// A protocol is like a list of rules that need to be followed.
protocol OlderSiblingDelegate: class {
// The following command (ie, method) must be obeyed by any
// underling (ie, delegate) of the older sibling.
func getYourNiceOlderSiblingAGlassOfWater()
}
// MARK: Characters in the story
class BossyBigBrother {
// I can make whichever little sibling is around at
// the time be my delegate (ie, slave)
weak var delegate: OlderSiblingDelegate?
func tellSomebodyToGetMeSomeWater() {
// The delegate is optional because even though
// I'm thirsty, there might not be anyone nearby
// that I can boss around.
delegate?.getYourNiceOlderSiblingAGlassOfWater()
}
}
// Poor little sisters have to follow (or at least acknowledge)
// their older sibling rules (ie, protocol)
class PoorLittleSister: OlderSiblingDelegate {
func getYourNiceOlderSiblingAGlassOfWater() {
// Little sis follows the letter of the law (ie, protocol),
// but no one said exactly how she had to respond.
print("Go get it yourself!")
}
}
// MARK: The Story
// Big bro is laying on the couch watching basketball on TV.
let bigBro = BossyBigBrother()
// He has a little sister named Sally.
let sally = PoorLittleSister()
// Sally walks into the room. How convenient! Now big bro
// has someone there to boss around.
bigBro.delegate = sally
// So he tells her to get him some water.
bigBro.tellSomebodyToGetMeSomeWater()
// Unfortunately no one lived happily ever after...
// The end.
В обзоре есть три ключевые части для создания и использования шаблона делегата.
- протокол, который определяет, что нужно делать работнику
- класс boss, который имеет переменную делегата, которую он использует, чтобы сообщить классу рабочего, что делать
- рабочий класс, который принимает протокол и выполняет то, что требуется
Реальная жизнь
В сравнении с нашей историей Bossy Big Brother делегаты часто используются для следующих практических приложений:
- Коммуникация: одному классу необходимо отправить некоторую информацию другому классу.
- Настройка: один класс хочет разрешить другому классу настраивать его.
Большая часть состоит в том, что этим классам не нужно ничего знать друг о друге заранее, за исключением того, что класс делегата соответствует требуемому протоколу.
Я настоятельно рекомендую прочитать следующие две статьи. Они помогли мне понять делегатов даже лучше, чем documentation.
Еще одно примечание
Делегаты, которые ссылаются на другие классы, которым они не владеют, должны использовать ключевое слово weak
, чтобы избежать сильных эталонных циклов. Подробнее см. этот ответ.
Ответ 4
У меня мало поправок к сообщению @MakeAppPie
Во-первых, когда вы создаете протокол делегата, он должен соответствовать протоколу Class. Как в примере ниже.
protocol ProtocolDelegate: class {
func myMethod(controller:ViewController, text:String)
}
Во-вторых, ваш делегат должен быть слабым, чтобы избежать цикла сохранения.
class ViewController: UIViewController {
weak var delegate: ProtocolDelegate?
}
Наконец, вы в безопасности, потому что ваш протокол является необязательным значением. Это означает, что его сообщение "nil" не будет отправлено на это свойство. Он похож на условное утверждение с respondToselector
в objC, но здесь у вас есть все в одной строке:
if ([self.delegate respondsToSelector:@selector(myMethod:text:)]) {
[self.delegate myMethod:self text:@"you Text"];
}
У вас есть пример obj-C, и ниже у вас есть пример Swift того, как он выглядит.
delegate?.myMethod(self, text:"your Text")
Ответ 5
Здесь gist Я собрал вместе. Мне было интересно то же самое, и это помогло улучшить мое понимание. Откройте это в Xcode Playground, чтобы узнать, что происходит.
protocol YelpRequestDelegate {
func getYelpData() -> AnyObject
func processYelpData(data: NSData) -> NSData
}
class YelpAPI {
var delegate: YelpRequestDelegate?
func getData() {
println("data being retrieved...")
let data: AnyObject? = delegate?.getYelpData()
}
func processYelpData(data: NSData) {
println("data being processed...")
let data = delegate?.processYelpData(data)
}
}
class Controller: YelpRequestDelegate {
init() {
var yelpAPI = YelpAPI()
yelpAPI.delegate = self
yelpAPI.getData()
}
func getYelpData() -> AnyObject {
println("getYelpData called")
return NSData()
}
func processYelpData(data: NSData) -> NSData {
println("processYelpData called")
return NSData()
}
}
var controller = Controller()
Ответ 6
DELEGATES IN SWIFT 2
Я объясняю примером делегата с двумя viewControllers. В этом случае объект SecondVC отправляет данные обратно в первый контроллер просмотра.
Класс с объявлением протокола
protocol getDataDelegate {
func getDataFromAnotherVC(temp: String)
}
import UIKit
class SecondVC: UIViewController {
var delegateCustom : getDataDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func backToMainVC(sender: AnyObject) {
//calling method defined in first View Controller with Object
self.delegateCustom?.getDataFromAnotherVC("I am sending data from second controller to first view controller.Its my first delegate example. I am done with custom delegates.")
self.navigationController?.popViewControllerAnimated(true)
}
}
В First ViewController протокол выполняется здесь:
class ViewController: UIViewController, getDataDelegate
Определение метода протокола в First View Controller (ViewController)
func getDataFromAnotherVC(dataString : String)
{
// dataString from SecondVC
lblForData.text = dataString
}
Во время нажатия SecondVC из первого контроллера просмотра (ViewController)
let objectPush = SecondVC()
objectPush.delegateCustom = self
self.navigationController.pushViewController(objectPush, animated: true)
Ответ 7
Первый класс:
protocol NetworkServiceDelegate: class {
func didCompleteRequest(result: String)
}
class NetworkService: NSObject {
weak var delegate: NetworkServiceDelegate?
func fetchDataFromURL(url : String) {
delegate?.didCompleteRequest(url)
}
}
Второй класс:
class ViewController: UIViewController, NetworkServiceDelegate {
let network = NetworkService()
override func viewDidLoad() {
super.viewDidLoad()
network.delegate = self
network.fetchDataFromURL("Success!")
}
func didCompleteRequest(result: String) {
print(result)
}
}
Ответ 8
Очень просто шаг за шагом (100% работает и тестируется)
step1: Создать метод на контроллере первого представления
func updateProcessStatus(isCompleted : Bool){
if isCompleted{
self.labelStatus.text = "Process is completed"
}else{
self.labelStatus.text = "Process is in progress"
}
}
step2: Установите делегат, пока нажмите контроллер второго представления
@IBAction func buttonAction(_ sender: Any) {
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController") as! secondViewController
secondViewController.delegate = self
self.navigationController?.pushViewController(secondViewController, animated: true)
}
step3: установите делегат как
класс ViewController: UIViewController, ProcessStatusDelegate {
step4: Создать протокол
protocol ProcessStatusDelegate:NSObjectProtocol{
func updateProcessStatus(isCompleted : Bool)
}
step5: взять переменную
var delegate:ProcessStatusDelegate?
step6: вернитесь к предыдущему методу делегата вызова диспетчера представлений, поэтому первый контроллер просмотра уведомляет данные
@IBAction func buttonActionBack(_ sender: Any) {
delegate?.updateProcessStatus(isCompleted: true)
self.navigationController?.popViewController(animated: true)
}
@IBAction func buttonProgress(_ sender: Any) {
delegate?.updateProcessStatus(isCompleted: false)
self.navigationController?.popViewController(animated: true)
}
Ответ 9
Делегаты представляют собой шаблон проектирования, который позволяет одному объекту отправлять сообщения другому объекту при возникновении определенного события.
Представьте, что объект A вызывает объект B для выполнения действия. Как только действие будет завершено, объект A должен знать, что B выполнил задачу и предпримет необходимые действия, это может быть достигнуто с помощью делегатов!
Ниже приведено руководство по реализации делегатов шаг за шагом в swift 3
Ссылка на учебное пособие
Ответ 10
Простой пример:
protocol Work: class {
func doSomething()
}
class Manager {
weak var delegate: Work?
func passAlong() {
delegate?.doSomething()
}
}
class Employee: Work {
func doSomething() {
print("Working on it")
}
}
let manager = Manager()
let developer = Employee()
manager.delegate = developer
manager.passAlong() // PRINTS: Working on it
Ответ 11
Вышеприведенные решения, казалось, немного связаны друг с другом и в то же время избегают повторного использования одного и того же протокола в других контроллерах, поэтому я пришел с более сильным решением, использующим универсальное стирание типов.
@noreturn public func notImplemented(){
fatalError("not implemented yet")
}
public protocol DataChangedProtocol: class{
typealias DataType
func onChange(t:DataType)
}
class AbstractDataChangedWrapper<DataType> : DataChangedProtocol{
func onChange(t: DataType) {
notImplemented()
}
}
class AnyDataChangedWrapper<T: DataChangedProtocol> : AbstractDataChangedWrapper<T.DataType>{
var base: T
init(_ base: T ){
self.base = base
}
override func onChange(t: T.DataType) {
base.onChange(t)
}
}
class AnyDataChangedProtocol<DataType> : DataChangedProtocol{
var base: AbstractDataChangedWrapper<DataType>
init<S: DataChangedProtocol where S.DataType == DataType>(_ s: S){
self.base = AnyDataChangedWrapper(s)
}
func onChange(t: DataType) {
base.onChange(t)
}
}
class Source : DataChangedProtocol {
func onChange(data: String) {
print( "got new value \(data)" )
}
}
class Target {
var delegate: AnyDataChangedProtocol<String>?
func reportChange(data:String ){
delegate?.onChange(data)
}
}
var source = Source()
var target = Target()
target.delegate = AnyDataChangedProtocol(source)
target.reportChange("newValue")
вывод: получил новое значение newValue
Ответ 12
В быстрой версии 4.0
Создайте делегат в классе, который должен отправить некоторые данные или предоставить некоторые функции другим классам
Как
protocol GetGameStatus {
var score: score { get }
func getPlayerDetails()
}
После этого в классе, который собирается подтвердить этому делегату
class SnakesAndLadders: GetGameStatus {
func getPlayerDetails() {
}
}