いきなり回答にいきたいところですがいくつか事前知識が必要になるのでその説明から。
スコープ
スコープ(scope)は日本語では「視野」だとか「範囲」だとか訳されます。プログラミング上のスコープとなると参照できる範囲、という感じですかね。上記のコードではselectedCurrencyPair
はスコープ外ですね。平たくいうとResultViewController
からはselectedCurrencyPair
が見えない、参照できないんですね。なぜかというとselectedCurrencyPair
が関数内にあるからです。言うよりも見た方が早い気がするので例書いてみます。(犬嫌いだったらすいません)下記のカタカナは犬の名前です。
swift
1let rei = 0
2
3func kansuu() {
4 let ichi = 1
5}
6
7print(rei) // 0
8print(ichi) // エラー
こんな感じだったり、
swift
1class Dogs {
2 let goldenRetriever = "ゴールデンレトリバー"
3 private let poodle = "プードル"
4
5 func currentDog() -> String {
6 let Schnauzer = "シュナウザー"
7 return Schnauzer
8 }
9
10 init() {
11 print(goldenRetriever) // ゴールデンレトリバー
12 print(poodle) //プードル
13 print(Schnauzer) //エラー
14 print(currentDog()) //シュナウザー
15 }
16}
17
18class Human {
19 init() {
20 print(goldenRetriever) //エラー
21 let dogs = Dogs()
22 print(dogs.goldenRetriever) //ゴールデンレトリバー
23 print(dogs.poodle) //エラー
24 print(dogs.Schnauzer) //エラー
25 print(dogs.currentDog()) //シュナウザー
26 }
27}
28
29Human()
30
DogsとHumanのinit()内を見比べてみてください。また上記のエラーが出てるのと同じようなものがありませんか?その同じようなものというのは定数Schnauzerです。Schnauzerは関数内で宣言されている定数です。こいつも同じようにスコープ外なのでエラーが出ちゃいます。関数内の変数や定数を呼び出したいならばその変数や定数を返り値にしてあげましょう。
メンバ
エラーを見てみると
Value of type 'SelectViewController' has no member 'selectedCurrencyPair'
とあります。これはSelectViewController
はメンバselectedCurrencyPair
を持っていないよというエラーです。メンバというのはClass内に書かれた定数や変数のことを指します。関数内の定数や変数は指しません。なので質問内容にあるSelectViewController
のメンバはcurrencyPairPicker
とcurrencyPair
の二つですね。スコープの欄に書いた通りselectedCurrencyPair
はスコープ外にあるのでメンバではありません。
インスタンス
swift
1var test = SelectViewController()
のようにResultViewController
でSelectViewController
のインスタンスを新しく生成しています。がしかしSelectViewController
のインスタンスはSelectViewController
内のviewDidLoad()
が呼ばれているならすでに存在しているんですね。なのでインスタンスを新たに生成する必要はありません。既存のSelectViewController
のインスタンスにアクセスしたい場合は別の方法を取る必要があります。
prepareForSegue
とあるviewControllerから別のviewControllerへ画面遷移した際に値を渡したい、ということはよくあることですが(今回の質問もそうですね)、そんな時はよくprepareForSegue
という関数を使います。この関数は二つのviewContollerを出発地点、目的地点と捉えると出発地点にある値を目的地点に運んでくれる関数です。画面遷移の際に呼ばれます。なので質問の回答をするにはこの関数をoverrideして使っていきます。
プラスα
またResultsViewControllerクラスの「var test = SelectController()」を省略した記述の仕
方はありますでしょうか?
省略という形ではありません。ただ、SelectViewController
と書きたい場合、"selvco"と入力すれば予測変換にSelectViewControllerが(多分)一番上に出て来るでしょうからそのように書けば多少楽ができます。
回答例
一例です。
swift
1
2import UIKit
3
4class ViewController: UIViewController {
5
6 @IBOutlet var pickerView: UIPickerView!
7
8 let character = ["あ", "い", "う", "え", "お"]
9
10 override func viewDidLoad() {
11 super.viewDidLoad()
12 }
13
14 override func didReceiveMemoryWarning() {
15 super.didReceiveMemoryWarning()
16 }
17
18 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
19 //画面遷移時に呼ばれます。ここでは直接Labelのtextに値を渡すのではなく
20 //DestinationViewControllerのメンバに値を渡します。
21 //ここでpickerViewで選択したrowを渡したほうが変な挙動になりにくいという私見があるので
22 //こちらを採用しています。
23 let selectedRow = pickerView.selectedRow(inComponent: 0)
24
25 if let destination = segue.destination as? DestinationViewController {
26 destination.labelText = character[selectedRow]
27 } else {
28 fatalError()
29 }
30
31 }
32
33}
34
35//今回はextensionに書いていますがViewControllerのclass内に書いても構いません。
36extension ViewController: UIPickerViewDataSource, UIPickerViewDelegate {
37 func numberOfComponents(in pickerView: UIPickerView) -> Int {
38 return 1
39 }
40
41 func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
42 return character.count
43 }
44
45 func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
46 return character[row]
47 }
48}
49
50class DestinationViewController: UIViewController {
51
52 var labelText = "" //ここで値を受け取ります
53 @IBOutlet var destinationLabel: UILabel!
54
55 override func viewDidLoad() {
56 super.viewDidLoad()
57 }
58
59 override func viewWillAppear(_ animated: Bool) {
60 //Labelに書き込むならviewWillAppearなんかで行うといい具合かと
61 super.viewWillAppear()
62 destinationLabel.text = labelText
63 }
64
65 override func didReceiveMemoryWarning() {
66 super.didReceiveMemoryWarning()
67 }
68
69}
70
とまあだいたいこんな感じです。