¿Cómo se hace para hacer un delegado, es decir, NSUserNotificationCenterDelegate
en forma rápida?
¿Cómo se hace para hacer un delegado, es decir, NSUserNotificationCenterDelegate
en forma rápida?
Respuestas:
No es tan diferente de obj-c. Primero, debe especificar el protocolo en su declaración de clase, como a continuación:
class MyClass: NSUserNotificationCenterDelegate
La implementación tendrá el siguiente aspecto:
// 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, debe configurar el delegado. Por ejemplo:
NSUserNotificationCenter.defaultUserNotificationCenter().delegate = self;
@interface MyCustomClass: UIViewController <ClassIWantToUseDelegate>
, permitiéndole iniciar / configurar el viewcontroller, así como llamar a los métodos de delegado en las subvistas? Algo similar a esto ?
Aquí hay una pequeña ayuda sobre los delegados entre dos controladores de vista:
Paso 1: Haga un protocolo en el UIViewController que eliminará / enviará los datos.
protocol FooTwoViewControllerDelegate:class {
func myVCDidFinish(_ controller: FooTwoViewController, text: String)
}
Paso 2: Declarar 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 adopte 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 receptora
class ViewController: UIViewController, FooTwoViewControllerDelegate {
Paso 5: Implemente 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. Por supuesto, esto es solo fragmentos de código, pero debería darle la idea. Para una larga explicación de este código, puede ir a la entrada de mi blog aquí:
Si está interesado en lo que sucede debajo del capó con un delegado, escribí sobre eso aquí:
weak
solo es necesario para clases, no estructuras y enumeraciones. Si el delegado va a ser una estructura o enumeración, entonces no debe preocuparse por los ciclos de retención. Sin embargo, el delegado es una clase (esto es cierto para muchos casos, ya que a menudo es un ViewController), entonces weak
necesita declarar su protocolo como una clase. Hay más información aquí stackoverflow.com/a/34566876/296446
Los delegados siempre me confundieron hasta que me di cuenta de que un delegado es solo una clase que hace algún trabajo para otra clase . Es como tener a alguien más allí para hacer 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 juegos si quieres.
// 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 delegado.
En comparación con nuestra historia Bossy Big Brother anterior, los delegados se utilizan a menudo para las siguientes aplicaciones prácticas:
La gran parte es que estas clases no necesitan saber nada de la otra con anterioridad, excepto que la clase delegada se ajusta al protocolo requerido.
Recomiendo leer los siguientes dos artículos. Me ayudaron a entender a los delegados incluso mejor que la documentación .
Una nota mas
Los delegados que hacen referencia a otras clases que no poseen deben usar la weak
palabra clave para evitar ciclos de referencia fuertes. Vea esta respuesta para más detalles.
Recibí algunas correcciones para publicar en @MakeAppPie
En primer lugar, cuando crea un protocolo de delegado, debe cumplir con el protocolo de clase. Como en el ejemplo a continuación.
protocol ProtocolDelegate: class {
func myMethod(controller:ViewController, text:String)
}
En segundo lugar, su delegado debe ser débil para evitar retener el ciclo.
class ViewController: UIViewController {
weak var delegate: ProtocolDelegate?
}
Por último, está a salvo porque su protocolo es un valor opcional. Eso significa que su mensaje "nulo" no se enviará a esta propiedad. Es similar a la declaración condicional respondToselector
en objC pero aquí tiene todo en una línea:
if ([self.delegate respondsToSelector:@selector(myMethod:text:)]) {
[self.delegate myMethod:self text:@"you Text"];
}
Arriba tienes un ejemplo de obj-C y debajo tienes un ejemplo Swift de cómo se ve.
delegate?.myMethod(self, text:"your Text")
delegate?.myMethod
no se bloqueará porque si delegado es, nil
entonces no pasaría nada. Sin embargo, si cometió un error y escribió delegate!.myMethod
, podría bloquearse si no se establece un delegado, por lo que es básicamente una forma de estar seguro ...
Aquí hay una esencia que puse juntos. Me preguntaba lo mismo y esto ayudó a mejorar mi comprensión. Abre 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()
UIViewController
clase se ajuste al delegado que hicimos? ¿Deben declararse en un archivo rápido? Cualquier ayuda significará mucho.
class ViewController : UIViewController NameOfDelegate
.
a.swift
acuerdo con su respuesta anterior, no aparece b.swift
. No puedo llegar a ninguna clase fuera de mi archivo rápido. cualquier hardts?
DELEGADOS EN SWIFT 2
Estoy explicando con un ejemplo de Delegado con dos viewControllers. En este caso, SecondVC Object está enviando datos de vuelta al primer 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, la conformidad se realiza aquí:
class ViewController: UIViewController, getDataDelegate
Definición del método de protocolo en First View Controller (ViewController)
func getDataFromAnotherVC(temp : String)
{
// dataString from SecondVC
lblForData.text = dataString
}
Durante la inserción de SecondVC desde First View Controller (ViewController)
let objectPush = SecondVC()
objectPush.delegateCustom = self
self.navigationController.pushViewController(objectPush, animated: true)
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)
}
}
Type 'ViewController' does not conform to protocol 'NetworkServiceDelegate'
favor, sugiéralo. Es mi sexto día en Swift :)
Muy fácil paso a paso (100% de trabajo y probado)
Paso 1: Crear método en el primer controlador de vista
func updateProcessStatus(isCompleted : Bool){
if isCompleted{
self.labelStatus.text = "Process is completed"
}else{
self.labelStatus.text = "Process is in progress"
}
}
Paso 2: establecer delegado mientras se empuja al segundo controlador de vista
@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: establecer delegado como
clase ViewController: UIViewController, ProcessStatusDelegate {
Paso 4: Crear protocolo
protocol ProcessStatusDelegate:NSObjectProtocol{
func updateProcessStatus(isCompleted : Bool)
}
paso5: toma una variable
var delegate:ProcessStatusDelegate?
Paso 6: Mientras regresa al método de delegado de llamadas del controlador de vista anterior, el primer controlador de vista notifica 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)
}
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
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 los delegados! Aquí hay un tutorial que implementa delegados paso a paso en Swift 3
Las soluciones anteriores parecían un poco acopladas y, al mismo tiempo, evitan reutilizar el mismo protocolo en otros controladores, es por eso que he venido con la solución que es más tipada con un borrado de tipo 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 : tiene un nuevo valor newValue
Cree un delegado en la clase que necesite 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() {
}
}