Swift传值+视图跳转

文章内容:

  • Swift中的常用传值方式
  • 不同情况下视图的几种跳转方法详解
  • xib的使用
  • 简单介绍一下单例设计模式
  • 单例的创建和使用方法
  • NSUserDefaults的用法

由于我最近正在进阶Swift的原因 控件都是手动创建。避免繁琐你可以在SB中直接创建并布局。

属性传值

简单实现一个demo

首先国际惯例,打开Xcode新建一个Project,选择SingleViewApplication 。然后在viewDidLoad中创建输入框和按钮

    //创建输入框
    textField = UITextField(frame: CGRectMake(0,200,200,30))
    textField.center.x = self.view.center.x
    textField.borderStyle = UITextBorderStyle.RoundedRect
  
    //创建按钮和对应的触发动作 添加到主视图上
    let button1 = UIButton(type: .System)
    button1.frame = CGRectMake(20,300,60,30)
    button1.setTitle("属性传值", forState: .Normal)
    button1.addTarget(self, action: "buttonAction1", forControlEvents: .TouchUpInside)
    
    let button2 = UIButton(type: .System)
    button2.frame = CGRectMake(20,300,60,30)
    button2.center.x = self.view.center.x
    button2.setTitle("代理传值", forState: .Normal)
    button2.addTarget(self, action: "buttonAction2", forControlEvents: .TouchUpInside)
    
    let button3 = UIButton(type: .System)
    button3.frame = CGRectMake(20,300,60,30)
    button3.center.x = self.view.frame.width - button1.center.x
    button3.setTitle("单例传值", forState: .Normal)
    button3.addTarget(self, action: "buttonAction3", forControlEvents: .TouchUpInside)
    
    self.view.addSubview(button1)
    self.view.addSubview(button2)
    self.view.addSubview(button3)
    self.view.addSubview(textField)
  • 注意UIButton的buttonType属性是只读计算属性 不能修改 所以最好用带type参数的初始化方法初始化

下面当然是添加按钮的触发方法

func buttonAction1(){

}

func buttonAction2(){
 
}

  
func buttonAction3(){

}

既然是不同界面之间的传值,那么除了系统默认的ViewController还需要再创建3个视图控制器。这里使用xib

  • 选择菜单栏File -> New -> File
  • 在弹出的对话框中选择IOS下Source中的Cocoa Touch Class文件
  • 输入类名,并继承于UIViewController,选中使用xib复选项 。击next

重复步骤再创建2个xib(由于前面取名FirstVC 我这里分别取名为SecondVC和ThirdVC)
然后点按每个xib的File’s Owner 确保为对应的类(通过创建类文件同时创建xib 系统默认是绑定好了的 这里是为了保住万无一失)

考虑到刚学Swift的同学可能只接触过StoryBoard,没接触到xib。所以这里简单解释一下xib。

  • xib和StoryBoard均可通过拖拽控件等方式实现可视化编程。
  • 区别在于StoryBoard其实就是多个xib的组合。
  • 相比StoryBoard 通过创建xib实现视图的分类管理能使整个Project看起来更有条理。(稍后会介绍xib的使用方法)

属性传值

我们通过在输入框中输入数据 然后点击按钮跳转到FirstVC 并通过一个标签显示输入的数据的方式实现属性传值。

首先打开FirstVC.Swift文件 添加一个属性

 var value:String!

修改viewDidLoad方法,建立标签和关闭按钮

 override func viewDidLoad() {
    super.viewDidLoad()
    
    let valueLable = UILabel(frame: CGRectMake(0,0,300,40))
    valueLable.center = self.view.center
    //显示传递的数据到lable
    valueLable.text = value
    
    let closeButton = UIButton(type: .System)
    closeButton.frame = CGRectMake(0, 30, 60, 30)
    closeButton.setTitle("关闭", forState: .Normal)
    closeButton.addTarget(self, action: "closeVC", forControlEvents: .TouchUpInside)
    
    self.view.addSubview(valueLable)
    self.view.addSubview(closeButton)
}

再实现关闭按钮的触发方法

