如何在swift中创建委托,例如NSUserNotificationCenterDelegate
?
如何在swift中创建委托,例如NSUserNotificationCenterDelegate
?
这里有一些关于在两个视图控制器之间使用代理的小帮助:
步骤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
}
第四步:在接收类中采用该协议
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
只适用于类而不是结构体和枚举。如果委托将是一个结构体或枚举,则无需担心保留循环。但是,如果委托是一个类(这在许多情况下都是正确的,因为通常它是 ViewController),则需要使用 weak
,但需要将您的协议声明为类。这里有更多信息:https://dev59.com/aGAf5IYBdhLWcg3w_W9j#34566876 - Robert委托一直让我感到困惑,直到我意识到委托只是为另一个类执行某些工作的类。就像有其他人帮你做你不想亲自做的所有脏活一样。
我写了一个小故事来阐述这个概念。如果您愿意,可以在 Playground 中阅读它。
// 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.
回顾一下,使用委托模式涉及三个关键部分:
与上面的Bossy Big Brother故事相比,委托通常用于以下实际应用:
重要的是,这些类之间事先不需要了解彼此的任何内容,只需要知道委托类符合所需的协议即可。
我强烈建议阅读以下两篇文章。它们帮助我更好地理解委托,甚至比文档还有用。
再补充一点
引用其他它所不拥有的类的委托应该使用 weak
关键字,以避免强引用循环。请参见此答案了解更多详细信息。
它与 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>
,允许您初始化/配置视图控制器,并在子视图上调用委托方法?类似于这个的东西。 - Mahmud Ahmad我对 @MakeAppPie 的帖子有几个修改意见。
首先,在创建委托协议时,它应该符合 Class 协议。就像下面的例子一样。
protocol ProtocolDelegate: class {
func myMethod(controller:ViewController, text:String)
}
其次,你的代理应该是弱引用,以避免出现循环引用。
class ViewController: UIViewController {
weak var delegate: ProtocolDelegate?
}
最后,由于您的协议是可选值,所以您是安全的。这意味着它的 "nil" 消息不会发送到此属性。这类似于在 objC 中使用 respondToselector
的条件语句,但这里您可以在一行中完成所有操作:
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
,如果 delegate 是 nil
,那么什么也不会发生,程序也不会崩溃。然而,如果你犯了错误,写成了 delegate!.myMethod
,如果没有设置委托,你就有可能会崩溃,所以这基本上是一种让你更加安全的方式... - mfaani这里是我整理的代码片段。我有同样的疑问,这对我的理解有所帮助。在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()
UIViewController
类符合我们创建的委托协议呢?
它们必须在一个Swift文件中声明吗?任何帮助都将意义重大。 - Farukclass ViewController:UIViewController NameOfDelegate
。 - SeeMeCodea.swift
中根据你上面的答案创建一个委托类时,它在b.swift
中没有出现。我无法访问我的Swift文件之外的任何类。有什么想法吗? - FarukSWIFT 2中的代理
我将通过两个视图控制器的代理示例进行说明。在这种情况下,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(temp: "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)
}
}
在第一个视图控制器中,协议的符合性是在这里完成的:
class ViewController: UIViewController, getDataDelegate
在第一个视图控制器(ViewController)中,协议方法的定义
func getDataFromAnotherVC(temp : String)
{
// dataString from SecondVC
lblForData.text = dataString
}
从第一个视图控制器(ViewController)推送SecondVC时
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(result: url)
}
}
第二类:
class ViewController: UIViewController, NetworkServiceDelegate {
let network = NetworkService()
override func viewDidLoad() {
super.viewDidLoad()
network.delegate = self
network.fetchDataFromURL(url: "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)
}
步骤三:设置委托,如下所示:
class ViewController: UIViewController, ProcessStatusDelegate {
步骤四:创建协议。
protocol ProcessStatusDelegate:NSObjectProtocol{
func updateProcessStatus(isCompleted : Bool)
}
步骤5:取一个变量
var delegate:ProcessStatusDelegate?
步骤6:返回到前一个视图控制器时,调用委托方法,以便第一个视图控制器使用数据通知。
@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)
}
以下是Delegate的简单代码示例:
//MARK: - Protocol ShowResult
protocol ShowResult: AnyObject {
func show(value: Int)
}
//MARK: - MyOperation Class
class MyOperation {
weak var delegate: ShowResult?
func sum(fNumber: Int, sNumber: Int) {
delegate?.show(value: fNumber + sNumber)
}
}
//MARK: - ViewController Class
class ViewController: UIViewController,ShowResult {
var myOperation: MyOperation?
override func viewDidLoad() {
super.viewDidLoad()
loadMyOperation()
myOperation?.delegate = self
myOperation?.sum(fNumber: 100, sNumber: 20)
}
private func loadMyOperation() {
if myOperation == nil {
myOperation = MyOperation()
}
}
func show(value: Int) {
print("value: \(value)")
}
}
简单示例:
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