質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

2回答

497閲覧

swift デリゲートでlabel.textにアクセスできない

mogiruri

総合スコア37

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2018/10/22 23:10

前回の質問と少し被ってしまうのですが、改善ができなかったので改めて投稿いたします。

デリゲートををして、別クラスのlabel.textにアクセスして値を送りたいのですがoptional nilだと言われ代入できません。
プロトコルを作成しメソッドにはアクセスできましたが、labelにアクセスできないのはなぜでしょうか。
改善策をよろしくお願いいたします。

アクセスされる側

swift

1import UIKit 2 3 4class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, VCDelegate { 5 6 7 @IBOutlet weak var layerView: UIView! 8 @IBOutlet weak var timerLabel: UILabel! // これに代入したい。最下部にメソッドあり 9 @IBOutlet weak var startBtn: CustomButton! 10 @IBOutlet weak var stopBtn: CustomButton! 11 @IBOutlet weak var finishBtn: CustomButton! 12 13 var totalTime = 0 14 15 var timer = Timer() 16 var isTimerRunning = false 17 var resumeTapped = false 18 var addLap: Bool = false 19 20 @IBAction func startBtn(_ sender: Any) { 21 22 if isTimerRunning == false { 23 runTimer() 24 self.startBtn.isEnabled = false 25 stopBtn.isEnabled = true 26 } 27 28 } 29 30 @IBAction func stopBtn(_ sender: Any) { 31 32 if resumeTapped == false { 33 timer.invalidate() 34 self.resumeTapped = true 35 self.stopBtn.setTitle("Resume", for: .normal) 36 } 37 38 } 39 40 @IBAction func finishBtn(_ sender: Any) { 41 42 alertShow() 43 44 45 } 46 47 48 49 @IBAction func settingBtn(_ sender: Any) { 50 51 let storyboard: UIStoryboard = self.storyboard! 52 let set = storyboard.instantiateViewController(withIdentifier: "settingVC") 53 54      // これが足りないのかと思い足してみましたが、delegeteがないと言われます 55// set.delegate = self 56 self.present(set, animated: true, completion: nil) 57 58 } 59 60 61 62 override func viewDidLoad() { 63 super.viewDidLoad() 64 65 layerView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5) 66 67 } 68 69} 70 71 72 73extension ViewController { 74 75 76 77 func timeString(time: TimeInterval) -> String{ 78 let hour = Int(time) / 3600 79 let minute = Int(time) / 60 % 60 80 let second = Int(time) % 60 81 print("(hour) a") 82 return String(format:"%02i:%02i:%02i", hour, minute, second) 83 } 84 85 86 87 @objc func updateTimer() { 88 if totalTime < 1 { 89 timer.invalidate() 90 }else{ 91 totalTime -= 1 92 timerLabel.text = timeString(time: TimeInterval(totalTime)) 93 } 94 } 95 96 97 98 func runTimer() { 99 timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true) 100 isTimerRunning = true 101 stopBtn.isEnabled = true 102 } 103 104 105 106 func alertShow(){ 107 108 let alert: UIAlertController = UIAlertController(title: "Confirmation", message: "Have you finished?", preferredStyle: UIAlertController.Style.alert) 109 110 let saveAction: UIAlertAction = UIAlertAction(title: "Save Record", style: UIAlertAction.Style.default) { (UIAlertAction) in 111 112 // save process 113 114 } 115 116 let unsaveAction: UIAlertAction = UIAlertAction(title: "Unsave Record", style: UIAlertAction.Style.destructive) { (UIAlertAction) in 117 118 // unsave process 119 120 } 121 122 let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel) { (UIAlertAction) in 123 124 // cancel process 125 126 } 127 128 alert.addAction(saveAction) 129 alert.addAction(unsaveAction) 130 alert.addAction(cancelAction) 131 132 self.present(alert, animated: true, completion: nil) 133 134 } 135 136 137 func setTime(_ time: String){ 138 print("success (time)") 139     // ここに代入したいがnilだと言われる 140 timerLabel.text = time 141 142 } 143} 144 145




アクセスする側

swift

1import UIKit 2 3var records = ["test", "tst"] 4 5// プロトコル 6protocol VCDelegate { 7 func timeString(time: TimeInterval) -> String 8 func setTime(_ time: String) 9} 10 11 12class settingVC: UIViewController, UITableViewDelegate, UITableViewDataSource { 13 14 var delegate: VCDelegate? 15 16 @IBOutlet weak var settingView: DesignableView! 17 @IBOutlet weak var tableView: UITableView! 18 @IBOutlet weak var hField: UITextField! 19 @IBOutlet weak var mField: UITextField! 20 @IBOutlet weak var sField: UITextField! 21 22 var hours = 0 23 var minutes = 0 24 var seconds = 0 25 var totalTime = 0 26 27 28 29 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 30 return records.count 31 } 32 33 34 35 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 36 let cell = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "cell") 37 cell.textLabel?.text = records[indexPath.row] 38 cell.backgroundColor = UIColor.clear 39 cell.textLabel?.textColor = UIColor.white 40 41 return cell 42 } 43 44 45 46 @IBAction func cancelBtn(_ sender: Any) { 47 self.dismiss(animated: true, completion: nil) 48 } 49 50 51 // ここで値を送り込みたい 52 @IBAction func setBtn(_ sender: Any) { 53 54 if hField.text != "" && mField.text != "" && sField.text != "" { 55 56 hours = Int(hField.text!)! * 3600 57 minutes = Int(mField.text!)! * 60 58 seconds = Int(sField.text!)! 59 totalTime = hours + minutes + seconds 60 61 var delTime = delegate?.timeString(time: TimeInterval(totalTime)) 62 delegate?.setTime(delTime!) 63 64 65 self.dismiss(animated: true, completion: nil) 66 } 67 68 } 69 70 71 72 override func viewDidLoad() { 73 74 super.viewDidLoad() 75 tableView.backgroundColor = UIColor.clear 76 settingView.backgroundColor = UIColor(white: 0.7, alpha: 0.8) 77 78 // デリゲートします宣言?? 79 let vc = ViewController() 80 self.delegate = vc 81 82 } 83 84} 85

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

UI部品を直接アクセスするのではなく、設定された値を介して受け渡しをします。
画面遷移でsegueを使う場合には大抵prepareメソッドで受け渡します。
その他、UserDefaultsやAppDelegate経由などにする場合もあります。

delegateを使う場合には、なんらかのタイミングでdelegateに指定するインスタンスを
設定する必要がありますし、その様に実装する必要があります。

投稿2018/10/23 02:49

t_obara

総合スコア5488

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mogiruri

2018/10/23 04:44

回答ありがとうございます。AppDelegateを使用するやり方はどこかがでみたような気がします。デリゲートの理解がまだ深くないので理解しないといけませんね。問題自体は解決していませんが、まだ調べたりななさそうなところをあさってみます。
t_obara

2018/10/23 04:55

UserDefaultsやAppDelegate経由は、ちょっとしたグローバル変数に近い概念なので、利用するには注意した方が良いです。 画面遷移で値を受け渡すサンプルはそこいらに転がっているので、ググれば結構出てきます。
mogiruri

2018/10/23 05:20

ありがとうございます。後ほどその方向で探ってみます。
mogiruri

2018/11/05 23:33

大変遅くなりましたがいろいろ試してみた結果、userdefaultsに保存し、dismissで親ファイルに戻ると同時にset func を叩くようにしてセットできました。。 はじめ、userdefaltsでもうまくいかなかったのですが、原因はインスタンスを新規に作成し vc.setValue() としていたのが問題でした。この時点では、別クラスにアクセスするためにインスタンス作成→UIと繋がっているクラスとは別物のインスタンス という概念がなかったの なぜtimerLable.text がnilなんだ?という疑問がずっと解決できませんでした。 UIと接続されている”そのまま呼び出し元のファイル”を参照するためには presentingViewController を使うというのを見つけまして、それで繋ぐことで解決できました。
guest

0

Swiftはしばらく書いていないので勘違いだったらすみません。
以下のコードは新しいViewControllerオブジェクトを作成して、デリゲートに渡していますがこの部分が意図した動作にならない原因だと思います。
新しく作成したオブジェクトのtimerLabelは、UI側と関連付けされていないからnilですよね?

swift

1// デリゲートします宣言?? 2let vc = ViewController() 3self.delegate = vc

投稿2018/10/23 00:05

YasuhiroMiyake

総合スコア1336

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mogiruri

2018/10/23 00:53

なるほど、また新たにvcが出来てしまったから中身はカラということですね。 これはどうしたらアクセスできるのでしょうか?
YasuhiroMiyake

2018/10/23 02:34

どのオブジェクトにデリゲート経由でアクセスさせたいかが、自身でイメージ出来ていますでしょうか。 まずはビューの部分、ソース部分を図に書いて、イメージをはっきりさせたほうが良いような気がします。 現状のコードでは新しいオブジェクトに対して、デリゲート経由でアクセスしているので、それを図に書いてイメージと異なっている部分を確認して下さい。 分かってしまえば、それほど難しいことではありませんがココが最初に引っかかりやすいところなので、もう少しだけデリゲートやビューとソースのイメージをはっきりさせたほうが今後のためにも良いと思います。
mogiruri

2018/10/23 04:41

ご回答ありがとうございます。そうですね、基本的な部分がまだ完全に理解できていないと思います。 プロトコルなどを用いると、それが橋になって向こうのクラスに渡っていけるというような理解でしたがまだ情報が足りていないよです。もう少し情報を集めてみます。
YasuhiroMiyake

2018/10/23 07:16

そのイメージで問題ないのですが、橋をかける先が間違っているのだと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問