func closeVC(){

    self.dismissViewControllerAnimated(true, completion: nil)
}

好了,终于要开始传值了。在ViewController.Swift中的buttonAction1方法中添加下面的代码

func buttonAction1(){

    let firstVC = FirstVC(nibName:"FirstVC",bundle: nil)
    
    firstVC.value = textField.text
    presentViewController(firstVC, animated: true, completion: nil)
}

解释一下:

  • 首先 通过xib的名字初始化一个FirstVC实例对象(这里注意:在FirstVC后直接打括号,并不会有带nibName 和 bundle 参数的初始化方法,需要手动打出)
  • 然后 将输入框输入的值赋给 firstVC的value
  • 通过presentViewController方法跳转到firstVC视图控制器

顺便提一下另一个视图跳转的方法:

 performSegueWithIdentifier("Segue跳转名字", sender: self) 
  • 其中Segue跳转名字就是你在StoryBoard中 在不同控制器中进行连线跳转时 点击控制器间蓝色的线条 右边属性面板上StoryBoard Segue下的Identifier 需要手动设置
  • sender是个AnyObject类型 看实际需要传入参数

如果你是用StoryBoard连线跳转实现传值请重写这个父类方法

 override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if(segue.identifier == "segue跳转名字")
    let firstVC = segue.destinationViewController as FirstVC
    firstVC.value = textField.text
 }
  • 如其名字prepareForSegue 这个方法是为当前视图进行跳转时做最后的准备,所以这是最后的传值和处理数据的机会
  • 这个方法来自UIViewController,由于所有视图控制器默认均继承自UIViewController。所以任何一个控制器都有此方法 只需要override重写一下
  • 当然一般我们的跳转动作不只一个 这时候就需要判断segue.identifier 实现不同的跳转传

当然你也可以使用StoryBoard中视图的Identifier进行跳转。只需调用StoryBoard的instantiateViewControllerWithIdentifier方法获取实例对象 再结合presentViewController方法跳转 如下:

var firstVC = self.storyboard?.instantiateViewControllerWithIdentifier("FirstViewController") as FirstViewController
    presentViewController(firstVC, animated: true, completion: nil)

当你有多个StoryBoard时 可以类比xib的实例对象获取方式

var storyboard = UIStoryboard(name: "New", bundle: nil)
var newVC = storyboard.instantiateViewControllerWithIdentifier("NewViewController") as NewViewController
presentViewController(newVC, animated: true, completion: nil)

代理反向传值

我们通过点击之前在ViewController上创建的代理传值按钮跳转到SecondVC,然后在SecondVC的输入框中输入数据 点击关闭按钮 在ViewController的输入框中显示数据的方式。

首先打开SecondVC.Swift文件添加全局textField

var textField:UITextField!

在viewDidLoad中添加下面代码 并在下面实现按钮关闭视图的方法

override func viewDidLoad() {
    textField = UITextField(frame: CGRectMake(0,200,200,30))
    textField.center.x = 187.5
    textField.borderStyle = .RoundedRect
    self.view.addSubview(textField)
    
    let closeButton = UIButton(type: .System)
    closeButton.frame = CGRectMake(0, 30, 60, 30)
    closeButton.setTitle("关闭", forState: .Normal)
    closeButton.addTarget(self, action: "closeVC", forControlEvents: .TouchUpInside)
    self.view.addSubview(closeButton)
}
func closeVC(){

       self.dismissViewControllerAnimated(true, completion: nil)
}

通过代理反向传值。通俗的说就是先定义一个protocol(协议)同时在协议里声明一个方法,然后在需要传值的A类中定义一个属性delegate(代理),类型为定义的协议类型。然后在A类的某个地方调用协议的方法。因为协议里的方法只进行了声明,并未具体实现。它将具体的实现交给遵循这个协议的B类。这样通过协议-代理的模式A类让B类 做了一些 A类想让B类做的事情。当然我们这里是进行传值(把SecondVC输入框中输入的数据传给ViewController并显示在textField上)这类似于其它编程语言里的接口。如下:



在SecondVC类的上面添加代码

