delegate delegado delegates swift delegation

delegates - delegate - delegado swift



Los delegados en swift? (12)

¿Cómo se hace para crear un delegado, es decir, NSUserNotificationCenterDelegate en forma rápida?


En veloz 4.0

Crear un delegado en la clase que necesita enviar algunos datos o proporcionar alguna funcionalidad a otras clases

Me gusta

protocol GetGameStatus { var score: score { get } func getPlayerDetails() }

Después de eso en la clase que va a confirmar a este delegado

class SnakesAndLadders: GetGameStatus { func getPlayerDetails() { } }


Aquí hay un poco de ayuda sobre los delegados entre dos controladores de vista:

Paso 1: Cree un protocolo en el UIViewController que va a eliminar / enviará los datos.

protocol FooTwoViewControllerDelegate:class { func myVCDidFinish(_ controller: FooTwoViewController, text: String) }

Paso 2: Declare el delegado en la clase de envío (es decir, UIViewcontroller)

class FooTwoViewController: UIViewController { weak var delegate: FooTwoViewControllerDelegate? [snip...] }

Paso 3: utilice el delegado en un método de clase para enviar los datos al método de recepción, que es cualquier método que adopta el protocolo.

@IBAction func saveColor(_ sender: UIBarButtonItem) { delegate?.myVCDidFinish(self, text: colorLabel.text) //assuming the delegate is assigned otherwise error }

Paso 4: adopte el protocolo en la clase de recepción

class ViewController: UIViewController, FooTwoViewControllerDelegate {

Paso 5: Implementar el método delegado

func myVCDidFinish(_ controller: FooTwoViewController, text: String) { colorLabel.text = "The Color is " + text controller.navigationController.popViewController(animated: true) }

Paso 6: configure el delegado en 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 } }

Y eso debería funcionar Esto es, por supuesto, solo fragmentos de código, pero debería darle la idea. Para una explicación larga de este código, puede ir a la entrada de mi blog aquí:

segues y delegados

Si está interesado en lo que está pasando bajo el capó con un delegado, lo escribí aquí:

bajo el capó con delegados


Aquí hay una gist que gist . Me preguntaba lo mismo y esto ayudó a mejorar mi comprensión. Abra esto en un Xcode Playground para ver qué está pasando.

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()


Conseguí algunas correcciones a la publicación de @MakeAppPie

Lo primero que debe hacer al crear un protocolo de delegado debe ser conforme al protocolo de Clase. Como en el ejemplo a continuación.

protocol ProtocolDelegate: class { func myMethod(controller:ViewController, text:String) }

Segundo, su delegado debe ser débil para evitar retener el ciclo.

class ViewController: UIViewController { weak var delegate: ProtocolDelegate? }

Por último, está seguro porque su protocolo es un valor opcional. Eso significa que su mensaje "nulo" no se enviará a esta propiedad. Es similar al enunciado condicional con respondToselector en objC, pero aquí tienes todo en una línea:

if ([self.delegate respondsToSelector:@selector(myMethod:text:)]) { [self.delegate myMethod:self text:@"you Text"]; }

Arriba tienes un ejemplo obj-C y debajo tienes un ejemplo Swift de cómo se ve.

delegate?.myMethod(self, text:"your Text")


Las soluciones anteriores parecían un poco acopladas y, al mismo tiempo, evitaban reutilizar el mismo protocolo en otros controladores, es por eso que he venido con la solución que es más tipada usando el borrado de tipos genérico.

@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")

salida : obtuvo un nuevo valor nuevoValor


Los delegados siempre me confundieron hasta que me di cuenta de que un delegado es solo una clase que trabaja para otra clase . Es como tener a alguien más allí para que haga todo el trabajo sucio por ti que no quieres hacer tú mismo.

Escribí una pequeña historia para ilustrar esto. Léelo en un patio de recreo si quieres.

Había una vez...

// 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''s 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.

En resumen, hay tres partes clave para hacer y usar el patrón de delegado.

  1. el protocolo que define lo que el trabajador necesita hacer
  2. la clase jefe que tiene una variable de delegado, que usa para decirle a la clase trabajadora qué hacer
  3. la clase trabajadora que adopta el protocolo y hace lo que se requiere

