본문 바로가기
iOS/iOS

[iOS] UserDefaults를 사용한 데이터 저장

by 원만사 2021. 12. 7.
반응형

앱 실행 전반에 걸쳐 키-값 쌍을 지속적으로 저장할 수 있는 사용자의 기본 데이터베이스에 대한 인터페이스
class UserDefaults : NSObject

 

 UserDefaults 클래스는 기본 시스템과 상호 작용하기 위한 프로그래밍 방식의 인터페이스를 제공한다. 런타임 시 객체를 사용하여 app이 사용자의 기본 데이터베이스에서 사용하는 기본값을 읽기 때문에 필요할 때마다 데이터베이스를 열 필요가 없어진다.

 

 사용자의 정보라던가 게시물에 대한 정보처럼 대용량의 데이터를 저장할 때 사용하지 않고 자동 로그인 여부, 아이디 저장, 환경설정에서 설정하는 설정 데이터 값(사용자가 선호하는 측정 단위나 미디어 재생 속도 등) 같은 단일 데이터 등을 UserDefaults로 담아서 보관한다.

 

 

예제

 UIAlertController에서 사용했던 예제를 이용해서 간단하게 UserDefaults를 사용해보자. 해당 예제에서 텍스트를 입력하고 앱을 종료했다가 다시 실행하면 입력했던 텍스트 값은 사라지고 Label의 값이 초기 상태로 돌아가는 것을 볼 수 있다.

 

 이제 UserDefaults를 사용하여 앱을 종료 후 다시 실행시켜도 입력한 텍스트 값이 남아있도록 바꿔보자. 먼저 해당 예제에서 조금 달라진 부분이 있다. labelText라는 프로퍼티를 새로 하나 만들어 해당 값에 입력된 텍스트 값을 넣어주도록 변경했다. didSet을 활용하기 위해 프로퍼티를 추가했는데, @IBOutlet의 경우 참조 타입인 클래스이기 때문에 인스턴스를 변경하지 않는 한 didSet은 호출되지 않는다고 한다(참고). 

 

 아무튼! 메시지 창에서 텍스트를 입력하고 나면 labelText의 값이 변경 되고 이 순간 labelText의 didSet이 호출되면서 아래의 saveLabel() 메서드가 실행된다.

private func saveLabel() {
        let userDefaults = UserDefaults.standard
        
        userDefaults.set(self.labelText, forKey: "labelText")
    }

 

 UserDefaults의 경우 싱글톤이기 때문에 하나의 공유된 객체만을 사용한다. UserDefaults.standard가 이에 해당한다. 그렇기 때문에 UserDefaults.standard를 가져와 userDefaults 변수에 담아둔다. 그 후에 set 메서드를 이용해서 labelText의 값을 저장한다. 위에서 언급했듯이 UserDefaults는 키-값 쌍으로 값을 저장한다. labelText의 키 값으로 'labelText'를 입력했음을 알 수 있다.

 

 이제 앱이 실행될 때 해당 키 값을 이용해서 저장된 정보를 가져오면 된다. 앱이 처음 로드될 때 호출되는 viewDidLoad() 메서드에서 아래의 loadLabelText() 메서드를 실행시킨다.

private func loadLabelText() {
        let userDefaults = UserDefaults.standard
        
        guard let data = userDefaults.object(forKey: "labelText") as? String else { return }
        self.alertLabel.text = data
        
    }

 

 마찬가지로 UserDefaults.standard를 사용해서 UserDefaults 객체를 가져온다. 그 후 object 메서드를 사용하여 입력한 키 값에 해당하는 데이터를 가져온다. 이 때 반환 타입이 Any이므로 우리가 사용하는 String으로 다운캐스팅을 해준다. 그 후 가져온 데이터를 alertLabel의 text로 설정해준다. 이제 앱을 종료 후 다시 실행시켜도 아까 입력된 텍스트 값이 그대로 유지되는 것을 볼 수 있다.

 

 전체 코드는 다음과 같다.

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var alertLabel: UILabel!
    
    var labelText: String? {
        didSet {
            self.saveLabel()
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.loadLabelText()
    }

    @IBAction func clickAlertButton(_ sender: UIButton) {
        let alert = UIAlertController(title: "메세지 입력", message: nil, preferredStyle: .alert)
        
        let cancelButton = UIAlertAction(title: "취소", style: .cancel, handler: nil)
        let okButton = UIAlertAction(title: "입력", style: .default, handler: { [weak self] _ in
            guard let text = alert.textFields?[0].text else { return }
            self?.labelText = text
            self?.alertLabel.text = text
        })
        
        alert.addTextField(configurationHandler: { textField in
            textField.placeholder = "메세지를 입력하세요."
        })
        
        alert.addAction(cancelButton)
        alert.addAction(okButton)
        
        self.present(alert, animated: true, completion: nil)
    }
    
    private func saveLabel() {
        let userDefaults = UserDefaults.standard
        
        userDefaults.set(self.labelText, forKey: "labelText")
    }
    
    private func loadLabelText() {
        let userDefaults = UserDefaults.standard
        
        guard let data = userDefaults.object(forKey: "labelText") as? String else { return }
        self.alertLabel.text = data
        
    }
    
}

 

 

참고

- https://daesiker.tistory.com/68

- https://developer.apple.com/documentation/foundation/userdefaults/

 

반응형

댓글