Come si fa a fare un delegato, cioè NSUserNotificationCenterDelegate
in fretta?
Come si fa a fare un delegato, cioè NSUserNotificationCenterDelegate
in fretta?
Risposte:
Non è così diverso da obj-c. Innanzitutto, devi specificare il protocollo nella dichiarazione di classe, come il seguente:
class MyClass: NSUserNotificationCenterDelegate
L'implementazione sarà simile alla seguente:
// 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
}
Certo, devi impostare il delegato. Per esempio:
NSUserNotificationCenter.defaultUserNotificationCenter().delegate = self;
@interface MyCustomClass: UIViewController <ClassIWantToUseDelegate>
, che consente di avviare / configurare il viewcontroller, nonché di chiamare i metodi delegati nelle viste secondarie? Qualcosa di simile a questo ?
Ecco un piccolo aiuto sui delegati tra due controller di visualizzazione:
Passaggio 1: crea un protocollo in UIViewController che rimuoverai / invierai i dati.
protocol FooTwoViewControllerDelegate:class {
func myVCDidFinish(_ controller: FooTwoViewController, text: String)
}
Step2: Dichiara il delegato nella classe di invio (es. UIViewcontroller)
class FooTwoViewController: UIViewController {
weak var delegate: FooTwoViewControllerDelegate?
[snip...]
}
Passaggio 3: utilizzare il delegato in un metodo di classe per inviare i dati al metodo di ricezione, ovvero qualsiasi metodo che adotti il protocollo.
@IBAction func saveColor(_ sender: UIBarButtonItem) {
delegate?.myVCDidFinish(self, text: colorLabel.text) //assuming the delegate is assigned otherwise error
}
Passaggio 4: adottare il protocollo nella classe di ricezione
class ViewController: UIViewController, FooTwoViewControllerDelegate {
Passaggio 5: implementare il metodo delegato
func myVCDidFinish(_ controller: FooTwoViewController, text: String) {
colorLabel.text = "The Color is " + text
controller.navigationController.popViewController(animated: true)
}
Passaggio 6: impostare il delegato nel preparForSegue:
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
}
}
E dovrebbe funzionare. Questo ovviamente è solo frammenti di codice, ma dovrebbe darti l'idea. Per una lunga spiegazione di questo codice puoi andare al mio blog qui:
Se sei interessato a quello che succede sotto il cofano con un delegato, l'ho scritto qui:
weak
è necessario solo per le classi non per strutture ed enumerazioni. Se il delegato diventerà una struttura o un enum allora non dovrai preoccuparti dei cicli di mantenimento. Tuttavia, il delegato è una classe (questo è vero per molti casi poiché abbastanza spesso è un ViewController), quindi è necessario weak
ma è necessario dichiarare il protocollo come classe. Maggiori informazioni qui stackoverflow.com/a/34566876/296446
I delegati mi hanno sempre confuso fino a quando ho capito che un delegato è solo una classe che fa un po 'di lavoro per un'altra classe . È come avere qualcun altro lì a fare tutto il lavoro sporco per te che non vuoi fare da solo.
Ho scritto una piccola storia per illustrare questo. Leggilo in un parco giochi se vuoi.
// 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.
In revisione, ci sono tre parti chiave per creare e usare il modello delegato.
Rispetto alla nostra storia Bossy Big Brother sopra, i delegati sono spesso usati per le seguenti applicazioni pratiche:
La parte migliore è che queste classi non hanno bisogno di conoscersi prima dell'altro, tranne che la classe delegata è conforme al protocollo richiesto.
Consiglio vivamente di leggere i seguenti due articoli. Mi hanno aiutato a capire i delegati anche meglio della documentazione .
Un'altra nota
I delegati che fanno riferimento ad altre classi che non possiedono dovrebbero usare la weak
parola chiave per evitare cicli di riferimento forti. Vedi questa risposta per maggiori dettagli.
Ho ricevuto alcune correzioni per pubblicare @MakeAppPie
Prima di tutto quando si crea un protocollo delegato, dovrebbe essere conforme al protocollo di classe. Come nell'esempio seguente.
protocol ProtocolDelegate: class {
func myMethod(controller:ViewController, text:String)
}
In secondo luogo, il delegato dovrebbe essere debole per evitare il ciclo di mantenimento.
class ViewController: UIViewController {
weak var delegate: ProtocolDelegate?
}
Infine, sei al sicuro perché il tuo protocollo è un valore opzionale. Ciò significa che il suo messaggio "zero" non verrà inviato a questa proprietà. È simile all'istruzione condizionale con respondToselector
in objC ma qui hai tutto in una riga:
if ([self.delegate respondsToSelector:@selector(myMethod:text:)]) {
[self.delegate myMethod:self text:@"you Text"];
}
Sopra hai un esempio obj-C e sotto hai un esempio Swift di come appare.
delegate?.myMethod(self, text:"your Text")
delegate?.myMethod
non si arresta in modo anomalo perché se il delegato è nil
allora non succederebbe nulla. Tuttavia, se hai commesso un errore e delegate!.myMethod
hai scritto che potresti bloccarti se non è stato impostato un delegato, quindi in pratica è un modo per essere al sicuro ...
Ecco un riassunto che ho messo insieme. Mi chiedevo lo stesso e questo mi ha aiutato a migliorare la mia comprensione. Apri questo in un Xcode Playground per vedere cosa sta succedendo.
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
classe sia conforme al delegato che abbiamo creato? Devono essere dichiarati in un unico file rapido? Qualsiasi aiuto significherà molto.
class ViewController : UIViewController NameOfDelegate
.
a.swift
base alla tua risposta sopra, non compare b.swift
. Non riesco a raggiungere alcuna classe al di fuori del mio file rapido. qualche duro?
DELEGATI IN SWIFT 2
Sto spiegando con l'esempio di Delegato con due viewController. In questo caso, SecondVC Object restituisce i dati al primo View Controller.
Classe con dichiarazione del protocollo
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)
}
}
Nel protocollo First ViewController la conformità viene eseguita qui:
class ViewController: UIViewController, getDataDelegate
Definizione del metodo di protocollo in First View Controller (ViewController)
func getDataFromAnotherVC(temp : String)
{
// dataString from SecondVC
lblForData.text = dataString
}
Durante il push del SecondVC dal controller First View (ViewController)
let objectPush = SecondVC()
objectPush.delegateCustom = self
self.navigationController.pushViewController(objectPush, animated: true)
Prima classe:
protocol NetworkServiceDelegate: class {
func didCompleteRequest(result: String)
}
class NetworkService: NSObject {
weak var delegate: NetworkServiceDelegate?
func fetchDataFromURL(url : String) {
delegate?.didCompleteRequest(url)
}
}
Seconda classe:
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'
suggerisco. È il mio sesto giorno in fretta :)
Step by step molto semplice (funzionante e testato al 100%)
step1: crea il metodo sul controller della prima vista
func updateProcessStatus(isCompleted : Bool){
if isCompleted{
self.labelStatus.text = "Process is completed"
}else{
self.labelStatus.text = "Process is in progress"
}
}
step2: imposta il delegato mentre premi il controller della seconda vista
@IBAction func buttonAction(_ sender: Any) {
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController") as! secondViewController
secondViewController.delegate = self
self.navigationController?.pushViewController(secondViewController, animated: true)
}
step3: imposta il delegato come
class ViewController: UIViewController, ProcessStatusDelegate {
step4: Crea protocollo
protocol ProcessStatusDelegate:NSObjectProtocol{
func updateProcessStatus(isCompleted : Bool)
}
step5: prendere una variabile
var delegate:ProcessStatusDelegate?
step6: Mentre torni alla visualizzazione precedente, chiama il metodo delegato, quindi prima controlla il controller con i dati
@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)
}
Esempio semplice:
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
I delegati sono un modello di progettazione che consente a un oggetto di inviare messaggi a un altro oggetto quando si verifica un evento specifico. Immagina un oggetto A chiama un oggetto B per eseguire un'azione. Una volta completata l'azione, l'oggetto A dovrebbe sapere che B ha completato l'attività e intraprendere le azioni necessarie, ciò può essere realizzato con l'aiuto dei delegati! Ecco un tutorial che implementa i delegati passo dopo passo in swift 3
Le soluzioni di cui sopra sembravano un po 'accoppiate e allo stesso tempo evitano di riutilizzare lo stesso protocollo in altri controller, ecco perché sono arrivato con la soluzione più tipizzata usando la cancellazione generica del tipo.
@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")
output : ottenuto nuovo valore newValue
Creare un delegato sulla classe che deve inviare alcuni dati o fornire alcune funzionalità ad altre classi
Piace
protocol GetGameStatus {
var score: score { get }
func getPlayerDetails()
}
Dopo quello nella classe che sta per confermare a questo delegato
class SnakesAndLadders: GetGameStatus {
func getPlayerDetails() {
}
}