Vida real

En comparación con nuestra historia Bossy Big Brother anterior, los delegados se utilizan a menudo para las siguientes aplicaciones prácticas:

  1. Comunicación : una clase necesita enviar información a otra clase.
    • Ejemplo de código 1: enviar datos de un controlador de vista a otro
    • Ejemplo de código 2: enviar texto de un teclado personalizado a un campo de texto
  2. Personalización : una clase quiere permitir que otra clase la personalice.

La gran parte es que estas clases no necesitan saber nada el uno del otro de antemano, excepto que la clase de delegado se ajusta al protocolo requerido.

Recomiendo leer los siguientes dos artículos. Me ayudaron a entender a los delegados incluso mejor que la documentation .

Una nota más

Los delegados que hacen referencia a otras clases que no les pertenecen deben usar la palabra clave weak para evitar fuertes ciclos de referencia. Vea esta respuesta para más detalles.


Los delegados son un patrón de diseño que permite que un objeto envíe mensajes a otro objeto cuando ocurre un evento específico. Imagine que un objeto A llama a un objeto B para realizar una acción. Una vez que se completa la acción, el objeto A debe saber que B ha completado la tarea y tomar las medidas necesarias, ¡esto se puede lograr con la ayuda de delegados! Aquí hay un tutorial que implementa delegados paso a paso en rápida 3

Enlace Tutorial


No es tan diferente de obj-c. Primero, debe especificar el protocolo en su declaración de clase, como por ejemplo:

class MyClass: NSUserNotificationCenterDelegate

La implementación se verá como sigue:

// 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 }

Por supuesto, tienes que configurar el delegado. Por ejemplo:

NSUserNotificationCenter.defaultUserNotificationCenter().delegate = self;


Primera clase:

protocol NetworkServiceDelegate: class { func didCompleteRequest(result: String) } class NetworkService: NSObject { weak var delegate: NetworkServiceDelegate? func fetchDataFromURL(url : String) { delegate?.didCompleteRequest(url) } }

Segunda clase:

class ViewController: UIViewController, NetworkServiceDelegate { let network = NetworkService() override func viewDidLoad() { super.viewDidLoad() network.delegate = self network.fetchDataFromURL("Success!") } func didCompleteRequest(result: String) { print(result) } }


DELEGADOS EN SWIFT 2

Estoy explicando con el ejemplo de Delegate con dos viewControllers. En este caso, SecondVC Object está enviando datos a la primera View Controller.

Clase con declaración de protocolo

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) } }

En First ViewController Protocol se realiza aquí:

class ViewController: UIViewController, getDataDelegate

Definición del método de protocolo en First View Controller (ViewController)

func getDataFromAnotherVC(dataString : String) { // dataString from SecondVC lblForData.text = dataString }

Durante empujar el SecondVC desde el controlador de primera vista (ViewController)

let objectPush = SecondVC() objectPush.delegateCustom = self self.navigationController.pushViewController(objectPush, animated: true)


Ejemplo simple:

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


Muy fácil paso a paso (100% trabajando y probado)

paso1: Crear método en el controlador de primera vista

func updateProcessStatus(isCompleted : Bool){ if isCompleted{ self.labelStatus.text = "Process is completed" }else{ self.labelStatus.text = "Process is in progress" } }

Paso 2: establece el delegado mientras presionas para ver el segundo controlador

@IBAction func buttonAction(_ sender: Any) { let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController") as! secondViewController secondViewController.delegate = self self.navigationController?.pushViewController(secondViewController, animated: true) }

paso 3: configurar delegado como

class ViewController: UIViewController, ProcessStatusDelegate {

paso4: Crear protocolo

protocol ProcessStatusDelegate:NSObjectProtocol{ func updateProcessStatus(isCompleted : Bool) }

paso 5: tomar una variable

var delegate:ProcessStatusDelegate?

Paso 6: Cuando regrese a la vista anterior, llame al controlador delegue el método para que primero vea el controlador notificar con datos

@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) }