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

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

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

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

Swift

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

Q&A

解決済

2回答

1678閲覧

Userdefaultsを違うclassで使う方法

Ytan

総合スコア39

Xcode

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

Swift

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

0グッド

1クリップ

投稿2020/04/07 11:41

実現したいこと&疑問点

TableViewにてtextFieldにtodoを入れ値を保存して遷移した後遷移した後のclassにtextViewを設けて一言書きてそちらも保存したいのですが、classが変わった場合、同じkey値は使えずに保存内容もtextArray(cellを入れている配列)とtextViewは別で保存しないといけないと思うのですが、可能ですか?

発生しているエラー

cellをtap時に発生します。

Swift

1Thread 1: Exception: "Attempt to insert non-property list object <UITextView: 0x7fe59a84da00; frame = (27 476; 361 255); text = ''; clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x60000045cb10>; layer = <CALayer: 0x600000a7ffc0>; contentOffset: {0, 0}; contentSize: {361, 247}; adjustedContentInset: {0, 0, 0, 0}> for key Key"

該当コード

ViewController

1 2var textArray = [String]() 3 4override func viewWillAppear(_ animated: Bool) { 5 super.viewWillAppear(animated) 6 7 navigationController?.isNavigationBarHidden = true 8 9 //値の読み込み 10 if (UserDefaults.standard.stringArray(forKey: "todo") != nil){ 11 textArray = UserDefaults.standard.stringArray(forKey: "todo")! 12 13 } 14 15 tableView.reloadData() 16 17 } 18 19func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 20 21 let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 22 23 cell.selectionStyle = .none 24 cell.textLabel?.text = textArray[indexPath.row] 25 cell.imageView?.image = UIImage(named: "profile") 26 cell.textLabel?.textColor = .white 27 28 //値の保存 29 UserDefaults.standard.set(textArray, forKey: "todo") 30 31 return cell 32 33 } 34

NextViewController

1class NextViewController: UIViewController { 2 3 var todoString = String() 4 let userDefaults = UserDefaults.standard 5 6 @IBOutlet weak var textView: UITextView! 7 @IBOutlet weak var Todolabel: UILabel! 8 9 override func viewDidLoad() { 10 super.viewDidLoad() 11 12 // Do any additional setup after loading the view. 13 14 Todolabel.text = todoString 15 UserDefaults.standard.set(textView, forKey: "Key") 16 17 } 18 19 override func viewWillAppear(_ animated: Bool) { 20 super.viewWillAppear(animated) 21 22 navigationController?.isNavigationBarHidden = false 23 let val1 = UserDefaults.standard.object(forKey: "Key") 24 25 } 26

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

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

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

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

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

TsukubaDepot

2020/04/07 14:04

先日のご質問に、クラスを作ってそこでToDoのラベルの内容、およびToDoに対するコメントを記録し、違うビューに遷移しても利用できるためのヒントを書いていますが、それはご理解いただけたでしょうか。 また、UserDefautlsはどんなデータ型でも保存できるわけではなく、いわゆるプロパティリストと呼ばれている型以外は一工夫しないと保存できないこと、またその対策法も書いていますが、そちらもご理解いただけていますか。 https://teratail.com/questions/251610#reply-363530 今回起きている実行時エラーは、UITextView をUserDefaultsで保存しようとした際に出たエラーだと思います。エラーが出た場所は明記されていませんが、コードをみた限り UserDefaults.standard.set(textView, forKey: "Key") のところで発生した可能性が高いです。 このtextViewはプロパティリストとして挙げられているデータ型ではないため、保存するためには先日ご提示した回答の末尾にあるヒント(別回答で挙げたサンプルコード)を使って、保存するためのクラスを実装する必要があります。
TsukubaDepot

2020/04/07 14:07

また、UserDefaults に保存しなければいけないのは、textView (UITextViewのインスタンス)全てではなく、textView のプロパティである text だけで十分です。 いずれにしても、どの程度ご理解されているのか次第でコメントも変わりますので、私が先日つけたコメントを再度ご確認いただいて、どの程度理解されているのか教えていただければとおもいます(必要に応じて質問内容を修正するようにお願いします)。
Ytan

2020/04/08 01:37

クラスを作ってのLabelのtitleの保存は仕組みはわかるのですが、classを元々設けることによりそれが保存先として機能するということですか? また別記事のUserDefautlsはNSObject, NSCodingが自分的にはよく分からないのでメソッドやインスタンスの理解が少し難しいのですが、classの中と外でプロパティとインスタンスを分けることによって保存内容を分けることができるということですか? ちなみにエラーはAppDelegateの class AppDelegate: UIResponder, UIApplicationDelegateで起こります。
TsukubaDepot

2020/04/08 02:43

> クラスを作ってのLabelのtitleの保存は仕組みはわかるのですが、classを元々設けることによりそれが保存先として機能するということですか? クラス先がそのまま保存されるわけではありません。データの扱い方として「Todo名、詳細事項」の2つをセットにしたクラスを作った方が便利ですよ、という程度の話です。 Todo名の String型の配列、詳細事項のString型の配列それぞれを別のキー名でUserDefaultsに保存しても作れますが、今後他の要素もまとめて扱いたいとなると処理も煩雑になるので、この時点でクラスを一つつくり、ひとまとめにして保存しておいた方が見通しの良いプログラムになりますよ、という話です。 > また別記事のUserDefautlsはNSObject, NSCodingが自分的にはよく分からないのでメソッドやインスタンスの理解が少し難しいのですが、classの中と外でプロパティとインスタンスを分けることによって保存内容を分けることができるということですか? プロパティリストと呼ばれているもの以外の任意のクラスを保存するためには、そのクラスがNSObjectを継承し、NSCodingに準拠する必要があります。それは、たとえば元の質問でやっているようなtextViewを保存する場合でも同じです。 https://developer.apple.com/documentation/foundation/userdefaults > A default object must be a property list—that is, an instance of (or for collections, a combination > of instances of) NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. If you want to > store any other type of object, you should typically archive it to create an instance of NSData. カスタムクラスで定義したイニシャライザの一つは、クラスの初期値を設定するために必要となるイニシャライザです。他のイニシャライザとメソッド一つは、とりあえずそういうものが必要だ、という認識でいいとおもいます(当然、自分が扱うデータによって書き換えは必要ですが)。 しかし、カスタムクラスを作り、それを保存することについて、まだ理解が難しいということであれば、Todo名で一つ、Todoの詳細で一つと、別々のキーでString型の配列を保存する方法の方が良いのかもしれません(管理は厄介になりますが、新しく覚えることはほぼないはずです)。 繰り返しになりますが、textView 全体をUserDefaultsに保存するとなるとひと工夫必要ですし、そもそもその必要はありません。保存する必要があるのは、textView で入力された文字列だけです。なので、素直にその値だけを保存するように考えてみてはいかがでしょうか。 > ちなみにエラーはAppDelegateの class AppDelegate: UIResponder, UIApplicationDelegateで起こります。 遷移先の画面で textView を保存するようなサンプルを作ってみました。たしかに実行時エラーで落ちるのはAppDelegateの部分です。しかし、吐かれているエラーメッセージと追加した処理から考えると、ほぼ間違いなく textView をUserDefaults に保存している部分です。
Ytan

2020/04/10 06:59

ご返信ありがとうございます。ベストアンサーにしたいのですが回答に何か一言入れてもらえないでしょうか?
TsukubaDepot

2020/04/10 07:13

では、上記のコメントを回答として適切な形に修正して回答にします。 丁寧にご連絡いただきありがとうございます。
guest

回答2

0

ベストアンサー

クラス先がそのまま保存されるわけではありません。今後アプリを発展させることを考えると、データの扱い方として「Todo名、詳細事項」の2つをセットにしたクラスを作った方が便利です。

Todo名String型の配列、詳細事項のString型の配列それぞれを別のキー名でUserDefaultsに保存しても作れますが、今後他の要素もまとめて扱いたいとなると処理も煩雑になるので、この時点でクラスを一つつくり、ひとまとめにして保存しておいた方が見通しの良いプログラムになります。

また別記事のUserDefautlsはNSObject, NSCodingが自分的にはよく分からないのでメソッドやインスタンスの理解が少し難しいのですが、classの中と外でプロパティとインスタンスを分けることによって保存内容を分けることができるということですか?

プロパティリストと呼ばれているもの以外の任意のクラスを保存するためには、そのクラスがNSObjectを継承し、NSCodingに準拠する必要があります。それは、たとえば元の質問でやっているようなtextViewを保存する場合でも同じです。

https://developer.apple.com/documentation/foundation/userdefaults

A default object must be a property list—that is, an instance of (or for collections, a combination of instances of) NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any other type of object, you should typically archive it to create an instance of NSData.

ちなみに、カスタムクラス(正確にはプロパティリスト)以外のクラスをUserDefaultsに保存するためには、さらにひと工夫必要です。

具体的な例は過去の回答の後半に例がありますので、そちらも参考にしてみてください。

カスタムクラスで定義したイニシャライザの一つは、クラスの初期値を設定するために必要となるイニシャライザです。他のイニシャライザとメソッド一つは、とりあえずそういうものが必要だ、という認識でいいとおもいます(当然、自分が扱うデータによって書き換えは必要ですが)。

しかし、カスタムクラスを作り、それを保存することについて、まだ理解が難しいということであれば、Todo名で一つ、Todoの詳細で一つと、別々のキーでString型の配列を保存する方法の方が良いのかもしれません(管理は厄介になりますが、新しく覚えることはほぼないはずです)。

繰り返しになりますが、textView 全体をUserDefaultsに保存するとなるとひと工夫必要ですし、そもそもその必要はありません。保存する必要があるのは、textView で入力された文字列だけです。なので、素直にその値だけを保存するように考えてみてはいかがでしょうか。

投稿2020/04/10 07:12

TsukubaDepot

総合スコア5086

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

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

0

Keyさえあっていれば、別クラスというかViewでも読めますよ。
アプリケーション内で共通だと思います。

投稿2020/04/07 11:51

freemann

総合スコア264

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問