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

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

ただいまの
回答率

88.92%

SwiftのUserDefaultsのクラスとメソッドの使い方につきまして

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 328

pegy

score 156

(環境)
xcode:11.3
version 5.1.3

(参考文献)
「たった2日でマスターできるIPhoneアプリ開発集中講座 Xcode 11 Swift5 対応」
2020年1月20日 初版第二刷発行
著者: 藤 治仁・小林 加奈子・小林 由憲
発行人: 片柳 秀夫
編集人:三浦 聡
発行所:ソシム株式会社

基本的にswiftでの調べ方についてご質問させてください。

上記の書籍に基づき、例えば、下記のviewController.swiftにおいて初めてデータの永続化をuserDefaultsクラスを利用することができることを学びました。standardクラスのregister()メソッドので永続化したいデータを登録してinteger()メソッドで数値列として登録した永続データの値を取り出すことができるのか。。ふむふむ。というのが思考過程です。

//viewController.swift

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        // UserDefaultsのインスタンスを生成
        let settings = UserDefaults.standard
        // UserDefaultsに初期値を登録
        settings.register(defaults: [settingKey:10])
    }
//中略

        // UserDefaultsのインスタンスを生成
        let settings = UserDefaults.standard
        // 取得した秒数をtimerValueに渡す
        let timerValue = settings.integer(forKey: settingKey)


また、UserDefaultsのDefinitionを見る限り、それぞれのクラスやメソッドについて、以下の様な記載が確認できました。

    /**
     +standardUserDefaults returns a global instance of NSUserDefaults configured to search the current application's search list.
     */
    open class var standard: UserDefaults { get }
    /**
     -registerDefaults: adds the registrationDictionary to the last item in every search list. This means that after NSUserDefaults has looked for a value in every other valid location, it will look in registered defaults, making them useful as a "fallback" value. Registered defaults are never stored between runs of an application, and are visible only to the application that registers them.

     Default values from Defaults Configuration Files will automatically be registered.
     */


   /**
     -integerForKey: is equivalent to -objectForKey:, except that it converts the returned value to an NSInteger. If the value is an NSNumber, the result of -integerValue will be returned. If the value is an NSString, it will be converted to NSInteger if possible. If the value is a boolean, it will be converted to either 1 for YES or 0 for NO. If the value is absent or can't be converted to an integer, 0 will be returned.
     */
    open func integer(forKey defaultName: String) -> Int

一方で、UiPickerでユーザーが選択した数値列の値を改めて格納するコードで示されているのが下記の通りなのですが、上記から当然standardクラスのregister()メソッドを使うのかと思いきや、setValue()メソッドが使用されており、setValueUserDefaultsクラスに特に言及がなく手詰りという結果になってしまいました。つまり、どの様な場合にはregister()メソッドでどの様な場合にはsetValue()メソッドが識別することができないという状況です。

//SettingViewController.swift

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        // UserDefaultsの設定
        let settings = UserDefaults.standard
        settings.setValue(settingArray[row], forKey: settingKey)
        settings.synchronize()
    }

基本的な調べ方のアプローチをお尋ねしたいのですが、
① Definitionの構造は例えばUserDefaults で俯瞰してみると以下の様になっていました。この記載はつまり両クラスがどの様な関係にあることを言いたいのでしょうか。この点からdefinitionからは理解することができませんでした。特に{get}の意味するところが不明でした。

open class UserDefaults : NSObject {
   /**
     +standardUserDefaults returns a global instance of NSUserDefaults configured to search the current application's search list.
     */
 open class var standard: UserDefaults { get }
}

②また、①の状況だからこそなのですが、 下記の様なdefitionであるとUserDefaultsのメソッドとしてregister()がある様に見えてしまいます。実際にはUserDefaults.standard.register()なのでstandardクラスとregister()が並列な関係の様に見えて不思議です。ここら辺のDefinitionの見方を特に知りたいです。

open class UserDefaults : NSObject {
 open class var standard: UserDefaults { get }
 open func register(defaults registrationDictionary: [String : Any])
}


③最後に唯一具体的なことになってしまうのですが、なぜsetValue()UserDefaultsクラスの説明の中に出てこないのでしょうか、、①②がわかれば自ずとわかるかもしれませんが。

また、ここら辺の定義やマニュアルの調べ方についてSwiftでわかりやすい解説サイトとかがあればそれをご教示いただくだけでもとても助かります。

長文で申し訳ございませんが
よろしくお願い申し上げます。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • TsukubaDepot

    2020/04/05 21:22

    質問内容が「Swiftの基本的なDefinitionの調べ方」というよりも、UserDefaultsのメソッド、およびシングルトンと呼ばれている手法のことに関する内容なので(おそらく...)、タイトルを変更された方がいいかもしれません。

    キャンセル

  • pegy

    2020/04/05 21:34

    コメント有難うございます。
    シングルトンについては、今見始めており、詳細はわかりませんが、タイトルについては承知を致しました。修正致します。

    キャンセル

