Délégués à swift?
Comment faire un délégué, i.e. NSUserNotificationCenterDelegate
dans swift?
12 réponses
Il n'est pas différent de l'obj-c. Tout d'abord, vous devez spécifier le protocole dans la déclaration de classe, comme suit:
class MyClass: NSUserNotificationCenterDelegate
la mise en œuvre ressemblera à ceci:
// 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
}
bien sûr, vous devez définir le délégué. Par exemple:
NSUserNotificationCenter.defaultUserNotificationCenter().delegate = self;
Voici un peu d'aide sur les délégués entre deux contrôleurs de vue:
Étape 1: faites un protocole dans le UIViewController que vous allez supprimer/que vous allez envoyer les données.
protocol FooTwoViewControllerDelegate:class {
func myVCDidFinish(_ controller: FooTwoViewController, text: String)
}
etape n ° 2: Déclare le délégué de l'envoi de la classe (c'est à dire UIViewcontroller)
class FooTwoViewController: UIViewController {
weak var delegate: FooTwoViewControllerDelegate?
[snip...]
}
Etape 3: Utiliser le délégué dans une méthode de classe pour envoyer les données pour la méthode de réception, qui est une méthode qui adopte le protocole.
@IBAction func saveColor(_ sender: UIBarButtonItem) {
delegate?.myVCDidFinish(self, text: colorLabel.text) //assuming the delegate is assigned otherwise error
}
Étape 4: adopter le protocole dans la classe de réception
class ViewController: UIViewController, FooTwoViewControllerDelegate {
Étape 5: mettre en Œuvre la méthode du délégué
func myVCDidFinish(_ controller: FooTwoViewController, text: String) {
colorLabel.text = "The Color is " + text
controller.navigationController.popViewController(animated: true)
}
Étape 6: Définir le délégué de l'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
}
}
et ça devrait marcher. C'est de entendu seulement des fragments de code, mais devrait vous donner l'idée. Pour une longue explication de ce code, vous pouvez aller à mon article de blog ici:
si vous êtes intéressé par ce qui se passe sous le capot avec un délégué, j'ai écrit là-dessus:
les délégués m'ont toujours déconcerté jusqu'à ce que je réalise que un délégué est juste une classe qui fait du travail pour une autre classe . C'est comme avoir quelqu'un là pour faire tout le sale boulot pour vous que vous ne voulez pas le faire vous-même.
j'ai écrit une petite histoire pour illustrer cela. Lis-le dans une cour de récréation si tu veux.
il était une fois...
// 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 revue, il y a trois parties clés à faire et utiliser le modèle de délégué.
- le protocole qui définit ce que le travailleur doit faire
- le chef de classe qui dispose d'un délégué variable, qui l'utilise pour dire le travailleur classe quoi faire
- la classe ouvrière qui adopte le protocole et fait ce qui est requis
par rapport à notre histoire de Grand Frère autoritaire ci-dessus, les délégués sont souvent utilisés pour les applications pratiques suivantes:
- Communication : une classe doit envoyer des informations à une autre classe.
- exemple de Code 1: envoi de données d'un contrôleur de vue à un autre
- exemple de Code 2: envoi de texte à partir d'un clavier personnalisé à un champ de texte
- personnalisation : une classe veut permettre à une autre classe de la personnaliser.
la grande partie est que ces classes n'ont pas besoin de savoir quoi que ce soit les uns des autres à l'avance, sauf que la classe déléguée est conforme au protocole requis.
je recommande vivement la lecture des deux articles suivants. Ils m'ont aidé à comprendre délégués encore mieux que le documentation fait.
- Qu'est-ce que la délégation? – Un guide du développeur Swift
- Comment la Délégation Œuvres – Une Swift Guide du Développeur
une autre note
les délégués qui se réfèrent à d'autres classes qu'ils ne possèdent pas doivent utiliser le weak
mot-clé pour éviter les cycles de référence forts. Voir cette réponse pour plus de détails.
j'ai eu quelques corrections de post de @MakeAppPie
tout d'abord quand vous créez le protocole de délégué, il doit être conforme au Protocole de classe. Comme dans l'exemple ci-dessous.
protocol ProtocolDelegate: class {
func myMethod(controller:ViewController, text:String)
}
Deuxièmement, votre délégué doit être faible pour éviter le cycle de conservation.
class ViewController: UIViewController {
weak var delegate: ProtocolDelegate?
}
enfin, vous êtes en sécurité parce que votre protocole est une valeur optionnelle. Cela signifie que son message "néant" ne sera pas envoyé à ce bien. C'est similaire à conditionnel déclaration avec respondToselector
dans objC mais ici vous avez tout dans une ligne:
if ([self.delegate respondsToSelector:@selector(myMethod:text:)]) {
[self.delegate myMethod:self text:@"you Text"];
}
ci-dessus vous avez un exemple obj-C et ci-dessous vous avez un exemple rapide de comment il regarde.
delegate?.myMethod(self, text:"your Text")
voici un gist j'ai mis ensemble. Je me demandais la même chose et cela a aidé à améliorer ma compréhension. Ouvrez ceci dans un Xcode Playground pour voir ce qui se passe.
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()
DÉLÉGUÉS À SWIFT 2
j'explique Avec exemple de délégué avec deux viewControllers.Dans ce cas, L'objet SecondVC renvoie des données au contrôleur de première vue.
classe avec Déclaration de protocole
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)
}
}
Dans le Premier ViewController Protocole conforme est fait ici:
class ViewController: UIViewController, getDataDelegate
définition de la méthode du Protocole dans la première vue Controller (ViewController)
func getDataFromAnotherVC(dataString : String)
{
// dataString from SecondVC
lblForData.text = dataString
}
pendant la poussée de la Seconde vc du contrôleur de première vue (ViewController)
let objectPush = SecondVC()
objectPush.delegateCustom = self
self.navigationController.pushViewController(objectPush, animated: true)
première classe:
protocol NetworkServiceDelegate: class {
func didCompleteRequest(result: String)
}
class NetworkService: NSObject {
weak var delegate: NetworkServiceDelegate?
func fetchDataFromURL(url : String) {
delegate?.didCompleteRequest(url)
}
}
deuxième 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)
}
}
Très facile, étape par étape (100% de travail et testé)
etape n ° 1: méthode de création à première vue-contrôleur
func updateProcessStatus(isCompleted : Bool){
if isCompleted{
self.labelStatus.text = "Process is completed"
}else{
self.labelStatus.text = "Process is in progress"
}
}
etape n ° 2: Jeu de déléguer tout pousser à seconde vue-contrôleur
@IBAction func buttonAction(_ sender: Any) {
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController") as! secondViewController
secondViewController.delegate = self
self.navigationController?.pushViewController(secondViewController, animated: true)
}
etape 3: set délégué comme
class ViewController: UIViewController, ProcessStatusDelegate {
etape 4: Créer protocole
protocol ProcessStatusDelegate:NSObjectProtocol{
func updateProcessStatus(isCompleted : Bool)
}
etape n ° 5: prendre une variable
var delegate:ProcessStatusDelegate?
step6: pendant que retourner à la méthode de délégué de contrôleur de vue précédente ainsi premier contrôleur de vue notifier avec des données
@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)
}
les délégués sont un motif qui permet à un objet d'envoyer des messages à un autre objet lorsqu'un événement spécifique se produit. Imaginez qu'un objet a appelle un objet B pour effectuer une action. Une fois l'action terminée, l'objet doit savoir que B a terminé la tâche et de prendre les mesures nécessaires, cela peut être réalisé avec l'aide des délégués! Voici un tutoriel mettant en œuvre les délégués étape par étape dans swift 3
Exemple 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
les solutions ci-dessus semblaient un peu couplées et en même temps éviter de réutiliser le même protocole dans d'autres controllers, c'est pourquoi je suis venu avec la solution qui est plus forte typée en utilisant le type générique-erasure.
@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")
sortie : a obtenu la nouvelle valeur newValue
dans swift 4.0
créer un délégué sur la classe qui doit envoyer des données ou fournir des fonctionnalités à d'autres classes
Comme
protocol GetGameStatus {
var score: score { get }
func getPlayerDetails()
}
après celui de la classe qui va confirmer à ce délégué
class SnakesAndLadders: GetGameStatus {
func getPlayerDetails() {
}
}