ローカルデータをSwiftアプリに保存する方法は?


148

私は現在、Swiftで開発されたiOSアプリを開発しています。ユーザーが作成したコンテンツをデバイスに保存する必要がありますが、ユーザーのコンテンツをデバイスに保存/受信する簡単で迅速な方法が見つからないようです。

誰かがローカルストレージを保存してアクセスする方法を説明できますか?

アイデアは、ユーザーがアクションを実行したときにデータを保存し、アプリの起動時にそれを受け取ることです。


どういたしまして、どのようなデータを保存していますか?あなたが探しているものの例を示すコードを提供できますか?ありがとう。
Wez、2015

1
保存する必要のあるデータは、基本的には文字列データです。それで、それを本当にシンプルに保つために、ユーザーがアプリを再起動したときに受け取ることができる2つのString値を保存する必要があります。
Nicklas Ridewing、2015

2
NSUserDefaultsを使用できます。これが、コーディングに
a

回答:


197

2つの文字列を格納するだけの場合の最も簡単な解決策はNSUserDefaults、Swift 3ではこのクラスの名前がjustに変更されたことですUserDefaults

キーをコードの別の場所で再利用できるように、キーをグローバルな場所に格納することをお勧めします。

struct defaultsKeys {
    static let keyOne = "firstStringKey"
    static let keyTwo = "secondStringKey"
}

Swift 3.0、4.0、5.0

// Setting

let defaults = UserDefaults.standard
defaults.set("Some String Value", forKey: defaultsKeys.keyOne)
defaults.set("Another String Value", forKey: defaultsKeys.keyTwo)

// Getting

let defaults = UserDefaults.standard
if let stringOne = defaults.string(forKey: defaultsKeys.keyOne) {
    print(stringOne) // Some String Value
}
if let stringTwo = defaults.string(forKey: defaultsKeys.keyTwo) {
    print(stringTwo) // Another String Value
}

Swift 2.0

// Setting

let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject("Some String Value", forKey: defaultsKeys.keyOne)
defaults.setObject("Another String Value", forKey: defaultsKeys.keyTwo)

// Getting

let defaults = NSUserDefaults.standardUserDefaults()
if let stringOne = defaults.stringForKey(defaultsKeys.keyOne) {
    print(stringOne) // Some String Value
}
if let stringTwo = defaults.stringForKey(defaultsKeys.keyTwo) {
    print(stringTwo) // Another String Value
}

マイナーな構成、フラグ、またはベース文字列よりも深刻な場合は、何らかの永続ストアを使用する必要があります。現在のところ、一般的なオプションはRealmですが、SQLiteまたはApplesの独自のCoreDataを使用することもできます。


7
いい例です。これはおそらく構造体ではなく列挙型である必要があります。
パンアンドスキャン

3
これは、列挙型の奇妙な実装です。静的定数がある場合は、構造体の場合もあります。
Craig Grummitt 2016年

1
このコードは間違っています。KVCメソッドsetValue(_:forKey:)を使用してデータをUserDefaultsに保存しないでください。提供されてUserDefaultsいるset(_:forKey:)(Swift 3の)メソッドを使用します
rmaddy

Swift 3のコードを更新しました。Swift 2の構文がどうあるべきかわかりません。
rmaddy

@rmaddyそのままで結構です。
ウェズ

57

彼らはNSUserDefaultsを使用すると言っています

初めて(アプリを閉じた後)長期的なデータストレージを実装していたとき、オンラインで読んだすべての情報がNSUserDefaultsを示していました。しかし、辞書を保存したかったのですが、できれば苦労しました。タイプエラーをなくすために何時間も費やしました。

NSUserDefaultsの機能も制限されています

さらに読むと、NSUserDefaultsの読み取り/書き込みが、アプリがすべてを一度にすべて読み取りまたは書き込みするのを強制する方法が明らかになったため、効率的ではありませんでした。その後、配列を取得することは簡単ではないことを学びました。いくつかの文字列またはブール値を格納している場合、NSUserDefaultsは実際には理想的ではないことに気付きました。

また、スケーラブルではありません。コーディング方法を学んでいる場合は、スケーラブルな方法を学んでください。NSUserDefaultsは、設定に関連する単純な文字列またはブール値を格納する場合にのみ使用してください。Core Dataを使用して配列やその他のデータを保存します。彼らが言うほど難しくはありません。小さなものから始めましょう。

更新:また、Apple Watchのサポートを追加する場合は、別の考慮事項があります。これで、アプリのNSUserDefaultsがWatch Extensionに自動的に送信されます。

コアデータの使用

したがって、Core Dataの方がより難しいソリューションであるという警告を無視して、読み始めました。3時間以内に私はそれを働かせました。テーブル配列をCore Dataに保存し、アプリを開いたときにデータを再ロードしました!チュートリアルのコードは適応するのに十分簡単で、少し余分な実験をするだけで、タイトルと詳細の両方の配列を格納することができました。

