一篇文章學會頁面傳值的10種方法(下)

前五種方法點擊這兒:一篇文章學會頁面傳值的10種方法(上)

6、代理委托實現頁面之間的反向傳值

這一種方法就是運用協議實現傳值,這種方式也是在工程中常用的一種傳值方法。首先創建好ViewController和SubViewController,在ViewController中創建好一個展示信息的Label,在SubViewController中創建好一個TextFeild,我們實現在第二個界面點擊屏幕時,將TextFeild中的文字傳到第一個界面,然后讓背景顏色變色。

效果如下:

代理傳值.gif

第一步:

首先我們要弄清楚ViewController和SubViewController誰是代理方,誰是委托方。委托方制訂協議,并且擁有一個代理,代理方準守協議,并且實現協議中的方法。因為是從SubViewController中向ViewController中傳遞信息,SubViewController需要讓代理完成傳值的動作,所以這里SubViewController便是委托方

在SubViewController中我們指定一個協議BackValueProtocol:

extension ViewController:BackValueProtocol {
    func backValue(text: String, color: UIColor){}
}

因為我們要傳遞文字和顏色,所以協議里的方法帶有text:String 和color:UIColor 兩個參數

第二步:

制定好協議之后,我們還要給SubViewController添加一個代理屬性

var delegate: BackValueProtocol?

第三步:

然后就是給SubViewController指定一個代理人,當然,這里就是ViewController了
我們設置當點擊屏幕時跳轉到第二個界面,并且告訴第二個界面,ViewController就是他的代理方


 override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
 
        //獲取第二個界面
        let svc = SubViewController()
        self.presentViewController(svc, animated: true, completion: nil)
        //MARK:告訴第二個界面ViewController就是他的代理
        svc.delegate = self
    }

第四步:

接下來就是在ViewController中實現協議中的方法了

extension ViewController:BackValueProtocol {
    func backValue(text: String, color: UIColor) {
    //讓label的文字顯示為傳過來的 文字
        textLabel.text = text
        
        //讓背景顏色改變為傳過來的顏色
        self.view.backgroundColor = color
    }
}
效果如下:

第五步

最后就是執行傳值操作了,我們設置在點擊第二個界面時傳值所以,在SubViewController的touchBegan里開始傳值

 override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

        //B頁面根部不需要考慮傳值的目標和方法具體是誰,直接去調用自己的屬性即可
        //這種方式稱為回調,讓目標調用目標方法,參數為我傳入的TextField的值
        let color  = UIColor.redColor()
        
        //MARK:讓自己的代理去執行傳值操作
        self.delegate?.backValue(self.tf.text!, color: color)
        self.dismissViewControllerAnimated(true, completion: nil)
    }

到此為止,整個的反向傳值就完成了,整個步驟如下:

  1. 想好誰是委托方誰是代理方,委托方制定協議并擁有一個代理屬性
  2. 代理方遵守協議并實現協議中的方法
  3. 告訴委托方誰是代理
  4. 委托方告訴代理方去執行協議中的方法

7、使用TargetAction實現傳值

這種傳值方式和使用代理傳值有相似之處,大致的思想就是在有數據的界面進行傳值開始的指令,在接收數據的界面完成實質的傳值操作

效果如下:

TargetAction傳值.gif

首先,同樣ViewController和SubViewController,并分別設置好label和TextFeild

第一步

在SubViewController中我們設置兩個屬性:target和action

 //設置兩個屬性接收傳值目標和方法
    //用來去接收傳值的目標是任意目標
    var target: AnyObject?

    //用來去接收傳值的方法
    var action: Selector?

第二步

在SubViewController中,當點擊屏幕時發送傳值指令

 override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

//B頁面根部不需要考慮傳值的目標和方法具體是誰,直接去調用自己的屬性即可
        //MARK:這種方式稱為回調,讓目標調用目標方法,參數為我傳入的TextField的值
        
        self.target?.performSelector(self.action!, withObject: self.tf.text )
        
        
        self.dismissViewController
        

第三步

在ViewController中我們要給SubViewController指定是指真正的target,真正的 action是什么。

同樣。我們設置當點擊屏幕時,將這些信息告訴給SubVIewController,顯然,target是ViewController,action則是我們指定的某個實現方法

那么,我們首先要設定一個用來回傳數據的方法

    //定義一個用來去回傳數據的方法
    func backValue(string:String) {
        //通過傳進來的參數,給label賦值
        textLabel.text = string
    }

然后將target和action告訴SubViewController

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        //獲取SubViewController
        let svc = SubViewController()
        //通過正向傳值,來告訴B頁面回調時需要用到的參數
        svc.target = self
        
   //MARK:將action告訴SubViewController
   
   //NSSelectorFromString 方法是將一個字符串方法轉換成真正的方法名
        svc.action = NSSelectorFromString("backValue:")
        self.presentViewController(svc, animated: true, completion: nil)
    }

