Swift 앱에서 로컬 데이터를 저장하는 방법은 무엇입니까?


148

현재 Swift에서 개발 된 iOS 앱을 개발 중이며 사용자가 만든 일부 콘텐츠를 장치에 저장해야하지만 사용자 콘텐츠를 장치에 저장 / 수신하는 간단하고 빠른 방법을 찾지 못하는 것 같습니다.

누군가 로컬 저장소를 저장하고 액세스하는 방법을 설명 할 수 있습니까?

아이디어는 사용자가 작업을 실행할 때 데이터를 저장하고 앱이 시작될 때 데이터를받는 것입니다.


환영합니다. 어떤 종류의 데이터를 저장하고 있습니까? 찾고자하는 예제를 제공하는 코드를 제공 할 수 있습니까? 감사.
— Wez

1
저장 해야하는 데이터는 기본적으로 문자열 데이터입니다. 정말 간단하게 유지하려면 사용자가 앱을 다시 시작할 때받을 수있는 두 개의 문자열 값을 저장해야합니다.
— Nicklas Ridewing

2
NSUserDefaults를 사용할 수 있습니다. 다음은 필요한 정보입니다 codingexplorer.com/nsuserdefaults-a-swift-introduction
— bpolat

답변:


197

두 개의 문자열 만 저장하는 경우 가장 간단한 해결책 NSUserDefaults은 Swift 3에서이 클래스의 이름이 just로 바뀌는 것 UserDefaults입니다.

코드의 다른 곳에서 키를 재사용 할 수 있도록 전 세계 어딘가에 키를 저장하는 것이 가장 좋습니다.

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

스위프트 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
}

스위프트 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 또는 Apple 자체의 CoreData 를 사용할 수도 있습니다 .


7
좋은 예입니다. 이것은 아마도 구조체 대신 열거 형이어야합니다.
— 팬 앤 스캔

3
열거 형의 이상한 구현입니다. 정적 상수가있는 경우 구조체 일 수도 있습니다.
— Craig Grummitt 2016 년

1
이 코드는 잘못되었습니다. KVC 방법 setValue(_:forKey:)을 사용하여 데이터를 UserDefaults에 저장 하지 마십시오 . (Swift 3에서) 제공된 UserDefaults방법을 사용하십시오 set(_:forKey:).
— rmaddy

Swift 3 코드를 업데이트했습니다. Swift 2 구문이 무엇인지 모르겠습니다.
— rmaddy

@rmaddy 그대로 괜찮습니다.
— Wez

57

NSUserDefaults를 사용한다고 말합니다.

처음 (앱 종료 후) 데이터 스토리지를 처음 구현할 때 온라인에서 읽은 모든 내용이 NSUserDefaults를 가리 켰습니다. 그러나 사전을 저장하고 싶었지만 가능한 한 고통 스럽습니다. 나는 유형 오류를 없애려고 몇 시간을 보냈습니다.

NSUserDefaults도 기능이 제한됩니다

더 읽어 보면 NSUserDefaults의 읽기 / 쓰기가 실제로 앱이 모든 것을 읽거나 쓰지 못하게하는 방법을 보여 주었으므로 효율적이지 않습니다. 그런 다음 배열 검색이 간단하지 않다는 것을 알게되었습니다. 문자열이나 부울을 몇 개 이상 저장하면 NSUserDefaults가 이상적이지 않다는 것을 깨달았습니다.

또한 확장 할 수 없습니다. 코딩 방법을 배우고 있다면 확장 가능한 방법을 배우십시오. 기본 설정과 관련된 간단한 문자열 또는 부울을 저장하는 데 NSUserDefaults 만 사용하십시오. Core Data를 사용하여 어레이 및 기타 데이터를 저장하십시오. 작은 것부터 시작하십시오.

업데이트 : 또한 Apple Watch 지원을 추가하면 또 다른 잠재적 고려 사항이 있습니다. 이제 앱의 NSUserDefaults가 Watch Extension으로 자동 전송됩니다.

핵심 데이터 사용

그래서 Core Data가 더 어려운 솔루션이라는 경고를 무시하고 읽기 시작했습니다. 세 시간 안에 나는 그것을 작동시켰다. 테이블 배열을 Core Data에 저장하고 앱을 다시 열면 데이터를 다시로드했습니다! 튜토리얼 코드는 쉽게 적응할 수 있었고 약간의 추가 실험만으로 제목과 세부 배열을 모두 저장할 수있었습니다.

따라서 NSUserDefault 유형 문제로 어려움을 겪고 있거나 문자열을 저장하는 것 이상이 필요한이 게시물을 읽는 사람이라면 코어 데이터를 가지고 한두 시간을 소비하는 것을 고려하십시오.

내가 읽은 튜토리얼은 다음과 같습니다.

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

