Wie macht man einen Delegierten, dh NSUserNotificationCenterDelegate
schnell?
Wie macht man einen Delegierten, dh NSUserNotificationCenterDelegate
schnell?
Antworten:
Es ist nicht so verschieden von obj-c. Zunächst müssen Sie das Protokoll in Ihrer Klassendeklaration wie folgt angeben:
class MyClass: NSUserNotificationCenterDelegate
Die Implementierung sieht folgendermaßen aus:
// 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
}
Natürlich müssen Sie den Delegaten einstellen. Beispielsweise:
NSUserNotificationCenter.defaultUserNotificationCenter().delegate = self;
@interface MyCustomClass: UIViewController <ClassIWantToUseDelegate>
, sodass Sie den Viewcontroller initiieren / konfigurieren und Delegierungsmethoden für die Unteransichten aufrufen können. Etwas ähnliches wie diese ?
Hier ist eine kleine Hilfe für Delegierte zwischen zwei Ansichtscontrollern:
Schritt 1: Erstellen Sie im UIViewController ein Protokoll, das Sie entfernen / die Daten senden.
protocol FooTwoViewControllerDelegate:class {
func myVCDidFinish(_ controller: FooTwoViewController, text: String)
}
Schritt 2: Deklarieren Sie den Delegaten in der sendenden Klasse (dh UIViewcontroller).
class FooTwoViewController: UIViewController {
weak var delegate: FooTwoViewControllerDelegate?
[snip...]
}
Schritt 3: Verwenden Sie den Delegaten in einer Klassenmethode, um die Daten an die Empfangsmethode zu senden. Hierbei handelt es sich um eine beliebige Methode, die das Protokoll übernimmt.
@IBAction func saveColor(_ sender: UIBarButtonItem) {
delegate?.myVCDidFinish(self, text: colorLabel.text) //assuming the delegate is assigned otherwise error
}
Schritt 4: Übernehmen Sie das Protokoll in die empfangende Klasse
class ViewController: UIViewController, FooTwoViewControllerDelegate {
Schritt 5: Implementieren Sie die Delegate-Methode
func myVCDidFinish(_ controller: FooTwoViewController, text: String) {
colorLabel.text = "The Color is " + text
controller.navigationController.popViewController(animated: true)
}
Schritt 6: Legen Sie den Delegaten in prepareForSegue fest:
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
}
}
Und das sollte funktionieren. Dies sind natürlich nur Codefragmente, sollten Ihnen aber die Idee geben. Für eine lange Erklärung dieses Codes können Sie hier zu meinem Blogeintrag gehen:
Wenn Sie daran interessiert sind, was mit einem Delegierten unter der Haube los ist, habe ich hier darüber geschrieben:
weak
wird nur für Klassen benötigt, nicht für Strukturen und Aufzählungen. Wenn der Delegat eine Struktur oder eine Aufzählung sein soll, müssen Sie sich keine Gedanken über Aufbewahrungszyklen machen. Der Delegat ist jedoch eine Klasse (dies gilt in vielen Fällen, da es sich häufig um einen ViewController handelt). Dann müssen weak
Sie Ihr Protokoll als Klasse deklarieren. Es gibt mehr Informationen hier stackoverflow.com/a/34566876/296446
Die Delegierten haben mich immer verwirrt, bis mir klar wurde, dass ein Delegierter nur eine Klasse ist, die für eine andere Klasse arbeitet . Es ist, als hätte jemand anderes die Drecksarbeit für Sie erledigt, die Sie nicht selbst erledigen möchten.
Ich habe eine kleine Geschichte geschrieben, um dies zu veranschaulichen. Lesen Sie es auf einem Spielplatz, wenn Sie möchten.
// 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.
Im Rückblick gibt es drei Schlüsselelemente für die Erstellung und Verwendung des Delegatenmusters.
Im Vergleich zu unserer obigen Bossy Big Brother-Geschichte werden Delegierte häufig für die folgenden praktischen Anwendungen verwendet:
Der große Teil ist, dass diese Klassen vorher nichts voneinander wissen müssen, außer dass die Delegatenklasse dem erforderlichen Protokoll entspricht.
Ich empfehle dringend, die folgenden zwei Artikel zu lesen. Sie haben mir geholfen, die Delegierten noch besser zu verstehen als die Dokumentation .
Noch eine Anmerkung
Delegaten, die auf andere Klassen verweisen, die sie nicht besitzen, sollten das weak
Schlüsselwort verwenden, um starke Referenzzyklen zu vermeiden. Siehe diese Antwort für weitere Details.
Ich habe einige Korrekturen für @MakeAppPie erhalten
Wenn Sie ein Delegatenprotokoll erstellen, sollte es zunächst dem Klassenprotokoll entsprechen. Wie im folgenden Beispiel.
protocol ProtocolDelegate: class {
func myMethod(controller:ViewController, text:String)
}
Zweitens sollte Ihr Delegierter schwach sein, um einen Aufbewahrungszyklus zu vermeiden.
class ViewController: UIViewController {
weak var delegate: ProtocolDelegate?
}
Zuletzt sind Sie sicher, da Ihr Protokoll ein optionaler Wert ist. Das bedeutet, dass die Nachricht "Null" nicht an diese Eigenschaft gesendet wird. Es ähnelt der bedingten Anweisung mit respondToselector
in objC, aber hier haben Sie alles in einer Zeile:
if ([self.delegate respondsToSelector:@selector(myMethod:text:)]) {
[self.delegate myMethod:self text:@"you Text"];
}
Oben haben Sie ein obj-C-Beispiel und unten haben Sie ein Swift-Beispiel dafür, wie es aussieht.
delegate?.myMethod(self, text:"your Text")
delegate?.myMethod
, stürzt dies nicht ab, denn wenn der Delegat ist nil
, würde nichts passieren. Allerdings , wenn Sie Fehler gemacht und schrieb delegate!.myMethod
man könnte abstürzen , wenn ein Delegierter nicht gesetzt ist, so ist es im Grunde eine Möglichkeit für Sie , um sicher zu sein ...
Hier ist ein Kern, den ich zusammengestellt habe. Ich habe mich das auch gefragt und dies hat mir geholfen, mein Verständnis zu verbessern. Öffne dies auf einem Xcode-Spielplatz, um zu sehen, was los ist.
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
Klasse dazu bringen, den von uns erstellten Delegierten zu entsprechen? Müssen sie in einer schnellen Datei deklariert werden? Jede Hilfe wird viel bedeuten.
class ViewController : UIViewController NameOfDelegate
.
a.swift
gemäß Ihrer obigen Antwort erstelle , wird sie nicht angezeigt b.swift
. Ich kann keine Klasse außerhalb meiner schnellen Datei erreichen. irgendwelche Schwierigkeiten?
DELEGATE IN SWIFT 2
Ich erkläre anhand eines Beispiels für Delegate mit zwei viewControllern. In diesem Fall sendet SecondVC Object Daten an den ersten View Controller zurück.
Klasse mit Protokollerklärung
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)
}
}
Im First ViewController-Protokoll wird hier Folgendes angepasst:
class ViewController: UIViewController, getDataDelegate
Definition der Protokollmethode in First View Controller (ViewController)
func getDataFromAnotherVC(temp : String)
{
// dataString from SecondVC
lblForData.text = dataString
}
Während des Pushs der SecondVC vom First View Controller (ViewController)
let objectPush = SecondVC()
objectPush.delegateCustom = self
self.navigationController.pushViewController(objectPush, animated: true)
Erste Klasse:
protocol NetworkServiceDelegate: class {
func didCompleteRequest(result: String)
}
class NetworkService: NSObject {
weak var delegate: NetworkServiceDelegate?
func fetchDataFromURL(url : String) {
delegate?.didCompleteRequest(url)
}
}
Zweite Klasse:
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'
angezeigt. Es ist mein 6. Tag auf Swift :)
Sehr einfach Schritt für Schritt (100% arbeiten und getestet)
Schritt 1: Erstellen Sie eine Methode auf dem First View Controller
func updateProcessStatus(isCompleted : Bool){
if isCompleted{
self.labelStatus.text = "Process is completed"
}else{
self.labelStatus.text = "Process is in progress"
}
}
Schritt 2: Legen Sie den Delegaten fest, während Sie auf den Controller für die zweite Ansicht drücken
@IBAction func buttonAction(_ sender: Any) {
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController") as! secondViewController
secondViewController.delegate = self
self.navigationController?.pushViewController(secondViewController, animated: true)
}
Schritt 3: Delegate wie einstellen
Klasse ViewController: UIViewController, ProcessStatusDelegate {
Schritt 4: Protokoll erstellen
protocol ProcessStatusDelegate:NSObjectProtocol{
func updateProcessStatus(isCompleted : Bool)
}
Schritt 5: Nehmen Sie eine Variable
var delegate:ProcessStatusDelegate?
Schritt 6: Während Sie zur vorherigen View Controller Call Delegate-Methode zurückkehren, benachrichtigen Sie zuerst den View Controller mit Daten
@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)
}
Einfaches Beispiel:
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
Delegaten sind ein Entwurfsmuster, mit dem ein Objekt Nachrichten an ein anderes Objekt senden kann, wenn ein bestimmtes Ereignis eintritt. Stellen Sie sich vor, ein Objekt A ruft ein Objekt B auf, um eine Aktion auszuführen. Sobald die Aktion abgeschlossen ist, sollte Objekt A wissen, dass B die Aufgabe abgeschlossen hat, und die erforderlichen Maßnahmen ergreifen. Dies kann mit Hilfe von Delegierten erreicht werden! Hier ist ein Tutorial, in dem Delegierte Schritt für Schritt in Swift 3 implementiert werden
Die oben genannten Lösungen schienen ein wenig gekoppelt zu sein und gleichzeitig zu vermeiden, dass dasselbe Protokoll in anderen Controllern wiederverwendet wird. Deshalb habe ich eine Lösung gefunden, die mit generischer Typlöschung stärker typisiert ist.
@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")
Ausgabe : hat neuen Wert newValue
Erstellen Sie einen Delegaten für eine Klasse, der Daten senden oder Funktionen für andere Klassen bereitstellen muss
Mögen
protocol GetGameStatus {
var score: score { get }
func getPlayerDetails()
}
Danach in der Klasse, die diesem Delegierten bestätigen wird
class SnakesAndLadders: GetGameStatus {
func getPlayerDetails() {
}
}