したがって、NSUserDefaultタイプの問題に苦労している、または文字列を保存する以上の必要があるこの投稿を読んでいる人は、1時間か2時間かけてコアデータを操作することを検討してください。

これが私が読んだチュートリアルです:

http://www.raywenderlich.com/85578/first-core-data-app-using-swift

「コアデータ」をチェックしなかった場合

アプリを作成したときに「コアデータ」をチェックしなかった場合は、後で追加でき、5分しかかかりません。

http://craig24.com/2014/12/how-to-add-core-data-to-an-existing-swift-project-in-xcode/

http://blog.zeityer.com/post/119012600864/adding-core-data-to-an-existing-swift-project

コアデータリストから削除する方法

Coredata Swiftからデータを削除する


6
Documentsディレクトリのどこか、またはアプリのサンドボックスディレクトリのどこかに.plistファイルにデータを保存するという中盤があります。
Nicolas Miari

私は初心者なので、この質問に1粒の塩を加えますが、その中間点はありますか?NSUserDefaultsは実質的にとにかくp.listファイルであるため、(私が読んだ内容に基づいて)ドキュメントディレクトリのp.listファイルに保存することは、NSUserDefaultsを使用することと同じです。私がその方法を使用しなかった理由は、配列をp.listに保存すると、別の型に変換し、後で値を復元するときに、値を読み取った後に値を再割り当てする必要があるなど、追加の手順が必要と思われたためですp.listから。繰り返しますが、過去数日間の私の読書のみに基づいています。
Dave G

