当前位置: > > > Swift - 创建代理协议实现页面间参数传递和方法调用

Swift - 创建代理协议实现页面间参数传递和方法调用

(本文代码已升级至Swift3)

在开发中,经常需要用到协议代理模式。比如,进入编辑页面修改数据后,将新数据回传到主界面。

下面通过一个样例来说明协议代理模式,功能如下:
1,主页面有一个标签和一个修改按钮,点击修改按钮会跳转到编辑页面
2,编辑页面中修改输入框的文字后,点击“确定”则返回主页面,同时主页面的标签值会替换成新值
3,如果点击编辑页面的“取消”按钮则直接返回主页面

效果图如下:


实现过程:
1,首先在storyboard中绘制如下两个界面,同时将主界面的“修改”按钮与编辑页做present modally关联


2,设置这个关联Segue的Identity为 EditView


3,主界面 ViewController.swift
import UIKit

class ViewController: UIViewController,EditViewControllerDelegate{
    
    @IBOutlet weak var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    //页面跳转时
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "EditView"{
            //通过seque的标识获得跳转目标
            let controller = segue.destination as! EditViewController
            //设置代理
            controller.delegate = self
            //将值传递给新页面
            controller.oldInfo = label.text
        }
    }
    
    func editInfo(controller:EditViewController, newInfo:String){
        label.text = newInfo;
        //关闭编辑页面
        controller.presentingViewController!.dismiss(animated: true, completion: nil)
    }
    
    func editInfoDidCancer(controller:EditViewController){
        //关闭编辑页面
        controller.presentingViewController!.dismiss(animated: true, completion: nil)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

4,编辑页 EditViewController.swift
import UIKit

class EditViewController: UIViewController {
    
    @IBOutlet weak var textField: UITextField!
    
    var delegate:EditViewControllerDelegate?
    
    var oldInfo:String?
    
    override func viewDidLoad() {
        super.viewDidLoad()

        if oldInfo  != nil{
            textField.text = oldInfo
        }
    }
    
    @IBAction func done(_ sender: AnyObject) {
        delegate?.editInfo(controller: self, newInfo: textField.text!)
    }
    
    @IBAction func cancel(_ sender: AnyObject) {
        delegate?.editInfoDidCancer(controller: self)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

5,编辑页代理 EditViewControllerDelegate.swift
protocol EditViewControllerDelegate{
    func editInfo(controller:EditViewController, newInfo:String)
    func editInfoDidCancer(controller:EditViewController)
}

6,在Storyboard中,将编辑页的Class设为EditViewController

7,源码下载:hangge_717.zip
评论5
  • 5楼
    2017-02-20 16:23
    wenfeng223

    能给个demo吗,我写的老是出错

    站长回复

    我把代码升级成Swift3的了,同时也附上完整的工程源码。你可以再看下。

  • 4楼
    2016-06-21 09:31
    swiftLearning

    航哥,你这代理不用weak修饰不会造成循环引用的内存泄露吗?求告知

    站长回复

    这个只是单向引用,而不是循环强引用,自然不会造成内存泄露。
    有关内存泄露的问题,可以参考我原来写的这篇文章:Swift - 内存泄露原因(循环强引用)及解决办法

  • 3楼
    2016-05-12 10:00
    Apples

    为什么一直报错Type "ViewController" does not conform to protocol "SecondViewControllerDelegate"
    代理关系我也设置了,方法我也实现了啊,为什么会这样

    站长回复

    这个不太清楚,你要自己再检查下了。看报错信息还是代理有问题。

  • 2楼
    2016-01-04 22:53
    ysfshine

    设置这个关联Segue的Identity为 EditView
    请问这里的设置 使用纯代码的方式应该如何 设置这个Identity

    站长回复

    Segue是storyboard里才有的,目的是为了减少代码量,其Identity也必须在storyboard定义,无法使用纯代码设置

  • 1楼
    2015-10-12 11:38
    Lu

    程序无法执行,点击确认或者Cancel时,delegate 都是nil,请问为什么?

    站长回复

    Swift一直在变,刚测试了下确实有问题,应该是要给Segue设置Identifier。文章内容已更新,如果还发现其他文章有问题的可以给我留言。