美文网首页
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