Делегаты в Свифте?



как можно сделать делегат, т. е. NSUserNotificationCenterDelegate в swift?

846   12  

12 ответов:

это не так уж отличается от obj-c. Во-первых, вы должны указать протокол в объявлении класса, например:

class MyClass: NSUserNotificationCenterDelegate

реализация будет выглядеть следующим образом:

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

конечно, вы должны установить делегат. Например:

NSUserNotificationCenter.defaultUserNotificationCenter().delegate = self;

вот небольшая помощь по делегатам между двумя контроллерами вида:

Шаг 1: сделайте протокол в UIViewController, который вы будете удалять / будет отправлять данные.

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

Шаг 2: объявить делегат в классе отправки (т. е. UIViewcontroller)

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

Шаг 3: используйте делегат в методе класса для отправки данных в метод получения, который является любым методом, который принимает протокол.

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

Шаг 4: примите протокол в приемном классе

class ViewController: UIViewController, FooTwoViewControllerDelegate {

Шаг 5: реализовать метод делегата

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

Шаг 6: установите делегат в 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
    }
}

и это должно сработать. Это, конечно, просто фрагменты кода, но должно дать вам представление. Долгое объяснение этого кода Вы можете перейти к моей записи в блоге здесь:

сегменты и делегаты

если вас интересует, что происходит под капотом с делегатом, я писала об этом здесь:

под капотом с делегатами

делегаты всегда смущали меня, пока я не понял, что делегат-это просто класс, который выполняет некоторую работу для другого класса. Это как если бы кто-то другой делал за тебя всю грязную работу, которую ты не хочешь делать сам.

Я написал небольшую историю, чтобы проиллюстрировать это. Читайте его на детской площадке, если хотите.

когда-то давно...

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

в обзоре есть три ключевые части для создания и использования делегата узор.

  1. the протокол это определяет, что работник должен сделать
  2. the босс класс это имеет переменную делегата, который он использует, чтобы сказать рабочему классу, что делать
  3. the рабочий класс что принимает протокол и делает то, что требуется

реальная жизнь

по сравнению с нашей историей старшего брата выше, делегаты часто используются для следующих практических целей приложения:

  1. сообщении: один класс должен послать некоторую информацию в другой класс.
  2. настройки: один класс хочет, чтобы другой класс, чтобы настроить его.

большая часть заключается в том, что эти классы не должны ничего знать друг о друге заранее, за исключением того, что класс-делегат соответствует нужный протокол.

я настоятельно рекомендую прочитать следующие две статьи. Они помогли мне понять делегатов даже лучше, чем документация сделал.

еще одно замечание

делегаты, ссылающиеся на другие классы, которые им не принадлежат, должны использовать weak ключевое слово, чтобы избежать сильных ссылочные циклы. Смотрите ответ для более подробной информации.

я получил несколько исправлений в посте @MakeAppPie

во-первых, когда вы создаете протокол делегата, он должен соответствовать протоколу класса. Как в примере ниже.

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

во-вторых, ваш представитель должен быть слабым, чтобы избежать удержания цикла.

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

наконец, вы в безопасности, потому что ваш протокол является необязательным значением. Это означает, что его сообщение " nil " не будет отправлено в это свойство. Это похоже на условный оператор с respondToselector в objC но здесь вы есть все в одной строке:

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

выше у вас есть пример obj-C, а ниже у вас есть быстрый пример того, как это выглядит.

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

здесь суть я собрал. Мне было интересно то же, и это помогло улучшить мое понимание. Откройте это в Xcode Playground чтобы посмотреть, что происходит.

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

ДЕЛЕГАТЫ В SWIFT 2

Я объясняю с примером делегата с двумя viewControllers.In в этом случае объект SecondVC отправляет данные обратно в первый контроллер представления.

класс с объявлением протокола

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

}

в первом протоколе ViewController соответствие выполняется здесь:

class ViewController: UIViewController, getDataDelegate

определение метода протокола в первом контроллере вида (ViewController)

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

во время нажима на SecondVC от Первый Контроллер Вида (ViewController)

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

первый класс:

protocol NetworkServiceDelegate: class {

    func didCompleteRequest(result: String)
}


class NetworkService: NSObject {

    weak var delegate: NetworkServiceDelegate?

    func fetchDataFromURL(url : String) {
        delegate?.didCompleteRequest(url)
    }
}

второй класс:

class ViewController: UIViewController, NetworkServiceDelegate {

    let network = NetworkService()

    override func viewDidLoad() {
        super.viewDidLoad()
        network.delegate = self
        network.fetchDataFromURL("Success!")
    }



    func didCompleteRequest(result: String) {
        print(result)
    }


}

очень легко шаг за шагом (100% работает и тестируется)

Шаг 1: создать метод на первом контроллере вида

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

Шаг 2: установить делегат при нажатии на второй контроллер вида

@IBAction func buttonAction(_ sender: Any) {

    let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController") as! secondViewController
    secondViewController.delegate = self
    self.navigationController?.pushViewController(secondViewController, animated: true)
}

Шаг 3: установить делегат как

класс ViewController: UIViewController, ProcessStatusDelegate {

Шаг 4: создать протокол

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

Шаг 5: принимать переменная

var delegate:ProcessStatusDelegate?

step6: пока вернитесь к предыдущему методу делегирования вызова контроллера вида, чтобы первый контроллер вида уведомил с данными

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

}

делегаты-это шаблон проектирования, который позволяет одному объекту отправлять сообщения другому объекту при возникновении определенного события. Представьте себе, что объект A вызывает объект B для выполнения действия. Как только действие завершено, объект A должен знать, что B выполнил задачу и принял необходимые меры, это может быть достигнуто с помощью делегатов! Вот учебник реализации делегатов шаг за шагом в swift 3

Учебник По Ссылке

Простой Пример:

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

решения выше казались немного связанными и в то же время избегали повторного использования того же протокола в других контроллерах, поэтому я пришел с решением, которое более сильно типизировано с использованием универсального типа-стирания.

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

выход: получил новое значение newValue

в swift 4.0

создайте делегат в классе, который должен отправлять некоторые данные или предоставлять некоторые функции другим классам

как

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

после этого в классе, который собирается подтвердить этот делегат

class SnakesAndLadders: GetGameStatus {
    func getPlayerDetails() {

 }
}

Comments

    Ничего не найдено.