Как сделать делегата, то есть NSUserNotificationCenterDelegate
быстро?
Как сделать делегата, то есть NSUserNotificationCenterDelegate
быстро?
Ответы:
Это ничем не отличается от 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;
@interface MyCustomClass: UIViewController <ClassIWantToUseDelegate>
обмануть, позволяя вам инициализировать / настраивать контроллер представления, а также вызывать методы делегата для вложенных представлений? Что-то похожее на это ?
Вот небольшая справка по делегатам между двумя контроллерами представления:
Шаг 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
}
}
И это должно сработать. Это, конечно, только фрагменты кода, но это должно дать вам представление. Для подробного объяснения этого кода вы можете перейти к моей записи в блоге здесь:
Если вам интересно, что происходит под капотом с делегатом, я написал об этом здесь:
weak
нужен только для классов, а не структур и перечислений. Если делегат будет структурой или перечислением, вам не нужно беспокоиться о циклах сохранения. Однако делегируйте свой класс a (это верно для многих случаев, поскольку довольно часто это ViewController), тогда вам нужно, weak
но вам нужно объявить свой протокол как класс. Здесь есть дополнительная информация stackoverflow.com/a/34566876/296446
Делегаты всегда сбивали меня с толку, пока я не понял, что делегат - это просто класс, который выполняет некоторую работу для другого класса . Это как если бы кто-то другой делал за вас всю грязную работу, которую вы не хотите делать сами.
Я написал небольшую историю, чтобы проиллюстрировать это. Прочитайте это на детской площадке, если хотите.
// 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.
Итак, можно сказать, что создание и использование шаблона делегата состоит из трех ключевых частей.
По сравнению с нашей историей о Босси-Большом Брате выше, делегаты часто используются для следующих практических целей:
Самое замечательное в том, что этим классам не нужно ничего знать друг о друге заранее, за исключением того, что класс делегата соответствует требуемому протоколу.
Я настоятельно рекомендую прочитать следующие две статьи. Они помогли мне понять делегатов даже лучше, чем документация .
Еще одна заметка
Делегаты, которые ссылаются на другие классы, которые им не принадлежат, должны использовать weak
ключевое слово, чтобы избежать циклов сильных ссылок. Смотрите этот ответ для более подробной информации.
Я получил несколько исправлений к посту @MakeAppPie
Прежде всего, когда вы создаете протокол делегата, он должен соответствовать протоколу Class. Как в примере ниже.
protocol ProtocolDelegate: class {
func myMethod(controller:ViewController, text:String)
}
Во-вторых, ваш делегат должен быть слабым, чтобы избежать цикла.
class ViewController: UIViewController {
weak var delegate: ProtocolDelegate?
}
Наконец, вы в безопасности, потому что ваш протокол является необязательным значением. Это означает, что его «ноль» сообщение не будет отправлено в это свойство. Это похоже на условный оператор respondToselector
в objC, но здесь все в одной строке:
if ([self.delegate respondsToSelector:@selector(myMethod:text:)]) {
[self.delegate myMethod:self text:@"you Text"];
}
Выше у вас есть пример obj-C, а ниже у вас есть пример Swift того, как это выглядит.
delegate?.myMethod(self, text:"your Text")
delegate?.myMethod
, не произойдет сбой, потому что если делегат, nil
то ничего не произойдет. Однако, если вы допустили ошибку и написали, delegate!.myMethod
вы можете потерпеть крах, если делегат не установлен, так что это, по сути, способ обезопасить вас ...
Вот суть, которую я собрал. Мне было интересно то же самое, и это помогло улучшить мое понимание. Откройте это на игровой площадке Xcode, чтобы увидеть, что происходит.
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
класс соответствующим делегату, который мы сделали? Они должны быть объявлены в одном быстром файле? Любая помощь будет много значить.
class ViewController : UIViewController NameOfDelegate
.
a.swift
соответствии с вашим ответом выше, он не появляется b.swift
. Я не могу добраться до любого класса за пределами моего файла swift. какие-нибудь проблемы?
ДЕЛЕГАТЫ В SWIFT 2
Я объясняю на примере Delegate с двумя viewController'ами. В этом случае SecondVC Object отправляет данные обратно в первый View Controller.
Класс с протоколом декларации
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
Определение метода протокола в First View Controller (ViewController)
func getDataFromAnotherVC(temp : 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)
}
}
Type 'ViewController' does not conform to protocol 'NetworkServiceDelegate'
пожалуйста. Это мой 6-й день на swift :)
Очень просто пошагово (100% работает и проверено)
step1: Создать метод на первом контроллере представления
func updateProcessStatus(isCompleted : Bool){
if isCompleted{
self.labelStatus.text = "Process is completed"
}else{
self.labelStatus.text = "Process is in progress"
}
}
step2: установить делегата при нажатии на второй контроллер представления
@IBAction func buttonAction(_ sender: Any) {
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController") as! secondViewController
secondViewController.delegate = self
self.navigationController?.pushViewController(secondViewController, animated: true)
}
step3: установите делегата как
class ViewController: UIViewController, ProcessStatusDelegate {
Шаг 4: Создать протокол
protocol ProcessStatusDelegate:NSObjectProtocol{
func updateProcessStatus(isCompleted : Bool)
}
step5: взять переменную
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)
}
Простой пример:
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
Делегаты - это шаблон проектирования, который позволяет одному объекту отправлять сообщения другому объекту, когда происходит определенное событие. Представьте, что объект A вызывает объект B для выполнения действия. Как только действие завершено, объект A должен знать, что B выполнил задачу, и предпринять необходимые действия, это может быть достигнуто с помощью делегатов! Вот руководство по реализации делегатов шаг за шагом в Swift 3
Вышеупомянутые решения казались немного связанными и в то же время избегали повторного использования одного и того же протокола в других контроллерах, поэтому я пришел с решением, которое более строго типизировано с использованием универсального стирания типов.
@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
Создайте делегата в классе, который должен отправить некоторые данные или предоставить некоторые функции другим классам
подобно
protocol GetGameStatus {
var score: score { get }
func getPlayerDetails()
}
После этого в классе, который собирается подтвердить этому делегату
class SnakesAndLadders: GetGameStatus {
func getPlayerDetails() {
}
}