回答 1

checkベストアンサー

+1

質問の意図を私が理解できているかわかりませんが、


UserDefaultsというのは、なんとなく「データを永続化してくれるクラス」という理解で良いと思いますが、
実は
・アプリ単体で使う場合
・複数のアプリ間で共有する場合
の2パターン(もっとある?)が存在します。

前者で取り扱う場合は、とりあえずUserDefaults.standardを使うんだな程度の認識でいいです。

{ get }は「プロパティかつ取得のみできる(setはできない)」事が定義されている
ぐらいの認識でとりあえずはいいです。


UserDefaultsはクラス、
registerはUserDefaultsクラスのメンバー関数です。
通常のメンバー関数はクラスのインスタンス経由で呼び出す必要があります。

インスタンスという言葉は今後もちょいちょい出てくるので覚えておいた方が良いですが、
「クラス」がプラモデルの設計図だとしたら、「インスタンス」はその設計図から作成された実際のプラモデルそのものを指します。

要は設計図だけではなんもできないので(※下記のとおり例外あり)、そこから作成されたオブジェクトを用いてメンバ関数などにアクセスする必要があります。

じゃあ「UserDefaults.standard」はなんなのよ?となりますが、
これはクラスプロパティ(※用語の自信無し)と呼ばれているもので、
インスタンスが無くても実行できるようになっているものです。
(通常の変数はvarですが、クラス変数はclass varになっています。)
設計図だけで直接アクセスできるプロパティととらえてもらえればいいです。

まとめると
UserDefaultsはクラス、
UserDefaults.standardはクラスプロパティを使ってUserDefaultsのインスタンスを取得(実装がどうなってるか知りませんが、シングルトン的なやつです)
UserDefaults.standard.register(...)でようやく、そのインスタンス経由でメンバ関数が呼べる感じです。


基本的に困ったら一次ソースを見ましょう。
https://developer.apple.com/documentation/foundation/userdefaults
set系はSwiftではset(_:forKey:)のような構文になっています。

解説サイトはあったかなあ・・・。
適当にググって補完してもらうのがよいかなとは思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/04/06 20:26

    takabosoft様
    ありがとうございます、まだまだ初心者なので逆に専門的な細かい知識というよりも、まずはイメージというところでご案内いただいたことがとても助かります。重要なとっかかりになりました!

    ②について、いろいろな記事や参考書でもピントこなかったことが多かったのですが、「インスタンス」を直接生成せずに、クラスプロパティを経由してメンバ関数に直接アクセスできるという構造のご説明が直感的に非常に分かり易かったです。

    なんとなく"そこから作成されたオブジェクトを用いてメンバ関数などにアクセス"というご説明で気になった点があります。少なくともSwiftの世界では設計図であるクラスから生み出される実態は「インスタンス」と捉えているので、これをたまに「オブジェクト」と言い換える場合もあると捉えていますが、厳密な表現で使い分けていらっしゃれば申し訳ございません。

    最後の③について、
    "set系はSwiftではset(_:forKey:)のような構文になっています。"というご説明とsetValueの関係についてイメージがわかなかったのですが、少し調べたところsetValue は NSUserDefaults のメソッドではなく、親クラスのNSObjectのメソッドである旨の記事を見つけることができました。

    おそらくNSUserDefaults クラスはNsObjectlくらすを承継している(ほとんど全てのクラスがその様な関係にあると今は理解していますが)、NSUserDefaults.standard.setValue的な使い方ができるし、NSUserDefaultクラス内のDefiniationを探してもそのメソッドの説明を見つけることができなかったと理解いたしました。
    慣れるまでは一次ソースでメソッドなどを見つけることができばければ、ググって他の親クラスのメソッドではないかなど、当たりをつけていこうと思います。

    ご協力をいただき、ありがとうございました!
    大きな感謝を申し上げます。

    キャンセル

  • 2020/04/07 16:07

    オブジェクトという言葉はたぶん言語などによって意味が変わってきそうなので、すみませんが私の方でしっかりとした説明はできそうにありません(teratailの過去の質問にもいくつかありましたので興味があれば検索してみは)。

    私の回答内の「オブジェクト」は「インスタンス」に置き換えて読んでもらって差し支え有りません。

    ③のsetの件ですが、ちょっと私も方で勘違いがありました。
    setValueはおかしいですね。
    もし書籍がsetValue(_:forKey:)を使っているのであれば、書籍側のミスの可能性がありますので、正誤表などありましたら、確認してみてください。

    Swiftにおいては、UserDefaultsへデータを保存するのはset(_:forKey:)系を使います。

    ついでにいうと、
    settings.synchronize()
    のsynchronize()関数は現在は使用しないでくださいというお達しが出ています。

    参考:
    https://developer.apple.com/documentation/foundation/userdefaults/1414005-synchronize
    > this method is unnecessary and shouldn't be used.

    キャンセル

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

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る