protocol SecondVCDelegate{

func passOnInformation(VC:SecondVC,value:String)
}
  • 系统命名协议的规则(类名+Delegate)
  • VC表示调用此方法的对象
  • value表示传出的数据

在SecondVC类中添加代理属性

var delegate:SecondVCDelegate?

修改closeVC方法

func closeVC(){
    //判断代理是否为空
    if (self.delegate != nil) {
         //传值     
        self.delegate?.passOnInformation(self, value: textField.text!)
    }
    self.dismissViewControllerAnimated(true, completion: nil)
}

你一定要意识到 现在SecondVC的代理属性本来就为空,因为我们还没有设置它的代理 😂 在哪里设置呢?既然我们是先从默认的ViewController跳转到SecondVC 再从SecondVC反向传值到ViewController。所以跳转到SecondVC的时候是个绝佳的机会。

下面打开ViewController.Swift
首先继承SecondVCDelegate协议

class ViewController: UIViewController,SecondVCDelegate {

再修改buttonAction2方法

func buttonAction2(){

    let secondVC = SecondVC(nibName:"SecondVC",bundle: nil)
    //设置secondVC代理为自己
    secondVC.delegate = self
    presentViewController(secondVC, animated: true, completion: nil)
    
}

这时候你会发现系统会报错,为什么呢?还少了什么?
那就是我们还没有实现协议里的方法 (再次强调继承协议必须实现协议里的方法)

最后在buttonAction2方法下面实现

func passOnInformation(VC: SecondVC, value: String) {
    //接收数据
    self.textField.text = value
    
}

完美🙄

单例传值

首先解释一下IOS里的单例模式:
单例模式是一种常用的软件设计模式。它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。(来自百度--)

优点就不说了,可以自行百度

iOS中单例的创建方法

class AppInstance {
static let sharedInstance = AppInstance()
 
       private init() {} // 私有化init方法
}
  • 一定注意要用Pravate把构造器私有化,因为Swift中默认所有对象的构造器都是public 防止其它其它对象使用它的默认初始化方法创建对象

例如下面这样构造将不会通过

var a1 = AppInstance() //不能通过

单例的使用方式

AppInstance.sharedInstance

不扯了,现在来通过单例传值。你可以自行创建一个单例🤔🤔🤔
当然还有更偷懒的方式,因为UIApplication就是一个单例,所以我们可以直接用它。

首先打开AppDelegate.Swift 在window属性下面添加一个value

var value:String?

再打开ThirdVC.Swift 在加载时给界面添加lable和关闭按钮 同时实现按钮的方法 和单例传值

override func viewDidLoad() {
    super.viewDidLoad()
    
    
    let closeButton = UIButton(type: .System)
    closeButton.frame = CGRectMake(0, 30, 60, 30)
    closeButton.setTitle("关闭", forState: .Normal)
    closeButton.addTarget(self, action: "closeVC", forControlEvents: .TouchUpInside)
    self.view.addSubview(closeButton)
    
    let lable = UILabel(frame: CGRectMake(0,200,100,30))
    lable.center.x = 187.5
    self.view.addSubview(label)

    //单例传值-接收数据
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    lable.text = appDelegate.value!

    // Do any additional setup after loading the view.
}

最后在ViewController的buttonAction3方法里添加代码

func buttonAction3(){

    //单例传值-传出数据
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    appDelegate.value = textField.text!
    //跳转视图
    let thirdVC = ThirdVC(nibName:"ThirdVC",bundle: nil)
    presentViewController(thirdVC, animated: true, completion: nil)    

}

单例还有很多 比如 NSUserDefaults 。它是一个轻量的经常用来保存数据的类,而且数据不会伴随App的退出而消失,当然也可以用来传值。它通过健-值对的方式存储和获取

 let userInfo = NSUserDefaults()
  userInfo.setValue(textField.text, forKey: "value")

 let userInfo = NSUserDefaults()  
 lable.text = userInfo.valueForKey("value") as! String

总结:

传值原理基本是都是通过先获取具体实例对象,然后通过某个属性或者媒介进行传值。

End

终于结束了😭 熬夜写的啊(头次写博文 有点慢😰)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容