正向传值:将上一个界面的值传到下一个界面
方法:
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)
}
}
网友评论