美文网首页swift程序员iOS Developer
iOS页面传值问题(swift2.0篇)

iOS页面传值问题(swift2.0篇)

作者: 4ba6804ff45f | 来源:发表于2016-01-10 23:31 被阅读1907次

    iOS页面传值问题(swift2.0篇)

    同样是介绍iOS开发中的页面传值,此篇与上一篇使用Objective-C传值对应。在OC中的方法在swift中也是同样适用的,而且还要介绍一些swift特有的方式。

    一、协议

    使用协议还是3+2一共五个步骤,按部就班来实现就可以了。还是先想清楚谁委托谁代理,在逻辑上不要出现错误。

    • 新的项目中创建了两个新的类:A类负责显示,B类负责输入。所以说A只要负责拿到数据即可,让B类来作委托方。这里的协议是写在委托方的文件之中的,并没有重新创建。

    借用上一篇的图来继续实现各个步骤:


    • 继续来委托方的两步走,因为这里代码行数真的不多,而且不分.h和.m,我们来看一下B类的所有代码:
    import UIKit
    
    /**
     *    @author kl, 16-01-10 17:01:25
     *
     *    @brief 传值协议
     */
    protocol passValueDelegate {
        func passValue(var text: String)
    }
    
    class BViewController: UIViewController {
        // 1、声明属性
        var delegate: passValueDelegate?
        
        @IBOutlet weak var textField: UITextField!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
        }
        
        @IBAction func buttonActive(sender: AnyObject) {
            
            // 2、调用代理方法,把值传输出去
            self.delegate?.passValue(textField.text!)
            
            self.dismissViewControllerAnimated(true, completion: nil)
        }
    }
    
    • 接着是代理方的三步走,还是来看全部代码:
    import UIKit
    
    class AViewController: UIViewController, passValueDelegate // 1、遵守协议
    {
    
        @IBOutlet weak var textLabel: UILabel!
        
        override func viewDidLoad() {
            super.viewDidLoad()
    
        }
        
        @IBAction func buttonAction(sender: AnyObject) {
            let bVC = BViewController()
            
            // 2、设置代理
            bVC.delegate = self
            
            self.presentViewController(bVC, animated: true, completion: nil)
            
        }
    
        // 3、重写协议方法,取到传值
        func passValue(text: String) {
            textLabel.text = text
        }
    
    }
    

    二、闭包

    在swift中对闭包有了很好的支持,相当于C和Objective-C的blocks或者Python的lambdas。而且相对于blocks更加灵活一些。这里简单介绍一下使用闭包传递信息的方法。

    • 需要在B类文件中做的事情:

    1、在B类先利用typealias声明一个闭包类型:

    typealias nameValue = (String)->Void
    

    2、然后在声明一个此类型的属性:

        var nameText: nameValue?
    

    3、掉用一次闭包属性把值传出去,此处是在Button的跳转方法中调用的:

            // 使用闭包传值出去
            self.nameText!(self.bNameTextField.text!)
    

    4、再添加一个方法用于传值:

        // 闭包方法
        func returnNameValue(name: nameValue) {
            self.nameText = name
        }
    
    • 在A类文件中做的事情:

    1、调用一次A类对象的闭包传值方法拿到值,这里是在Button的跳转方法里调用的:

            // 取到闭包传递的值
            bVC.returnNameValue { (name) -> Void in
                self.nameTextField.text = name
            }
    
    • 最后有两个页面的全部代码,可以参照整体来看。

    三、使用NSNotificationCenter

    在swift语言中通知机制几乎没什么太大变化,还是以NSNotificationCenter为中介者,通过String类型标识来广播和接受信息。一般步骤是广播-接收-移除观察者,最后一步千万不能忘,收到信息记得移除观察者,不然会产生一些意料之外不可预测的情况发生,而且对系统资源也是一种浪费。

    1、A发出一个名为"name"的广播,广播内容是A页面上的textField所输入的内容,这里是写在跳转语句后边的,以确保发送的广播是输入完成以后的:

        @IBAction func buttonAction(sender: AnyObject) {
            let bVC = BViewController()
            
            // 取到闭包传递的值
            bVC.returnNameValue { (name) -> Void in
                self.nameTextField.text = name
            }
            
            // 2、设置代理
            bVC.delegate = self
            
            self.presentViewController(bVC, animated: true, completion: nil)
            
            // 发出广播
            NSNotificationCenter.defaultCenter().postNotificationName("name", object: self.nameTextField.text)
        }
    

    2、在B类中接收信息,并在收到时执行指定方法,方法的参数也还是跟Objective-C中一样,第一个为要注册的观察者;第二个同样是SEL类型的参数,不过在swift中没有了@selector关键字,采用以String类型输入要执行的方法名,这个跟OC中是有些区别的;第三个name参数即为要接收的信息的名字,这里采用String类型作为标识;最后一个参数同样是是否指定信息的发送者,填写的话便表示你只需要你填写的那个对象发出的信息,这里nil表示不指定对象:

        override func viewDidLoad() {
            super.viewDidLoad()
            self.bNameTextField.clearButtonMode = .WhileEditing
            self.textField.clearButtonMode = .WhileEditing
            
            // 注册为观察者,接收信息
            NSNotificationCenter.defaultCenter().addObserver(self, selector: "printName:", name: "name", object: nil)
        }
    
    • 方法内容:
        func printName(notifaction: NSNotification) {
            print(notifaction.object)
            self.bNameTextField.text = notifaction.object as? String
        }
    

    3、在方法中添加移除观察者者的代码:

        func printName(notifaction: NSNotification) {
            print(notifaction.object)
            self.bNameTextField.text = notifaction.object as? String
            NSNotificationCenter.defaultCenter().removeObserver(self)
        }
    

    最后还是借用上次的图:


    • 这样A中的nameTextField和B中的bNameTextField就相连接起来了,在这两个控件中输入信息在更换页面时都会显示在另一个控件上。从B到A是采用的是闭包传值,而从A到B时采用的是广播传值。

    最后的A类文件内容:

    import UIKit
    class AViewController: UIViewController, passValueDelegate // 1、遵守协议
    {
        @IBOutlet weak var textLabel: UILabel!
        @IBOutlet weak var nameTextField: UITextField!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.nameTextField.clearButtonMode = .WhileEditing
        }
            
        @IBAction func buttonAction(sender: AnyObject) {
            let bVC = BViewController()
            
            // 取到闭包传递的值
            bVC.returnNameValue { (name) -> Void in
                self.nameTextField.text = name
            }
            
            // 2、设置代理
            bVC.delegate = self
            
            self.presentViewController(bVC, animated: true, completion: nil)
            
            // 发出广播
            NSNotificationCenter.defaultCenter().postNotificationName("name", object: self.nameTextField.text)
        }
        
        // 3、重写协议方法,取到传值
        func passValue(text: String) {
            textLabel.text = text
        }
        
    
    }
    
    最后的B类文件内容:
    import UIKit
    
    protocol passValueDelegate {
        func passValue(var text: String)
    }
    
    typealias nameValue = (String)->Void
    
    class BViewController: UIViewController {
        // 1、声明属性
        var delegate: passValueDelegate?
        
        @IBOutlet weak var textField: UITextField!
        @IBOutlet weak var bNameTextField: UITextField!
        var nameText: nameValue?
        
        override func viewDidLoad() {
            super.viewDidLoad()
            self.bNameTextField.clearButtonMode = .WhileEditing
            self.textField.clearButtonMode = .WhileEditing
            
            // 注册为观察者,接收信息
            NSNotificationCenter.defaultCenter().addObserver(self, selector: "printName:", name: "name", object: nil)
        }
        
        @IBAction func buttonActive(sender: AnyObject) {
            // 2、调用代理方法,把值传输出去
            self.delegate?.passValue(textField.text!)
            
            // 使用闭包传值出去
            self.nameText!(self.bNameTextField.text!)
            
            self.dismissViewControllerAnimated(true, completion: nil)
        }
        
        func printName(notifaction: NSNotification) {
            print(notifaction.object)
            self.bNameTextField.text = notifaction.object as? String
            NSNotificationCenter.defaultCenter().removeObserver(self)
        }
        
        // 闭包方法
        func returnNameValue(name: nameValue) {
            self.nameText = name
        }
    }
    

    需要代码戳这里

    相关文章

      网友评论

      • 1ef8e6a45b9f:采用协议的方式有些疑问,A中点击button才设置代理,那B发送值的时候,A中并没有设置代理吧
        1ef8e6a45b9f:@eric_cartman 就是说你在B中发送消息的时候A并没有被B代理, 这样不会收到数据的吧?
      • 鹤鹤:点击navigationbar上的返回按钮怎么传值
        486b0dc8ccb3:@鹤鹤 viewWillDisppear

      本文标题:iOS页面传值问题(swift2.0篇)

      本文链接:https://www.haomeiwen.com/subject/sumqkttx.html