๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐ŸŽ iOS/iOS Programming

[iOS, Swift] UserDefault ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ ์ €์žฅ, ์‚ฌ์šฉํ•˜๊ธฐ

728x90

โญ๏ธ UserDefault ๋ž€ ?

  • iOS์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๊ด€ํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜
  • ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ ์ƒ์—์„œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. ์ฆ‰ ๋ฉ”๋ชจ๋ฆฌ ์บ์‹ฑ์„ ํ•œ๋‹ค.
  • ์‚ฌ์šฉ์ž์˜ ์ •๋ณด๋ผ๋˜๊ฐ€ ๊ฒŒ์‹œ๋ฌผ์— ๋Œ€ํ•œ ์ •๋ณด์ฒ˜๋Ÿผ ๋Œ€์šฉ๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ๋•Œ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ,
  • ์ž๋™ ๋กœ๊ทธ์ธ ์—ฌ๋ถ€, ์•„์ด๋”” ์ €์žฅ, ํ™˜๊ฒฝ์„ค์ •์—์„œ ์„ค์ •ํ•˜๋Š” ์„ค์ • ๋ฐ์ดํ„ฐ ๊ฐ’(์‚ฌ์šฉ์ž๊ฐ€ ์„ ํ˜ธํ•˜๋Š” ์ธก์ • ๋‹จ์œ„๋‚˜ ๋ฏธ๋””์–ด ์žฌ์ƒ ์†๋„ ๋“ฑ) ๊ฐ™์€ ๋‹จ์ผ ๋ฐ์ดํ„ฐ ๋“ฑ์„ UserDefaults๋กœ ๋‹ด์•„์„œ ๋ณด๊ด€

 

๊ณต์‹ ๋ฌธ์„œ : https://developer.apple.com/documentation/foundation/userdefaults

 

Apple Developer Documentation

 

developer.apple.com


โญ๏ธ UserDefault ํŠน์ง•

  • ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ(์•ฑ์ด ์‹คํ–‰๋˜๋Š” ๋™์•ˆ)์—์„œ ๋™์ž‘, ์•ฑ์ด ์‹คํ–‰๋˜๋Š” ๋™์•ˆ ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•ด key-value์˜ ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋กํ•˜๊ฑฐ๋‚˜ ๊ฐ€์ ธ์˜จ๋‹ค.
  • [๋ฐ์ดํ„ฐ(value), ํ‚ค(key)]์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅ
    • ํ‚ค(key)์˜ ๊ฐ’์€ String
    • ๋ฐ์ดํ„ฐ(value)๋Š” ๋ชจ๋“  ๊ฐ์ฒด ๊ฐ€๋Šฅ
  • ์šฐ๋ฆฌ๊ฐ€ iOS์— ์•ฑ์„ ์„ค์น˜ํ•˜๋ฉด ์•ฑ์ด ์‹คํ–‰๋˜๋Š” ์‹œ์ ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.
  • ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” Property List๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ, .plist ํŒŒ์ผ์— xml ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ๋œ๋‹ค.
  • ์ด plist ํŒŒ์ผ์€ SandBox ๋‚ด์˜ Bundle Container์— ์ €์žฅ > ์•ฑ ์‚ญ์ œ ์‹œ ๊ฐ™์ด ์‚ญ์ œ๋œ๋‹ค.

โญ๏ธ UserDefault ์‚ฌ์šฉํ•˜๊ธฐ - Swift

1. set

let userName = "์—ฌ๋‹"
UserDefaults.standard.set(userName, forKey: "name")

2. get 

UserDefaults.standard.string(forKey: "name")

3. remove 

UserDefaults.standard.removeObject(forKey: "name")

4.  ์ „์ฒด UserDefault ๊ฐ์ฒด ๋ชฉ๋ก ์กฐํšŒ

for (key, value) in UserDefaults.standard.dictionaryRepresentation() {
  print("\(key) = \(value) \n")
}

โญ๏ธ  UserDefault ์‚ฌ์šฉํ•˜๊ธฐ - Objective-C

1. set

[[NSUserDefaults standardUserDefaults] setObject:false forKey:@"TEST_INVALID"]

2. get 

[[NSUserDefaults standardUserDefaults] objectForKey:@"TEST_INVALID"]

โญ๏ธ UserDefault ์ž˜ ์ €์žฅ ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ - plist ํŒŒ์ผ ํ™•์ธ

Data container ์•ˆ์˜ Library > Preferences ๋‚ด plist ํŒŒ์ผ์—์„œ ํ™•์ธ ๊ฐ€๋Šฅ

 

ํ•ด๋‹น ๊ฒฝ๋กœ ํ™•์ธํ•˜๋Š” ๋ฒ• : NSHomeDirectory ์‚ฌ์šฉ

//UserDefaults ๋ฐ์ดํ„ฐ ์ €์žฅ
UserDefaults.standard.setValue(true, forKey: "test")
//์ €์žฅ ๊ฒฝ๋กœ ์ถœ๋ ฅ
print("App Directory path : \(NSHomeDirectory())")

