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

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

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

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

Swift

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

Q&A

解決済

1回答

1149閲覧

UserDefaults保存できない

KYSFY

総合スコア3

Xcode

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

Swift

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

0グッド

0クリップ

投稿2020/08/24 19:55

編集2020/08/25 06:51

<やりたい事>

UILabelの「表示・非表示(isHidden)の値」を、 UserDefaultsで保存したい。

下記のクラスに対象のUILabelがあります。

SWIFT

1import UIKit 2class Container_ViewController:UIViewController { 3 4 let clear = ClearMark()  //★追記修正しました。 5  let nsobject = NSObject() 6 7 @IBOutlet weak var clearMark1: UILabel! //このラベルの表示or非表示の値を保存したい 8 9 override func viewDidLoad() { 10 super.viewDidLoad() 11 12 clearMark1.isHidden = true //最初は非表示の設定 13 14   UserDefaults.standard.bool(forKey: "c1") //後に保存される値を取得(する予定) 15 } 16 17 18 19 func segueToNextViewController() { 20 self.performSegue(withIdentifier: "next", sender: self.clear) 21} 22 23 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 24 if segue.identifier == "next" { 25 let nextViewController = segue.destination as! NextViewController1 26 nextViewController.clear = self.clear 27 28 } 29 } 30 }

別画面(下記クラス)で、UILabelの表示・非表示が変更され、その値を保存したい。

SWIFT

1import UIKit 2class NextViewController1: UIViewController { 3 4  weak var clear: ClearMark! //★追記修正しました。 5 weak var vc: Container_ViewController! 6 let nsobject = NSObject() 7 8    override func viewDidLoad() { 9    super.viewDidLoad() 10 } 11 12 13 14//以下コード内容 ★追記修正しました。 15 16 @IBAction func okButton(_ sender: Any){  //このボタンを押したら非表示→表示に切替える 17 18 if (sender as AnyObject).tag == 1{ 19 20 clear.clear1() 21      image01b.isHidden = true  22 23 UserDefaults.standard.set(vc.clearMark1.isHidden, forKey: "c1") 24 // 1の保存がうまくいき次第、以下の2〜20にforKeyを変えて展開予定です。 25 26 27 28 }else if (sender as AnyObject).tag == 2{ 29 clear.clear2() 30 image02b.isHidden = true 31 32 } 33     //以下3〜20まで同様。 34 35 36 37 38 @IBAction func reset(_ sender: Any) {  //このボタンを押したら表示→非表示に切替える 39 40   if (sender as AnyObject).tag == 101{ 41 clear.notClear1() 42 image01b.isHidden = false 43 44     UserDefaults.standard.set(vc.clearMark1.isHidden, forKey: "c1") 45 // 1の保存がうまくいき次第、以下の2〜20にforKeyを変えて展開予定です。 46 47 48 }else if (sender as AnyObject).tag == 102{ 49 clear.notClear2() 50 image02b.isHidden = false 51 }  52    //以下103〜120まで同様。 53 54 } 55}

一応ビルドはできるのですが、実行する(ボタンを押す)と、

Swift

1 2 UserDefaults.standard.set(vc.clearMark.isHidden, forKey: "c1")  3//このコード部分で以下のエラーメッセージになります 4---------------------------------------------------------------------- 5Thread 1: Fatal error: 6Unexpectedly found nil while implicitly unwrapping an Optional value 7----------------------------------------------------------------------

ネットで色々調べてるのですが解決できず、

保存する値が「UI部品のBool型」という事で、何かしらの手を加えないといけない?
と、漠然とした事しか分からず、

let nsobject = NSObject() 

の部分は調べてる中で後から追加したコードになります。

どなたか解決方法をご教授頂けませんでしょうか。
よろしくお願い致します。

//★以下追記修正しました。

実際には20個のViewControllerをclass NextViewController1で共有しており、

画面毎の20個のボタンがある為、下記のクラスも作成しており、ボタンの表示・非表示の関数をまとめた形になってます。

Swift

1import UIKit 2 3class ClearMark: NSObject { 4 5 weak var vc: Container_ViewController! 6 7 func clear1() { 8 vc.clearMark1.isHidden = false 9 } 10 func clear2() { 11 vc.clearMark2.isHidden = false 12 } 13 func clear3() { 14 vc.clearMark3.isHidden = false 15 } 16 func clear4() { 17 vc.clearMark4.isHidden = false 18 } 19 func clear5() { 20 vc.clearMark5.isHidden = false 21 } 22 func clear6() { 23 vc.clearMark6.isHidden = false 24 } 25 func clear7() { 26 vc.clearMark7.isHidden = false 27 } 28 func clear8() { 29 vc.clearMark8.isHidden = false 30 } 31 func clear9() { 32 vc.clearMark9.isHidden = false 33 } 34 func clear10() { 35 vc.clearMark10.isHidden = false 36 } 37 func clear11() { 38 vc.clearMark11.isHidden = false 39 } 40 func clear12() { 41 vc.clearMark12.isHidden = false 42 } 43 func clear13() { 44 vc.clearMark13.isHidden = false 45 } 46 func clear14() { 47 vc.clearMark14.isHidden = false 48 } 49 func clear15() { 50 vc.clearMark15.isHidden = false 51 } 52 func clear16() { 53 vc.clearMark16.isHidden = false 54 } 55 func clear17() { 56 vc.clearMark17.isHidden = false 57 } 58 func clear18() { 59 vc.clearMark18.isHidden = false 60 } 61 func clear19() { 62 vc.clearMark19.isHidden = false 63 } 64 func clear20() { 65 vc.clearMark20.isHidden = false 66 } 67 68 69 70 func notClear1(){ 71 vc.clearMark1.isHidden = true 72 } 73 func notClear2(){ 74 vc.clearMark2.isHidden = true 75 } 76 func notClear3(){ 77 vc.clearMark3.isHidden = true 78 } 79 func notClear4(){ 80 vc.clearMark4.isHidden = true 81 } 82 func notClear5(){ 83 vc.clearMark5.isHidden = true 84 } 85 func notClear6(){ 86 vc.clearMark6.isHidden = true 87 } 88 func notClear7(){ 89 vc.clearMark7.isHidden = true 90 } 91 func notClear8(){ 92 vc.clearMark8.isHidden = true 93 } 94 func notClear9(){ 95 vc.clearMark9.isHidden = true 96 } 97 func notClear10(){ 98 vc.clearMark10.isHidden = true 99 } 100 func notClear11(){ 101 vc.clearMark11.isHidden = true 102 } 103 func notClear12(){ 104 vc.clearMark12.isHidden = true 105 } 106 func notClear13(){ 107 vc.clearMark13.isHidden = true 108 } 109 func notClear14(){ 110 vc.clearMark14.isHidden = true 111 } 112 func notClear15(){ 113 vc.clearMark15.isHidden = true 114 } 115 func notClear16(){ 116 vc.clearMark16.isHidden = true 117 } 118 func notClear17(){ 119 vc.clearMark17.isHidden = true 120 } 121 func notClear18(){ 122 vc.clearMark18.isHidden = true 123 } 124 func notClear19(){ 125 vc.clearMark19.isHidden = true 126 } 127 func notClear20(){ 128 vc.clearMark20.isHidden = true 129 } 130}

先の2つのクラスについても追記修正してます。
(//★追記修正しました。の部分)

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

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

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

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

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

TsukubaDepot

2020/08/24 21:33

そもそもご提示のコードはコンパイルも通らないように思えます。 class Container_ViewController には nextViewController.clear = self.clear という部分がありますが、nextViewController には clear というプロパティ(変数)はありませんし、Container_ViewController にも clear (self.clear) という変数が存在しません(よく見たら performSegue の sender にも self.clear を指定していますが、それもありません)。 また、class NextViewController1 では vc.clearMark.isHidden = false  //このボタンが押されたら、「表示」にする。 を実行していますが、そもそも weak var vc: Container_ViewController! とオプショナル型で宣言したあと、具体的な値を入れていませんから、まず上記の行で実行時エラーができるのではないでしょうか(UserDefaultの行まで到達しない)。 もしかしたらコードを簡素化して掲載されているのかもしれませんが、本質的な原因がわからなくなりますので、辻褄が合うように編集していただければと思います。
KYSFY

2020/08/24 21:51

ご連絡ありがとうございます。 仰る通り、質問内容に関係ない部分は削除し、簡素化した状態で記載した為、 矛盾が生じたかもしれません。申し訳ありません。 後ほど、追記・修正した形で更新させて頂きますので、ご確認頂けますと幸いです。 実際には、下記のクラスも作成しており、ボタンの表示・非表示の関数をまとめた形になってます。
KYSFY

2020/08/24 22:49

↑ 「実際には・・・」の部分、誤記載です。 「//★以下追記修正しました。」の部分 ご確認お願い致します。
TsukubaDepot

2020/08/25 05:50

NextViewController1 にある weak var vc: Container_ViewController! ですが、オプショナル型で宣言されていますが、具体的な値はどの段階で入る予定なのでしょうか。 遷移前には値を入れていませんので、現在ご提示いただいているコードのままだと vc == nil となってしまいます。 従って、 UserDefaults.standard.set(vc.clearMark1.isHidden, forKey: "c1") ではエラーが出て当然かと思いますが、このあたりはいかがなのでしょうか。
TsukubaDepot

2020/08/25 05:55

そもそも、vc, つまり Container_ViewController には clearMark1 というプロパティがないように見えますのでコンパイルエラーになるとおもいますが、それも合わせてご回答いただければと思います。
KYSFY

2020/08/25 06:48

Q. 「オプショナル型で宣言されていますが、具体的な値はどの段階で入る予定なのでしょうか。」 A. 表示・非表示を切り替えて値を保存したいUILabelが Container_ViewController にある為、 weak var vc: Container_ViewController! と宣言する必要があるかと思ってたのですが、不必要だったでしょうか。 vc.clearMark1.isHidden (ここなどで使用する為、宣言必要かと思ってました) Q. 「そもそも、vc, つまり Container_ViewController には clearMark1 というプロパティがないように見えます」 A. 実際のコードには「clearMark」が1〜20ある為、質問用にコードを簡素化した際に、 番号を消してまってました。 ややこしくしてすみません。コードを修正しました。 @IBOutlet weak var clearMark: UILabel!  →  @IBOutlet weak var clearMark1: UILabel! に訂正してます。  諸々、不備があって申し訳ありませんが、実際のコードではコンパイルエラーは出てません。 あくまで、実行時(ボタンを押した時)に、 ------------------------------------------------------------------------------------------------ Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value ------------------------------------------------------------------------------------------------ このエラーで止まってしまう状況です。
guest

回答1

0

ベストアンサー

コメントにあるご質問ですが、

表示・非表示を切り替えて値を保存したいUILabelが Container_ViewController にある為、

weak var vc: Container_ViewController!
と宣言する必要があるかと思ってたのですが、不必要だったでしょうか。

不必要ではないのですが、記述しただけでは目的とするインスタンスは代入されません(この場合はオプショナル型として宣言されているので nil が代入されます)。

代入されない、つまり値が nil のまま

Swift

1     UserDefaults.standard.set(vc.clearMark1.isHidden, forKey: "c1")

の行で vc にアクセスしていますので、実行時エラーが生じています。

なので、遷移前に vc に対してインスタンスを代入する必要があります。

たとえば、下記のような感じです。

Swift

1 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 2 if segue.identifier == "next" { 3 let nextViewController = segue.destination as! NextViewController1 4 // Container_ViewController (つまり self)のインスタンスを代入する 5 nextViewController.vc = self 6 } 7 }

ご質問のコードを最小限のコードで動くようにしたのが下記のようなコードになりますので、合わせてご参照いただければと思います。

Swift

1import UIKit 2class Container_ViewController:UIViewController { 3 @IBOutlet weak var clearMark1: UILabel! 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 8 // UserDefaults に保存された状態に応じてラベルの表示/非表示を切り替える 9 // 過去に一度も保存されていない場合、つまりキーが存在しない場合には false となる 10 clearMark1.isHidden = UserDefaults.standard.bool(forKey: "c1") 11 } 12 13 // この関数はどのタイミングで呼び出されているか不明なのでコメントアウト 14// func segueToNextViewController() { 15// self.performSegue(withIdentifier: "next", sender: self.clear) 16// } 17 18 // ボタンを押したら Segue を実行する 19 @IBAction func nextButton(_ sender: Any) { 20 performSegue(withIdentifier: "next", sender: nil) 21 } 22 23 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 24 if segue.identifier == "next" { 25 let nextViewController = segue.destination as! NextViewController1 26 // Container_ViewController (つまり self)のインスタンスを代入する 27 nextViewController.vc = self 28 } 29 } 30}

Swift

1import UIKit 2class NextViewController1: UIViewController { 3 weak var vc: Container_ViewController! 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 } 8 9 @IBAction func okButton(_ sender: Any) { 10 if (sender as! UIButton).tag == 1 { 11 // ClearMark.vc に値が設定されていないので、本来は下記の行で実行時エラーになる 12 // clear.clear1() 13 vc.clearMark1.isHidden = false 14 15 UserDefaults.standard.set(vc.clearMark1.isHidden, forKey: "c1") 16 } 17 } 18 19 @IBAction func reset(_ sender: Any) { 20 if (sender as! UIButton).tag == 101 { 21 // ClearMark.vc に値が設定されていないので、本来は下記の行で実行字エラーになる 22 //clear.notClear1() 23 vc.clearMark1.isHidden = true 24 25 UserDefaults.standard.set(vc.clearMark1.isHidden, forKey: "c1") 26 } 27 } 28}

投稿2020/08/25 07:45

TsukubaDepot

総合スコア5086

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

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

KYSFY

2020/08/25 14:14

最初にご提示頂いた、 nextViewController.vc = self を追加しただけで問題解決しました。 本当にありがとうございました! 「最小限のコードで動くようにした」参考コードについても、じっくり内容を理解して勉強させて頂きたいと思います。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問