私は現在、Swiftで開発されたiOSアプリを開発しています。ユーザーが作成したコンテンツをデバイスに保存する必要がありますが、ユーザーのコンテンツをデバイスに保存/受信する簡単で迅速な方法が見つからないようです。
誰かがローカルストレージを保存してアクセスする方法を説明できますか?
アイデアは、ユーザーがアクションを実行したときにデータを保存し、アプリの起動時にそれを受け取ることです。
私は現在、Swiftで開発されたiOSアプリを開発しています。ユーザーが作成したコンテンツをデバイスに保存する必要がありますが、ユーザーのコンテンツをデバイスに保存/受信する簡単で迅速な方法が見つからないようです。
誰かがローカルストレージを保存してアクセスする方法を説明できますか?
アイデアは、ユーザーがアクションを実行したときにデータを保存し、アプリの起動時にそれを受け取ることです。
回答:
2つの文字列を格納するだけの場合の最も簡単な解決策はNSUserDefaults
、Swift 3ではこのクラスの名前がjustに変更されたことですUserDefaults
。
キーをコードの別の場所で再利用できるように、キーをグローバルな場所に格納することをお勧めします。
struct defaultsKeys {
static let keyOne = "firstStringKey"
static let keyTwo = "secondStringKey"
}
// 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
}
// 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を使用することもできます。
setValue(_:forKey:)
を使用してデータをUserDefaultsに保存しないでください。提供されてUserDefaults
いるset(_:forKey:)
(Swift 3の)メソッドを使用します
彼らは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
コアデータリストから削除する方法
@bploatとhttp://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/
使用する NSCodingとNSKeyedArchiverことは、にとっては複雑すぎるNSUserDefaults
が、CoreDataはやり過ぎになるデータのためのもう1つの優れたオプションです。また、ファイル構造をより明示的に管理する機会も与えられます。これは、暗号化を使用する場合に最適です。
Swift 4.0の場合、これは簡単になりました。
let defaults = UserDefaults.standard
//Set
defaults.set(passwordTextField.text, forKey: "Password")
//Get
let myPassword = defaults.string(forKey: "Password")
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 }
何らかの理由で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
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の非同期および同期の性質です。
デフォルト値を設定すると、プロセス内で同期的に変更され、永続ストレージやその他のプロセスに対して非同期的に変更されます。
たとえば、プログラムを保存してすぐに閉じると、結果が保存されないことに気付く場合があります。これは、プログラムが非同期に持続しているためです。これに気づかない場合があるので、プログラムを終了する前に保存を計画している場合は、終了するまでに少し時間を与えることで、これを考慮する必要があります。
多分誰かがこれについてコメントで共有できるいくつかの素晴らしい解決策を持っていますか?
NsUserDefaultsは小さな変数サイズのみを保存します。多くのオブジェクトを保存する場合は、CoreDataをネイティブソリューションとして使用できます。または、.save()関数と同じくらい簡単にオブジェクトを保存できるライブラリを作成しました。SQLiteに基づいています。
チェックしてコメントを教えて