頁面間的資料傳遞(一)

總的來說,先前練習的內容都是事先建立好的頁面
如果主頁分別可以開啟A、B、C三個頁面
那就得事先準備好三個頁面的Controller及內容
接下來建立segue來觸發事件開啟目的頁面

All controller setting

上述所說的執行序中並沒有帶著資料
顯示的頁面根據segue指向的Controller動作
有多少頁面就得拉多少segue
當ViewController一多,處理起來可能還會卡卡lag

那如果在執行序當中帶著資料
頁面內容是否就可以利用這些資料來做變化?
是不是也可以減少需要的Controller的量

資料傳遞又分別有兩種狀況:

  1. 傳遞資料到下一頁
  2. 資料回傳到上一頁

以下先針對傳遞資料到下一頁來做練習/說明
App在頁面切換上,我們多半都會拉好主畫面到下一頁的segue
並選擇換頁的方式要以show或是present去顯示

新生成的project內雖然有一組ViewController.swift的檔案
現在先刪除它再另外建立一個繼承UIViewController的檔案
在這個練習裡面會用到兩個畫面,所以新增兩組檔案

Add a new file for ViewController

在生成的檔案底下有個被封(ㄓㄨˋ)印(ㄐㄧㄝˇ)的func prepare
解除它的註解(/**/)就可以透過該程序傳遞資料
其功能大意是:透過seque.destination獲取新的ViewControlle
並將選取的物件內容傳遞到新的ViewController去

Prepare function

接下來就看新頁面需要哪種呈現的方式,present或是push
不從Storyboard連segue切換畫面(一)
不從Storyboard連segue切換畫面(二)

初步完成單純換頁/返回後就可以開始以下資料的傳遞
我們先給按鈕兩個特定的名稱,新頁面新增ImageView用來顯示圖片
當執行新頁面換頁的時候,根據按鈕上的名稱顯示該人物照片
※在這邊要傳遞的資料就是“按鈕上的名稱”

Select Controller and Show Controller

這邊首先提到的是按鈕換頁不透過seque的方式
因為不透過seque,所以傳遞資料的方式不會用到prepare function
(喂~那你前面講這麼多到底是要做啥💢
雖然不會用到,不過兩種用法是差不多的
直接將資料傳遞的執行序放在Button觸發的func內

若是單純切換頁面或新頁面已經有固定的內容,不需要傳遞資料
我們就可以用先前提到的方式直接顯示新頁面

if let controller = storyboard?.instantiateViewController(withIdentifier: “secondPage”) {
present(controller, animated: true, completion: nil)
}

可是我們要將按鈕上的文字當成資料傳送到新頁面
就不能用上面的方式,需要用新的方式
我們將最後要指向的storyboard ID轉型為ShowViewController
如果不轉型,無法取得該頁面的property

if let controller = storyboard?.instantiateViewController(withIdentifier: "PhotoView") as? ShowViewController {
present(controller, animated: true, completion: nil)
}

轉型後我們就可以存取新頁面的property,並作出修改/資料傳遞
但是⋯⋯但是,沒有錯,有但是⋯⋯

在畫面切換之前該有的Label, Image⋯⋯etc
這些畫面上的元件其實都還沒生成
不論option怎麼解都沒辦法修改的
能傳遞資料的只有變數可以當成容器存取

所以我們得先在ShowViewController上宣告一個變數
我們現在要傳遞的是字串,簡單宣告一個放字串的變數就好
這樣在轉型後的controller就可以存取nameText這個容器

var nameText:String = “ ”

在Button觸發的執行序中,我們將觸發源轉型為UIButton宣告成常數
要觸發換頁之前將剛才宣告的nameText抓進來改變,再present新頁面
改變的內容就根據按鈕的標題改變,點哪個新頁面就顯示哪個名稱

let button = sender as? UIButton
if let controller = storyboard?.instantiateViewController(withIdentifier: “PhotoView”) as? ShowViewController {
controller.nameText = (button?.currentTitle)!
present(controller, animated: true, completion: nil)
}

上述內容已經初步將我們要傳遞的資料(button title)丟到新頁面了

既然已經拿到資料了,我們就來看ShowViewController要怎麼處理

@IBOutlet weak var myImageView: UIImageView!
@IBOutlet weak var nameLabel: UILabel!

Show Page有兩個物件會用來呈現新頁面的內容
要改變物件內容的時候必須確定該物件已經生成
所以改變內容的程序就寫在ViewDidLoad()底下

nameLabel.text = nameTextif nameText == “鬼宿” {
myImageView.image = imageLiteral(resourceName: “pic01”)
} else if nameText == “星宿” {
myImageView.image = imageLiteral(resourceName: “pic02”)
}

把上述程序寫進去就可以完成“依據資料內容改變顯示內容”
可以發現依據的源頭都是nameText這個變數
其內容在頁面切換之前就已經從SelectViewController獲取資料了
剩下就是如何運用資料的部分,我是用來挑選顯示的圖片

Demo畫面如下,不同按鈕show不同的圖
不需要多個view對應不同的觸發按鈕
左上Label也可根據來源顯示不同內容

DataTrans Demo

--

--