美文网首页
Swift采用闭包、单例、消息中心正向传值和反向传值

Swift采用闭包、单例、消息中心正向传值和反向传值

作者: T92 | 来源:发表于2016-09-04 13:59 被阅读533次

    正向传值:将上一个界面的值传到下一个界面

    方法:
    1.在下一个界面中声明一个要传的值的类型的属性。
    2.上一个界面弹出下一个界面的时候,通过属性传值
    3.在下一个界面中使用传过去的值(在生命周期ViewDidload以及ViewDidload以后调用的方法中都可以用)

    例子:将上一个界面(first)文本输入框的文字传到下一个界面(second)。只需要在下一个界面(second)中声明一个String类型的属性

    • 创建window
    import UIKit
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
    
        func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            
            //创建window
            self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
            //设置背景颜色
            self.window?.backgroundColor = UIColor.whiteColor()
            //设置根视图控制器
            self.window?.rootViewController = FirstViewController()
            return true
        }
    }
    
    • 创建需要传值的第一个视图控制器
    import UIKit
    
    //正向传值:将上一个界面的值传到下一个界面
    //方法:
    //1.在下一个界面中声明一个要传的值的类型的属性。(下一个视图控制器见)
    //2.上一个界面弹出下一个界面的时候,通过属性传值
    //3.在下一个界面中使用传过去的值(在生命周期ViewDidload以及ViewDidload以后调用的方法中都可以用)
    class FirstViewController: UIViewController {
    
        let textField = UITextField()
        override func viewDidLoad() {
            super.viewDidLoad()
            //设置背景颜色
            self.view.backgroundColor = UIColor.greenColor()
            //添加按钮
            let btn = UIButton(frame: CGRectMake(0,100,100,50))
            btn.setTitle("下一页", forState: .Normal)
            self.view.addSubview(btn)
            btn.addTarget(self, action: "btnAction", forControlEvents: .TouchUpInside)
            //添加文本输入框
            textField.frame = CGRectMake(100,100,200,50)
            textField.backgroundColor = UIColor.grayColor()
            textField.clearButtonMode = .Always
            self.view.addSubview(textField)
        }
    
    }
    
    extension FirstViewController{
        func btnAction(){
            
            //1.创建下一页对应的视图控制器对象
            let second = SecondViewController()
            
            //开始传值
            second.value = self.textField.text
            
            //点击按钮进入下一页
            //2.将视图控制器展示出来(模态化弹出下一个视图)
            //参数1:想要显示的视图控制器对象(实质是展示该控制器的view)
            //参数2:是否要动画效果
            //参数3:界面切换完成后需要执行代码的闭包
            self.presentViewController(second, animated: true, completion: nil)
        }
    }
    
    • 创建需要接收值的第二个视图控制器
    import UIKit
    
    class SecondViewController: UIViewController {
        let label = UILabel()
        
        //声明一个属性来接收从上一个界面传下来的值
        var value:String? = nil
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            //创建界面
            //背景颜色
            self.view.backgroundColor = UIColor.redColor()
            //创建按钮
            let btn = UIButton(frame: CGRectMake(0,100,100,50))
            btn.setTitle("上一页", forState: .Normal)
            self.view.addSubview(btn)
            btn.addTarget(self, action: "btnAction", forControlEvents: .TouchUpInside)
            
            //添加label
            label.frame = CGRectMake(100,100,200,50)
            self.view.addSubview(label)
            
            //使用上一个界面传下来的值
            self.label.text = self.value
        }
    }
    
    extension SecondViewController{
        func btnAction(){
            //回到上一页(注意:只有通过present的形式添加的视图控制器才能通过dismiss方法让其消失并且从内存中销毁)
            //参数1:是否动画
            //参数2:当前页面消失之后要执行代码的闭包
            self.dismissViewControllerAnimated(true, completion: nil)
        }
    }
    

    反向传值

    反向传值最常见三种方法,闭包反向传值、消息中心反向传值、单例反向传值

    利用闭包反向传值

    用闭包做反向传值,就是利用闭包的声明、实现和调用,方法步骤:
    1.在下一个界面中声明闭包(将要传的值通过闭包的参数来传)
    2.在上一个界面中界面跳转到下一个界面的时候去实现闭包
    3.在下一个界面消失的时候去调用闭包

    • 创建window
    import UIKit
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
    
        func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            
            self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
            let root = First()
            self.window?.rootViewController = root 
            return true
        }
    }
    
    • 由于以后两个视图控制器都有相同的地方,因此我们先创建一个他们的父类视图控制器
    import UIKit
    
    class myViewController: UIViewController {
        
        let textField = UITextField()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            creatUI()
        }
    
        func creatUI(){
            
            self.view.backgroundColor = UIColor(red:  CGFloat(arc4random() % 256) / 255, green:  CGFloat(arc4random() % 256) / 255, blue:  CGFloat(arc4random() % 256) / 255, alpha: 1)
            
            let btn = UIButton(frame: CGRectMake(0,0,100,50))
            self.view.addSubview(btn)
            btn.setTitle(self.title, forState: .Normal)
            btn.backgroundColor = UIColor.blackColor()
            btn.addTarget(self, action: "btnAction:", forControlEvents: .TouchUpInside)
            
            textField.frame = CGRectMake(100,100, 100, 50)
            textField.backgroundColor = UIColor.grayColor()
            self.view.addSubview(textField)
        }
        
        func btnAction(btn:UIButton){
            
        }
    }
    
    • 为了文章的整体结构,我先创建第一个视图控制器,但是阅读代码的时候最好按着方法步骤进行阅读,可以跳到第二个视图控制器看一下声明的闭包属性
    import UIKit
    //用闭包做反向传值,就是利用闭包的声明、实现和调用:
    //1.在下一个界面中声明闭包(将要传的值通过闭包的参数来传)
    //2.在上一个界面中界面跳转到下一个界面的时候去实现闭包
    //3.在下一个界面消失的时候去调用闭包
    class First: myViewController {
        override func viewDidLoad() {
            self.title = "界面1"//像这种属性一定要写在调用父类相应方法前面,便于调用以后能找到对应的值
            super.viewDidLoad()
        }
        
        override func btnAction(btn: UIButton) {
            let second = Second()
            
            //2.实现闭包
            second.sendeValue = {(value) in
                self.textField.text = value
            }
            self.presentViewController(second, animated: true, completion: nil)
        }
    }
    
    • 创建第二个视图控制器
    import UIKit
    
    class Second: myViewController {
        //1.声明闭包属性
        var sendeValue:((String) -> Void)? = nil
        
        override func viewDidLoad() {
            self.title = "界面2"
            super.viewDidLoad()
        }
        
        override func btnAction(btn: UIButton) {
            //3.调用闭包
            self.sendeValue!(self.textField.text!)
            self.dismissViewControllerAnimated(true, completion: nil)
        }
    }
    

    使用消息中心反向传值

    消息中心相当于生活中的广播站。作用:1.发送消息,2.一个消息中心可以发送多条消息,每条消息以不同的消息名来区分

    观察者:相当于收音机。作用:1.接收消息,2.能接收消息的前提:a.消息中心发送消息并且是实时的,b.观察者观察的消息名要和消息中心发送的消息的消息名保持一致。3.同一个观察者可以接收不同的消息

    消息:消息中心发出的内容(观察者接受的内容)

    消息中心作反向传值:在下一个界面中使用消息中心发送消息(消息的内容就是要传的值);在上一个界面注册观察者来接收消息

    注意
    在使用观察者时记得释放观察者,下面的例子是没有释放的,造成内存泄露
    以OC为例:在dealloc方法中,你需要做
    1.如果使用了NSTimer,那么要调用invalidate方法使其失效
    2.如果使用了观察者,那么要移除观察者
    3.如果使用了系统底层的C函数申请了内存,那么要在此处手动释放内存
    申请方法对应释放方法
    malloc() --->free() --->nil
    CFXxxCreat --->CFRelease

    例子:Second视图控制器发消息,First和Middle视图控制器接收消息

    • 创建window
    import UIKit
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
    
        func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            
            self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
            let root = First()
            self.window?.rootViewController = root
            
            return true
        }
    }
    
    • 创建视图控制器的父类
    import UIKit
    
    class myViewController: UIViewController {
        
        let textField = UITextField()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            creatUI()
        }
    
        func creatUI(){
            
            self.view.backgroundColor = UIColor(red:  CGFloat(arc4random() % 256) / 255, green:  CGFloat(arc4random() % 256) / 255, blue:  CGFloat(arc4random() % 256) / 255, alpha: 1)
            
            let btn = UIButton(frame: CGRectMake(0,0,100,50))
            self.view.addSubview(btn)
            btn.setTitle(self.title, forState: .Normal)
            btn.backgroundColor = UIColor.blackColor()
            btn.addTarget(self, action: "btnAction:", forControlEvents: .TouchUpInside)
            
            textField.frame = CGRectMake(100,100, 100, 50)
            textField.backgroundColor = UIColor.grayColor()
            self.view.addSubview(textField)
        }
        
        func btnAction(btn:UIButton){
            
        }
    }
    
    • 这里先创建First视图控制器,阅读代码时应该按照步骤阅读
    import UIKit
    //消息中心相当于生活中的广播站。作用:1.发送消息,2.一个消息中心可以发送多条消息,每条消息以不同的消息名来区分
    //观察者:相当于收音机。作用:1.接收消息,2.能接收消息的前提:a.消息中心发送消息并且是实时的,b.观察者观察的消息名要和消息中心发送的消息的消息名保持一致。3.同一个观察者可以接收不同的消息
    //消息:消息中心发出的内容(观察者接受的内容)
    
    //消息中心作反向传值:在下一个界面中使用消息中心发送消息(消息的内容就是要传的值);在上一个界面注册观察者来接收消息
    class First: myViewController {
        override func viewDidLoad() {
            self.title = "界面1"
            super.viewDidLoad()
            
            //2.注册成为观察者
            //参数1:观察者对象(想要把谁作为观察者)
            //参数2:消息中心发送消息的时候观察者会自动调用的方法的selector(观察者接收到消息后会调用的方法),必须带一个参数,并且参数的类型为NSNotification
            //参数3:观察者要观察的消息的名字
            //参数4:??
            NSNotificationCenter.defaultCenter().addObserver(self, selector: "notificationgAction:", name: "nof1", object: nil)
        }
        
        func notificationgAction(nof:NSNotification){
            self.textField.text = nof.object as? String//(用String(nof.object)会转成可空类型)
        }
        
        override func btnAction(btn: UIButton) {
            let mid = Middle()
            
            self.presentViewController(mid, animated: true, completion: nil)
        }
    }
    
    • 创建Middle视图控制器
    import UIKit
    
    class Middle: myViewController {
    
        override func viewDidLoad() {
            self.title = "界面2"
            super.viewDidLoad()
            let btn = UIButton(frame: CGRectMake(150,0,100,50))
            btn.backgroundColor = UIColor.blackColor()
            btn.setTitle("返回", forState: .Normal)
            btn.addTarget(self, action: "btnAction", forControlEvents: .TouchUpInside)
            self.view.addSubview(btn)
            
            NSNotificationCenter.defaultCenter().addObserver(self, selector: "notificationgAction:", name: "nof1", object: nil)
            
        }
        func notificationgAction(nof:NSNotification){
            self.textField.text = nof.object as? String//(用String(nof.object)会转成可空类型)
        }
    
        func btnAction(){
            self.dismissViewControllerAnimated(true, completion: nil)
        }
        
        override func btnAction(btn: UIButton) {
            let second = Second()
            self.presentViewController(second, animated: true, completion: nil)
        }
    }
    
    • 创建Second视图控制器发消息
    import UIKit
    
    class Second: myViewController {
        
        override func viewDidLoad() {
            self.title = "界面3"
            super.viewDidLoad()
        }
        
        override func btnAction(btn: UIButton) {
            //1.使用消息中心发送消息
            //a.拿到消息中心(单例对象)
            //参数1:消息名
            //参数2:要发送的消息内容
            NSNotificationCenter.defaultCenter().postNotificationName("nof1", object: self.textField.text)
            
            self.dismissViewControllerAnimated(true, completion: nil)
        }
    }
    

    使用单例进行反向传值

    依照我的理解,利用单例反向传值需要创建一个单独的类来保存相关的数据,在这个类里面会创建出一个唯一的对象(单例对象),传值的对象通过把值赋给单例对象的相关属性,其他的类需要得到值就直接取得单例对象相关属性的值即可。

    例子:创建保存值的类ValueManeger,Second传值,First接收值

    • 创建window
    import UIKit
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
    
    
        func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            
            self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
            let root = First()
            self.window?.rootViewController = root
            
            return true
        }
    }
    
    • 创建视图控制器的父类
    import UIKit
    
    class myViewController: UIViewController {
        
        let textField = UITextField()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            creatUI()
        }
    
        func creatUI(){
            
            self.view.backgroundColor = UIColor(red:  CGFloat(arc4random() % 256) / 255, green:  CGFloat(arc4random() % 256) / 255, blue:  CGFloat(arc4random() % 256) / 255, alpha: 1)
            
            let btn = UIButton(frame: CGRectMake(0,0,100,50))
            self.view.addSubview(btn)
            btn.setTitle(self.title, forState: .Normal)
            btn.backgroundColor = UIColor.blackColor()
            btn.addTarget(self, action: "btnAction:", forControlEvents: .TouchUpInside)
            
            textField.frame = CGRectMake(100,100, 100, 50)
            textField.backgroundColor = UIColor.grayColor()
            self.view.addSubview(textField)
        }
        
        func btnAction(btn:UIButton){
            
        }
    }
    
    • 创建单例对象

    注意
    单例对象的相关属性要根据需要传的值进行设定

    import UIKit
    
    class ValueManeger: NSObject {
        
        //1.保证当前这个类只能创建出一个对象,而且这个对象必须通过defalutManager才能拿到
        //通过这个属性拿到当前这个类唯一的对象
        static let defalutManager = ValueManeger()
        //2.私有化构造方法
        private override init() {
            
        }
        
        //声明一个属性的类型是需要传的值的类型,这里是String型
        var sendValue = ""
    }
    
    • 创建First视图控制器
    import UIKit
    
    class First: myViewController {
        override func viewDidLoad() {
            self.title = "界面1"
            super.viewDidLoad()
            
        }
        
        override func viewWillAppear(animated: Bool) {
            super.viewWillAppear(animated)
            
            //通过单例对象去拿到值
            self.textField.text = ValueManeger.defalutManager.sendValue
        }
        override func btnAction(btn: UIButton) {
            let second = Second()
            self.presentViewController(second, animated: true, completion: nil)
        }
    }
    
    • 创建Second视图控制器
    import UIKit
    
    class Second: myViewController {
        
        
        override func viewDidLoad() {
            self.title = "界面2"
            super.viewDidLoad()
        }
        
        override func btnAction(btn: UIButton) {
            //传值
            ValueManeger.defalutManager.sendValue = self.textField.text!
            
            self.dismissViewControllerAnimated(true, completion: nil)
        }
    }
    

    相关文章

      网友评论

          本文标题:Swift采用闭包、单例、消息中心正向传值和反向传值

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