到此為止,當點擊ViewController屏幕時,將taget和action告訴了第二個界面,在第二個界面點擊屏幕時,執行了target action命令,實現了backValue方法,完成了完整的傳值操作

8、使用系統單例去傳值

這個方法就厲害了我的哥!使用UIApplication這個單例類去完成數據的存儲,將需要傳輸的數據存儲到一個公共的數據源中,任何一個界面的任何地方都可以使用里面的資源

效果圖如下:

系統單例傳值.gif

在工程中,我們對AppDelegate.swift文件都不陌生,這個文件配置好了window層,并且可以設置指定的很視圖控制器,在AppDelegate中我們知道它遵守了UIResponder和UIApplicationDelegate協議,而UIApplication便是一個系統提供的單例類,AppDelegate雖然不是單例類 ,但是共享的數據可以存放到這個類中

第一步

在AppDelegate聲明一個用來去和共享數據的數組,然后配置一個帶有的VC1,VC2和VC3的TabBarController做為根視圖控制器

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    //用來去共享數據的數組
    var datas = [String]()

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        //給數組里加一個原始數據
        datas.append("AD")
        
        //配置window
        window?.frame = UIScreen.mainScreen().bounds
        window?.backgroundColor = UIColor.whiteColor()

        let vc = ViewController()
        vc.view.backgroundColor = UIColor.redColor()
        let vc1 = ViewController1()
        vc1.view.backgroundColor = UIColor.yellowColor()
        let vc2 = ViewController2()
        vc2.view.backgroundColor = UIColor.blueColor()

        //設置標題
        vc.title = "視圖1"
        vc1.title = "視圖2"
        vc2.title = "視圖3"

        let tvc = UITabBarController()
        tvc.viewControllers = [vc,vc1,vc2]
        window?.rootViewController = tvc
        window?.makeKeyAndVisible()
        return true
    }

第二步

當點擊屏幕時,添加數據到公共的數據源中并且讀取出來
因為在VC1,VC2,VC3中的任何一個界面都可以完成相同操作,在這里只拿一個做展示

  1. 首先我們獲取UIApplication的單例類
  2. 通過單例類獲取AppDelegate
  3. 通過AppDelegate操作共享的數組

代碼如下:

 override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
   
        //獲取單例
        let application = UIApplication.sharedApplication()

        //通過這個單例獲取AppDelegate這個對象
        let appDelegate = application.delegate as! AppDelegate

        //通過這個AppDelegate來操作共享的datas數組
        appDelegate.datas.append("VC-\(n + 1)")
        print(appDelegate.datas)
    }

當點擊屏幕時,我們可以看到控制臺中打印出來了我們設置的初始值“AD”和新加入的值“VC-2”,

同樣在VC2中我們使用同樣的放法獲取數據

import UIKit

class ViewController1: UIViewController {
    var n = 1
    override func viewDidLoad() {
        super.viewDidLoad()

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

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        //UIApplication 是一個單例類
        //AppDelegate并不是單例類,但是共享的數據放到了這個類里

        //獲取單例
        let application = UIApplication.sharedApplication()

        //通過這個單例獲取AppDelegate這個對象
        let appDelegate = application.delegate as! AppDelegate

        //銅鼓這個APPDelegate來操作共享的datas數組
        appDelegate.datas.append("VC1-\(n + 1)")
        print(appDelegate.datas)
    }
}

在控制臺中我們看到VC1傳入的數據和VC2自己傳入的數據,實現了頁面之間的傳值

9、使用自定義的單例實現頁面之間的傳值

本方法和第8中方法的實質原理是一樣的,共享一個公共的數據源數組,任何一個界面都可以通過單例找到這個數據源進而進行寫入和讀取的操作,只不過,這里我們使用了自己的單例。

首先將根視圖控制器設置為帶有三個界面的標簽控制器

1、自定義一個單例

在工程中我們繼承于NSObject新建一個SingleInstance單例類,在單例類中我們聲明一個公共的數據源,并且提供一個公開用來去獲取單例的方法

不會創建單例的小伙伴點這兒

//創建一個單例類
class SingleInstance: NSObject {


    //在單例類中,有一個用來共享數據的數組
    var datas = [String]()
    //創建一個靜態或者全局變量,保存當前單例實例值
    private static let singleInstance = SingleInstance()
    //私有化構造方法
    private override init() {
        //給數組加一個原始數據
        datas.append("SI")
    }