저는 초보자입니다. 소금 한알로이 질문을하세요.하지만 그 중간 정도입니까? NSUserDefaults는 실제로 p.list 파일이므로, 내가 읽은 내용에 따라 문서 디렉토리의 p.list 파일에 저장하는 것은 NSUserDefaults를 사용하는 것과 같습니다. 그 방법을 사용하지 않은 이유는 배열을 p.list에 저장하면 다른 유형으로 변환 한 다음 나중에 값을 복원 할 때 값을 다시 할당 할 때 값을 다시 할당 해야하는 것과 같은 추가 단계가 필요하다고 들었 기 때문입니다. p.list에서. 다시 말하지만, 지난 며칠 동안 나의 독서에 기초한 것입니다.
— Dave G

배열을 .plist 파일에 저장하는 것은 매우 간단합니다 (계층 구조의 모든 객체는 배열, 문자열, 사전 또는 숫자 (사용자 정의 클래스 없음)
— Nicolas Miari

동의하면 파일을 읽는 것이 전부 또는 아무것도 아니지만, 구조에 따라 데이터를 별도의 파일로 분할 할 수 있습니다. 그리고 CoreData는 적어도 마지막으로 확인했을 때 상당한 학습 곡선을 보였습니다.
— Nicolas Miari

3
NSUserDefaults를 사용하여 환경 설정 (결과적으로 이름의 의미)을 저장하고, 지속적이고 민감한 데이터를 저장하는 키 체인, 매우 기본적인 앱 생성 데이터를 위한 .plist 파일의 사용자 정의 구성표 , 더 무거운 것을위한 CoreData .
— Nicolas Miari

11

@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/에 요약했습니다.


9

NSCoding과 NSKeyedArchiver를 사용 하는 것은 너무 복잡 NSUserDefaults하지만 CoreData가 과도하게 사용되는 데이터에 대한 또 다른 훌륭한 옵션입니다 . 또한 파일 구조를보다 명시 적으로 관리 할 수있는 기회를 제공하므로 암호화를 사용하려는 경우 유용합니다.


7

Swift 4.0의 경우 더 쉬워졌습니다.

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

6

스위프트 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
UserDefaults에 authtoken과 같은 smth를 저장해서는 안됩니다. 키 체인을 사용하십시오
— BilalReffas

5

스위프트 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


4

스위프트 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")

getter 중 하나에 흥미로운 점은 dictionaryRepresentation 이며,이 편리한 getter는 데이터 유형에 관계없이 모든 데이터 유형을 가져 와서 문자열 이름으로 액세스하고 요청할 때 올바른 해당 데이터 유형을 제공 할 수있는 좋은 사전에 넣습니다. 'any' 형식이므로 다시 돌아옵니다. .

그에 따라 func set(Any?, forKey: String)and func object(forKey: String) -> Any?setter 및 getter를 사용하여 자신의 클래스와 객체를 저장할 수 있습니다 .

이것이 로컬 데이터를 저장하는 UserDefaults 클래스의 힘을 더 잘 나타내기를 바랍니다.

저장하고 얼마나 자주해야 얼마의 메모에서 Hardy_Germany는 이에 그에 좋은 답변했다 게시물을 , 여기에서 인용 한 것입니다

많은 사람들이 이미 언급했듯이 : .plist (예 : UserDefaults)에 데이터를 저장하는 SIZE 제한 (실제 메모리 제외)을 알지 못합니다. 따라서 HOW MUCH의 문제는 아닙니다.

실제 질문은 얼마나 자주 새 값 / 변경된 값을 작성해야하는지입니다. 그리고 이것은이 쓰기로 인한 배터리 소모와 관련이 있습니다.

iOS는 단일 값이 변경된 경우 데이터 무결성을 유지하기 위해 "디스크"에 물리적으로 쓰는 것을 피할 수 없습니다. UserDefaults와 관련하여 전체 파일이 디스크에 다시 쓰여집니다.

이렇게하면 "디스크"의 전원이 켜지고 오랫동안 전원이 켜진 상태로 유지되어 IOS가 저전력 상태가되지 않습니다.

이 게시물 에서 사용자 Mohammad Reza Farahani가 언급 한 다른 사항 은 userDefaults 의 비동기 및 동기 특성입니다.

기본값을 설정하면 프로세스 내에서 동 기적으로 변경되고 영구 저장소 및 기타 프로세스와 비동기 적으로 변경됩니다.

예를 들어 프로그램을 저장하고 빠르게 닫으면 결과가 저장되지 않는 것을 알 수 있습니다. 이는 비동기 적으로 지속되기 때문입니다. 프로그램을 종료하기 전에 저장을 계획하는 경우 완료 할 시간을 주어이를 설명 할 수 있습니다.

어쩌면 누군가 의견에 공유 할 수있는 좋은 해결책이 있습니까?


0

NsUserDefaults는 작은 가변 크기 만 저장합니다. 많은 객체를 저장하려면 CoreData를 기본 솔루션으로 사용하거나 .save () 함수처럼 객체를 쉽게 저장할 수있는 라이브러리를 만들었습니다. SQLite를 기반으로합니다.

SundeedQLite

그것을 확인하고 의견을 말 해주세요

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.