Yerel veriler bir Swift uygulamasına nasıl kaydedilir?


151

Şu anda Swift'de geliştirilmiş bir iOS uygulaması üzerinde çalışıyorum ve kullanıcı tarafından oluşturulan bazı içerikleri cihazda depolamam gerekiyor ancak kullanıcıların içeriğini cihazda depolamanın / almanın basit ve hızlı bir yolunu bulamıyorum.

Birisi yerel depolamanın nasıl saklanacağını ve erişileceğini açıklayabilir mi?

Buradaki fikir, kullanıcı bir eylemi gerçekleştirdiğinde verileri depolamak ve uygulama başladığında bunu almaktır.


Merhaba ve hoş geldiniz, ne tür veriler saklıyorsunuz? Aradığınız şeyin bir örneğini vermek için herhangi bir kod verebilir misiniz? Teşekkürler.
Wez

1
Depolamam gereken veriler temelde sadece dize verileridir. Bu yüzden gerçekten basit tutmak için, kullanıcı uygulamayı yeniden başlatırsa alabileceğim iki String değerini kaydetmem gerekiyor.
Nicklas Ridewing

2
NSUserDefaults'u kullanabilirsiniz. İşte ihtiyacınız olan bilgiler codingexplorer.com/nsuserdefaults-a-swift-introduction
bpolat

Yanıtlar:


199

Yalnızca iki dizgeyi depoluyorsanız en basit çözüm NSUserDefaults, Swift 3'te bu sınıfın sadece olarak yeniden adlandırılmasıdır UserDefaults.

Anahtarlarınızı dünyanın herhangi bir yerinde saklamak en iyisidir, böylece onları kodunuzun başka bir yerinde yeniden kullanabilirsiniz.

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

Swift 3.0, 4.0 ve 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
}

Şu anda popüler bir seçenektir - minör geneli, bayraklar veya baz dizeleri daha ciddi bir şey için kalıcı deposundan çeşit kullanmalısınız Diyar ama aynı zamanda kullanabilir SQLite'ı veya Elmalar çok kendi CoreData .


7
Güzel örnek. Bu muhtemelen bir yapı yerine bir enum olmalıdır.
kaydır ve tara

3
Bu tuhaf bir numaralandırma uygulaması, eğer sadece statik sabitleriniz varsa, bir yapı da olabilir.
Craig Grummitt

1
Bu kod yanlış. setValue(_:forKey:)Verileri UserDefaults'a kaydetmek için KVC yöntemlerini kullanmayın . Sağlanan (Swift 3'te) UserDefaultsyöntemlerini kullanın set(_:forKey:).
rmaddy

Swift 3 kodunu güncelledim. Swift 2 sözdiziminin ne olması gerektiğini bilmiyorum.
rmaddy

@rmaddy olduğu gibi iyi.
Wez

58

NSUserDefaults Kullanıyor Diyorlar

Uzun vadeli (uygulama kapatıldıktan sonra) veri depolamayı ilk kez uygularken, çevrimiçi okuduğum her şey beni NSUserDefaults'a yönlendirdi. Bununla birlikte, bir sözlük saklamak istedim ve mümkün olsa da bir acı olduğunu kanıtlıyordu. Yazım hatalarının ortadan kalkması için saatler harcadım.

NSUserDefaults da İşlevde Sınırlıdır

Daha fazla okuma, NSUserDefaults'un okuma / yazma işleminin, uygulamayı bir kerede her şeyi veya hiçbir şeyi okumaya / yazmaya gerçekten zorladığını ortaya çıkardı, bu nedenle verimli değildir. Sonra bir diziyi almanın kolay olmadığını öğrendim. Birkaç dizeden veya booleandan daha fazlasını depoluyorsanız, NSUserDefaults'un gerçekten ideal olmadığını anladım.

Ayrıca ölçeklenebilir de değil. Kod yazmayı öğreniyorsanız, ölçeklenebilir yolu öğrenin. NSUserDefaults'u yalnızca tercihlerle ilgili basit dizeleri veya boole'leri depolamak için kullanın. Dizileri ve diğer verileri Core Data kullanarak depolayın, dedikleri kadar zor değil. Küçük başlayın.

Güncelleme: Ayrıca, Apple Watch desteği eklerseniz, başka bir olası değerlendirme daha vardır. Uygulamanızın NSUserDefaults artık otomatik olarak İzleme Uzantısına gönderilir.