[์ถœ๋ ฅ๊ฐ’]

์ถœ๋ ฅ๋œ ๊ฒฝ๋กœ์—์„œ Library > Preferences  > ์•ฑ๋ฒˆ๋“คID.plist ํŒŒ์ผ ํ™•์ธ

plist ํŒŒ์ผ์„ ์—ด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ €์žฅ์ด ์ž˜ ๋˜์–ด ์žˆ๋‹ค!


โญ๏ธ UserDefault์— struct ์ €์žฅํ•˜๊ธฐ

“Attempt to insert non-property list object” ์˜ค๋ฅ˜ ํ•ด๊ฒฐํ•˜๊ธฐ

 

์•„๋ž˜ ๋ธ”๋กœ๊ทธ ์ฐธ๊ณ ๋ฅผ ๋งŽ์ด ํ–ˆ๋‹ค.

https://ios-development.tistory.com/702

 

์š”์•ฝ ์ •๋ฆฌํ•˜์ž๋ฉด,

Swift๋Š” ๋ฉ”๋ชจ๋ฆฌ ํ˜น์€ ๋””์Šคํฌ์— ๊ฐ์ฒด ์ •๋ณด๋ฅผ ์ €์žฅํ•  ๋•Œ, byteBuffer๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ €์žฅ

> ์ €์žฅํ•  ๋•Œ, ์•„์นด์ด๋น™์„ ํ†ตํ•ด ๋ฐ”์ดํŠธ ํ˜•ํƒœ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ์ž‘์—…์ด ํ•„์š”

> ๊ธฐ๋ณธํƒ€์ž…์ธ Int, Double, String์€ Userdefault์— ์ €์žฅํ•  ๋•Œ ๋‚ด๋ถ€์ ์œผ๋กœ ์ž‘์—…์ด ์ง„ํ–‰

> ํ•˜์ง€๋งŒ, Struct์˜ ๊ฒฝ์šฐ ์ง์ ‘ ์•„์นด์ด๋น™ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด ์ค˜์•ผํ•จ!!!!!

> ๋”ฐ๋ผ์„œ ์œ„ ์—๋Ÿฌ๋Š” ์•„์นด์ด๋น™ํ•ด์ฃผ์ง€ ์•Š์•„ ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ~~~~

์•„๋ž˜๋Š” Solution!

๋จผ์ €, Struct์— Codable ํ”„๋กœํ† ์ฝœ ์ค€์ˆ˜ํ•ด์•ผ ํ•จ

struct SubjectModel: Codable {
    let code: Int
    let value: String
    let topic: String
}

propertyWrapper๋ฅผ ์ด์šฉํ•˜์—ฌ ์•„์นด์ด๋น™, ์–ธ์•„์นด์ด๋น™ ๋‚ด๋ถ€์ ์œผ๋กœ ๊ตฌํ˜„ํ•ด์ค€๋‹ค.

struct UserDefaultsManager {
    @UserDefaultWrapper(key: "subjectList", defaultValue: nil)
    static var subjectList: [SubjectModel]?
}

//UserDefaultWrapper ์ •์˜
@propertyWrapper
struct UserDefaultWrapper<T: Codable> {
    private let key: String
    private let defaultValue: T?

    init(key: String, defaultValue: T?) {
        self.key = key
        self.defaultValue = defaultValue
    }
    
    var wrappedValue: T? {
        get {
        	// ์–ธ์•„์นด์ด๋น™ ์ •์˜ : JSONDecoder ์‚ฌ์šฉ
            if let savedData = UserDefaults.standard.object(forKey: key) as? Data {
                let decoder = JSONDecoder()
                if let lodedObejct = try? decoder.decode(T.self, from: savedData) {
                    return lodedObejct
                }
            }
            return defaultValue
        }
        set {
        	// ์•„์นด์ด๋น™ ์ •์˜ : JSONEncoder ์‚ฌ์šฉ
            let encoder = JSONEncoder()
            if let encoded = try? encoder.encode(newValue) {
                UserDefaults.standard.setValue(encoded, forKey: key)
            }
        }
    }
}

์ €์žฅํ•˜๊ณ  ๋ณผ๋Ÿฌ์˜ฌ ๋•Œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ–ˆ๋‹ค.

let dataString = String(data: response.data!, encoding: .utf8)
let data = dataString!.data(using: .utf8)!
if let jsonArray = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? [Dictionary<String,Any>]{
    UserDefaultsManager.subjectList = []
    for subject in jsonArray{
        let subjectData = SubjectModel(code: subject["code"] as! Int,
                                       value: subject["value"] as! String,
                                       topic: subject["topic"] as! String)
        //์ €์žฅํ•˜๊ธฐ                            
        UserDefaultsManager.subjectList!.insert(subjectData, at: 0)
    }
}
//๋ถˆ๋Ÿฌ์˜ค๊ธฐ
print(UserDefaultsManager.subjectList)
๋ฐ˜์‘ํ˜•