    //提供一個公開的用來去獲取單例的方法
    class func defaultSingleInstance() ->SingleInstance {
        //返回初始化好的靜態變量值
        return singleInstance
    }
}

2、在VC1中寫入并讀取數據

當點擊屏幕時,將數據傳入公共數據源,并讀出

class ViewController1: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

    }
    
    //MARK:-當點擊屏幕時寫入并讀取數據
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        //獲取單例對象
        let si = SingleInstance.defaultSingleInstance()
        //給單例中的數組加一個數據
        si.datas.append("VC1")
        print(si.datas)
    }
}

3、在VC2中寫入并讀取數據

class ViewController2: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }
    
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        //獲取單例對象
        let si = SingleInstance.defaultSingleInstance()
        //給單例中的數組加一個數據
        si.datas.append("VC2")
        print(si.datas)
    }
}

在VC2中同樣可以通過單例找到數據源,并且實現了頁面之間的傳值

10、通過通知中心NSNotificationCenter傳值

在這里我們實現用通知中心的方法實現從VC中向VC1和VC2中傳值

通知傳值類似于廣播和接收信號的過程,我們在AppDelegate中共享一個公共的數據源,在傳值的界面設置了一個公共的廣播站,并且獲取這個數據源,需要接收數據的頁面就相當于一個收音機,一旦收到廣播站的信號,便去執行相應的方法

1、在AppDelegate中我們共享一個數據源

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    //用來保存共享數據的數組
    var datas = [Int]()

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        window = UIWindow()
        window?.frame = UIScreen.mainScreen().bounds
        window?.backgroundColor = UIColor.whiteColor()
 
        let vc = ViewController()
        vc.title = "VC"
        
        let vc1 = ViewController1()
        vc1.title = "VC1"
        
        let vc2 = ViewController2()
        vc2.title = "VC2"

        let tvc = UITabBarController()
        tvc.viewControllers = [vc,vc1,vc2]
        window?.rootViewController = tvc
        window?.makeKeyAndVisible()
        return true
    }

2、在VC1和VC2中擴展一個成為觀察者的方法,并設置接收到數據后需要執行的動作

擴展為觀察者的方法

extension ViewController1{
    //成為觀察者的方法
    func becomeObserver(){
        //先去獲取通知中心的單例
        let notificationCenter = NSNotificationCenter.defaultCenter()
        //向通知中心去加入觀察者
        notificationCenter.addObserver(self, selector: #selector(ViewController1.sum), name: "又有新數據啦!", object: nil)
    }
}

接收到信號后執行的動作

 //觀察者的響應方法
    func sum(){
        let datas = ((UIApplication.sharedApplication().delegate)as!AppDelegate).datas
        var sum = 0
        for i in datas{
            sum += i
        }
        print("VC1計算求和得:\(sum)")
    }

完整代碼如下:

class ViewController1: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
extension ViewController1{
    //成為觀察者的方法
    func becomeObserver(){
        //先去獲取通知中心的單例
        let notificationCenter = NSNotificationCenter.defaultCenter()
        //向通知中心去加入觀察者
        notificationCenter.addObserver(self, selector: #selector(ViewController1.sum), name: "又有新數據啦!", object: nil)
    }
    //觀察者的響應方法
    func sum(){
        let datas = ((UIApplication.sharedApplication().delegate)as!AppDelegate).datas
        var sum = 0
        for i in datas{
            sum += i
        }
        print("VC1計算求和得:\(sum)")
    }
    
}

3、回到AppDelegate中將VC1和VC2注冊成為觀察者

  //讓vc1,注冊成為觀察者
  vc1.becomeObserver()
  //讓vc2,注冊成為觀察者
  vc2.becomeObserver()
        

4、當點擊VC屏幕時寫入數據并發送通知

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
     //在這里,向數據源中去增加數據,并發送通知
        
        //隨機生成一個數字
        let num = arc4random_uniform(100)
        
        //通過UIApplication獲取單例類并獲取數據
        ((UIApplication.sharedApplication().delegate) as! AppDelegate).datas.append(Int(num))
        
        //MARK-獲取通知中心
        let nc = NSNotificationCenter.defaultCenter()
        //發送通知
         nc.postNotificationName("又有新數據啦!", object: nil)
             
    }

在控制臺中我們就可以看見當點擊VC的時候,VC1和VC2都執行了響應的方法

效果如下:

通知中心傳值.gif

到此,頁面傳值的10種方法全部介紹完了,文中有描述不當之處希望大家包涵和指正,有需要源代碼的伙伴們可以點擊這兒下載!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,489評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,290評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,510評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,866評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,036評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,585評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,331評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,536評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,754評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,273評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,505評論 2 379

推薦閱讀更多精彩內容