Temel Verileri Kullanma

Bu yüzden Core Data'nın daha zor bir çözüm olduğuna dair uyarıları görmezden geldim ve okumaya başladım. Üç saat içinde çalıştırdım. Tablo dizim Core Data'ya kaydedildi ve uygulamayı yeniden açtıktan sonra verileri yeniden yükledim! Öğretici kodu uyarlamak için yeterince kolaydı ve sadece biraz fazladan deneyle hem başlık hem de ayrıntı dizilerini depolamasını sağlayabildim.

Bu nedenle, NSUserDefault türü sorunları ile mücadele eden veya ihtiyacı dizeleri depolamaktan daha fazlası olan bu gönderiyi okuyan herkes için, çekirdek verilerle oynamak için bir veya iki saat harcamayı düşünün.

İşte okuduğum öğretici:

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

"Temel Veriler" i kontrol etmediyseniz

Uygulamanızı oluştururken "Temel Veriler" i işaretlemediyseniz, daha sonra ekleyebilirsiniz ve yalnızca beş dakika sürer:

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

Çekirdek Veri Listelerinden Nasıl Silinir

Coredata Swift'den Veri Silme


6
Verilerinizi bir .plist dosyasına Belgeler dizininde veya uygulamanın korumalı dizininde başka bir yere kaydetmenin orta yolu vardır.
Nicolas Miari

Acemiyim, bu soruyu biraz tuzlu al, ama bu orta yol mu? NSUserDefaults pratik olarak bir p.list dosyasıdır, bu nedenle (okuduğuma göre) belgeler dizinindeki bir p.list dosyasına kaydetmek, NSUserDefaults kullanmakla aynıdır. Bu yöntemi kullanmamamın nedeni, bir diziyi bir p.list'e kaydetmenin, onu başka bir türe dönüştürmek gibi ekstra adımlar içeriyor gibi görünmesi ve daha sonra değerleri geri yüklerken, değerleri okuduktan sonra yeniden atamayı gerektirmesiydi. s. listesinden. Yine, yalnızca son birkaç gündeki okumalarıma dayanarak.
Dave G

Bir diziyi .plist dosyasına kaydetmek oldukça basittir (hiyerarşideki tüm nesneler Diziler, Dizeler, Sözlükler veya Sayılardır (özel sınıflar yoktur).
Nicolas Miari

Kabul edildiğinde, dosyanın okunması ya hep ya hiçtir, ancak verilerinizi yapısına bağlı olarak ayrı dosyalara bölebilirsiniz. Ve CoreData en azından son kontrol ettiğimde önemli bir öğrenme eğrisine sahipti.
Nicolas Miari

3
Şunu söyleyebilirim: tercihleri ​​depolamak için NSUserDefaults kullanın (sonuçta adın anlamı budur), Kalıcı ve / veya hassas verileri depolamak için anahtarlık, çok temel uygulama tarafından oluşturulan veriler için .plist dosyalarının özel şeması ve daha ağır şeyler için CoreData .
Nicolas Miari

11

Okey, @bploat ve http://www.codingexplorer.com/nsuserdefaults-a-swift-introduction/ bağlantısına çok teşekkürler

Bazı temel dize depolaması için cevabın oldukça basit olduğunu buldum.

let defaults = NSUserDefaults.standardUserDefaults()

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

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

Bunu burada özetledim http://ridewing.se/blog/save-local-data-in-swift/


9

NSCoding ve NSKeyedArchiver'ı kullanmak , veriler için çok karmaşık olan NSUserDefaults, ancak CoreData'nın gereğinden fazla olacağı başka bir harika seçenektir . Ayrıca, dosya yapısını daha açık bir şekilde yönetme fırsatı verir, bu da şifrelemeyi kullanmak istiyorsanız harikadır.


7

Swift 4.0 için bu daha kolay hale geldi:

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

6

Swift 3.0

Ayarlayıcı: Yerel Depolama

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

 defaults.synchronize()

Getter: Yerel Depolama

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

//perform your task on success }

3
Sen UserDefaults..Please içinde Kimlik Doğrulama Simgesi gibi sorulmak tasarruf bunun için Anahtarlık kullanmamalısınız
BilalReffas

5

Swift 3 için

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

Verileri kaydetmek için KVC yöntemlerini kullanmayın.
rmaddy

4

Bazı nedenlerle UserDefaults'u işlemeyi tercih etmeyen biri için başka bir seçenek daha var - NSKeyedArchiver & NSKeyedUnarchiver. Arşivleyici kullanarak nesneleri bir dosyaya kaydetmeye ve arşivlenmiş dosyayı orijinal nesnelere yüklemeye yardımcı olur.

// 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)
}