まあ、の.plistファイルへの配列は非常に簡単です保存(階層内のすべてのオブジェクトが配列、文字列、辞書、または数字(なしカスタムクラス)です。
ニコラスMiari

ファイルの読み取りはオールオアナッシングですが、構造に応じてデータを個別のファイルに分割できます。そして、CoreDataには、少なくとも最後にチェックしたときに、大きな学習曲線がありました。
Nicolas Miari

3
私は言うでしょう:NSUserDefaultsを使用して設定を保存します(結局のところその名前が意味します)、永続的または機密データを保存するためのキーチェーン、非常に基本的なアプリ生成データ用の.plistファイルのカスタムスキーム、およびより重いもののためのCoreData 。
Nicolas Miari

11

@bploathttp://www.codingexplorer.com/nsuserdefaults-a-swift-introduction/へのリンクに感謝します

一部の基本的な文字列ストレージでは、答えは非常に単純であることがわかりました。

let defaults = NSUserDefaults.standardUserDefaults()

// Store
defaults.setObject("theGreatestName", forKey: "username")

// Receive
if let name = defaults.stringForKey("username")
{
    print(name)
    // Will output "theGreatestName"
}

私はそれをここで要約しましたhttp://ridewing.se/blog/save-local-data-in-swift/



7

Swift 4.0の場合、これは簡単になりました。

let defaults = UserDefaults.standard
//Set
defaults.set(passwordTextField.text, forKey: "Password")
//Get
let myPassword = defaults.string(forKey: "Password")

6

Swift 3.0

セッター:ローカルストレージ

let authtoken = "12345"
    // Userdefaults helps to store session data locally 
 let defaults = UserDefaults.standard                                           
defaults.set(authtoken, forKey: "authtoken")

 defaults.synchronize()

ゲッター:ローカルストレージ

 if UserDefaults.standard.string(forKey: "authtoken") != nil {

//perform your task on success }

2
authtokenのようなsmthをUserDefaultsに保存しないでください。これにはキーチェーンを使用してください
BilalReffas '27

5

Swift 3の場合

UserDefaults.standard.setValue(token, forKey: "user_auth_token")
print("\(UserDefaults.standard.value(forKey: "user_auth_token")!)")

KVCメソッドを使用してデータを保存しないでください。
rmaddy

4

何らかの理由でUserDefaultsを処理したくない人のために、NSKeyedArchiverとNSKeyedUnarchiverという別のオプションがあります。アーカイバを使用してオブジェクトをファイルに保存し、アーカイブされたファイルを元のオブジェクトにロードするのに役立ちます。

// To archive object,
let mutableData: NSMutableData = NSMutableData()
let archiver: NSKeyedArchiver = NSKeyedArchiver(forWritingWith: mutableData)
archiver.encode(object, forKey: key)
archiver.finishEncoding()
return mutableData.write(toFile: path, atomically: true)

// To unarchive objects,
if let data = try? Data(contentsOf: URL(fileURLWithPath: path)) {
    let unarchiver = NSKeyedUnarchiver(forReadingWith: data)
    let object = unarchiver.decodeObject(forKey: key)
}

上記のサンプルコードを使用して、オブジェクトをローカルストレージに保存/ロードする簡単なユーティリティを作成しました。あなたはこれを見たいかもしれません。 https://github.com/DragonCherry/LocalStorage


3

Swift 5+

デフォルトのビルトインローカルストレージ機能を詳細にカバーする回答はありません。文字列だけではありません

デフォルトからデータを「取得」するために、アップルのドキュメントから直接次のオプションがあります。

func object(forKey: String) -> Any?
//Returns the object associated with the specified key.

func url(forKey: String) -> URL?
//Returns the URL associated with the specified key.

func array(forKey: String) -> [Any]?
//Returns the array associated with the specified key.

func dictionary(forKey: String) -> [String : Any]?
//Returns the dictionary object associated with the specified key.

func string(forKey: String) -> String?
//Returns the string associated with the specified key.

func stringArray(forKey: String) -> [String]?
//Returns the array of strings associated with the specified key.

func data(forKey: String) -> Data?
//Returns the data object associated with the specified key.

func bool(forKey: String) -> Bool
//Returns the Boolean value associated with the specified key.

func integer(forKey: String) -> Int
//Returns the integer value associated with the specified key.

func float(forKey: String) -> Float
//Returns the float value associated with the specified key.

func double(forKey: String) -> Double
//Returns the double value associated with the specified key.

func dictionaryRepresentation() -> [String : Any]
//Returns a dictionary that contains a union of all key-value pairs in the domains in the search list.

ここに「設定」のオプションがあります

func set(Any?, forKey: String)
//Sets the value of the specified default key.

func set(Float, forKey: String)
//Sets the value of the specified default key to the specified float value.

func set(Double, forKey: String)
//Sets the value of the specified default key to the double value.

func set(Int, forKey: String)
//Sets the value of the specified default key to the specified integer value.

func set(Bool, forKey: String)
//Sets the value of the specified default key to the specified Boolean value.

func set(URL?, forKey: String)
//Sets the value of the specified default key to the specified URL.

大きなデータセットではなく、設定などを保存している場合これらは完全に優れたオプションです。

二重の例

設定:

let defaults = UserDefaults.standard
var someDouble:Double = 0.5
defaults.set(someDouble, forKey: "someDouble")

取得:

let defaults = UserDefaults.standard
var someDouble:Double = 0.0
someDouble = defaults.double(forKey: "someDouble")

ゲッターの1つについて興味深いのは、dictionaryRepresentationです。この便利なゲッターは、データタイプに関係なくすべてのデータタイプを取得し、文字列名でアクセスできる適切なディクショナリに入れます。タイプ「any」であるため、それを戻しますます。

独自のクラスとオブジェクトを格納するにはfunc set(Any?, forKey: String)func object(forKey: String) -> Any?それに応じてセッターとゲッターを使用します。

これにより、ローカルデータを格納するためのUserDefaultsクラスの機能がより明確になることを願っています。

保存する必要がある量と頻度についてのメモで、Hardy_Germanyはこの投稿について良い答えを出しました。ここからの引用です

すでに多くの人が言及したように、.plistにデータを格納するための(物理メモリを除く)SIZEの制限については知りません(例:UserDefaults)。だからそれはどのように多くの問題ではありません。

本当の質問は、新しい/変更された値をどのくらいの頻度で書き込むかです...これは、この書き込みが引き起こすバッテリーの消耗に関連しています。

IOSは、単一の値が変更された場合に「ディスク」への物理的な書き込みを回避する機会はなく、データの整合性を維持するだけです。UserDefaultsに関しては、これによりファイル全体がディスクに再書き込みされます。

これにより、「ディスク」に電源が投入され、長時間電源が投入されたままになり、IOSが低電力状態になるのを防ぎます。

この投稿でユーザーMohammad Reza Farahaniが述べたように、他に注意すべき点は、userDefaultsの非同期および同期の性質です。

デフォルト値を設定すると、プロセス内で同期的に変更され、永続ストレージやその他のプロセスに対して非同期的に変更されます。

たとえば、プログラムを保存してすぐに閉じると、結果が保存されないことに気付く場合があります。これは、プログラムが非同期に持続しているためです。これに気づかない場合があるので、プログラムを終了する前に保存を計画している場合は、終了するまでに少し時間を与えることで、これを考慮する必要があります。

多分誰かがこれについてコメントで共有できるいくつかの素晴らしい解決策を持っていますか?


0

NsUserDefaultsは小さな変数サイズのみを保存します。多くのオブジェクトを保存する場合は、CoreDataをネイティブソリューションとして使用できます。または、.save()関数と同じくらい簡単にオブジェクトを保存できるライブラリを作成しました。SQLiteに基づいています。

SundeedQLite

チェックしてコメントを教えて

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.