Yerel depolamadaki nesneleri kaydetmek / yüklemek için basit bir yardımcı program yazdım, yukarıdaki örnek kodları kullandım. Bunu görmek isteyebilirsin. https://github.com/DragonCherry/LocalStorage


4

Swift 5+

Yanıtların hiçbiri, varsayılan olarak yerleşik yerel depolama yeteneklerini ayrıntılı olarak kapsamıyor. Dizelerden çok daha fazlasını yapabilir .

Varsayılanlardan veri 'almak' için doğrudan apple belgelerinde bulunan aşağıdaki seçeneklere sahipsiniz.

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.

İşte 'ayar' için seçenekler

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.

Tercihler gibi şeyler depoluyorsanız ve büyük bir veri kümesi yoksa, bunlar mükemmel seçeneklerdir.

Çift Örnek :

Ayar:

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

Başlarken:

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

Alıcılardan biri hakkında ilginç olan, sözlük Temsilcisi , bu kullanışlı alıcı, ne olduklarına bakılmaksızın tüm veri türlerinizi alacak ve bunları dize adıyla erişebileceğiniz ve istediğinizde doğru karşılık gelen veri türünü verebileceğiniz güzel bir sözlüğe koyacaktır. o türden beri geri döndü 'herhangi' .

Kendi sınıflarınızı ve nesnelerinizi ayrıca func set(Any?, forKey: String)vefunc object(forKey: String) -> Any? ayarlayıcı ve alıcıyı buna göre .

Umarım bu, UserDefaults sınıfının yerel verileri depolamak için gücünü daha fazla açıklığa kavuşturur.

Ne kadar ve ne sıklıkla saklamanız gerektiğine ilişkin olarak Hardy_Germany bu yazıda buna iyi bir cevap verdi , işte ondan bir alıntı

Daha önce de belirtildiği gibi: Verileri bir .plist (örn. UserDefaults) içinde depolamak için herhangi bir SIZE sınırlamasından (fiziksel bellek dışında) haberdar değilim. Yani bu NE KADAR sorusu değil.

Asıl soru NASIL yeni / değiştirilmiş değerler yazmanız olmalıdır ... Ve bu, yazının neden olacağı pil boşalmasıyla ilgilidir.

IOS, veri bütünlüğünü korumak için tek bir değerin değişmesi durumunda "diske" fiziksel bir yazmayı engelleme şansına sahip değildir. UserDefaults ile ilgili olarak bu, tüm dosyanın diske yeniden yazılmasına neden olur.

Bu, "diski" çalıştırır ve daha uzun süre açık kalmasını sağlar ve IOS'nin düşük güç durumuna geçmesini önler.

Bu kullanıcı Mohammad Reza Farahani tarafından belirtildiği gibi nota başka bir şey mesaja olduğunu asenkron ve senkron userDefaults doğası.

Varsayılan bir değer belirlediğinizde, işleminiz içinde eşzamanlı olarak ve eşzamansız olarak kalıcı depolama ve diğer işlemlerle değiştirilir.

Örneğin, programı kaydeder ve hızlı bir şekilde kapatırsanız, sonuçları kaydetmediğini fark edebilirsiniz, bunun nedeni, eşzamansız olarak devam etmesidir. Bunu her zaman fark etmeyebilirsiniz, bu nedenle programdan çıkmadan önce tasarruf etmeyi planlıyorsanız, bitirmesi için biraz zaman vererek bunu hesaba katmak isteyebilirsiniz.

Belki birinin bunun için yorumlarda paylaşabileceği güzel çözümleri vardır?


0

NsUserDefaults yalnızca küçük değişken boyutları kaydeder. Çok sayıda nesneyi kaydetmek istiyorsanız CoreData'yı yerel bir çözüm olarak kullanabilirsiniz veya nesneleri kaydetmenize .save () işlevi kadar kolay bir şekilde yardımcı olacak bir kitaplık oluşturdum. SQLite tabanlı.

SundeedQLite

Kontrol et ve bana yorumlarını söyle

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.