꾸준히 안타치기

UserDefaults 본문

iOS/기본편 | 실전편 -꼼꼼한재은씨

UserDefaults

글자줍기 2022. 2. 10. 00:10
반응형
  // userDefault에 저장
   let plist = UserDefaults.standard
   plist.setValue(userID, forKey: "name")//이름이라는 키로 저장
   plist.synchronize()//동기화처리

   //userDefaults에 불러오기
    let plist = UserDefaults.standard
   //지정된 값을 꺼내어 각 컨트롤에 설정한다.
    self.userName.text = plist.string(forKey: "name")
    
    //삭제
    UserDefaults.standard.removeObject(forKey: "key")

https://qussk.github.io/2021/02/27/swift-UserDefault 참고

https://developer.apple.com/documentation/foundation/userdefaults 애플

UserDefaults는 앱 삭제 전까지는 데이터가 유지된다. 앱을 종료했다 다시켜도 데이터가 남아있음

데이터 저장
프로퍼티 리스트  관계형 /목록형 데이터 비정형 객체 데이터
NSUserDefault       Core Data Archiving
Custom Property List SQLite  

 

이것을 만들어보자

메인스토리보드에서 테이블뷰 컨트롤러를 만들고, 네비게이션컨트롤러를 연결

테이블뷰의 Content 속성을 Static Cells로 설정

-  Static Cells타입의 테이블뷰는 스토리보드를 통해 설정됨, 일반 뷰컨트롤러에 일일이 넣는것보다 테이블뷰에서 Static Cells을 이용해 만드는 것이 좋다. !프로그래밍방식에서는 지원하지 않음.

테이블뷰 셀을  Custom을 설정 / 각각 다해줘야함

ListViewController.swift 클래스를 생성한다. 메인스토리보드와 연결

ListViewController.swift 와 메인스토리보드  IBOutlet연결, 성별,결혼여부 액션메소드 연결

전체코드

import UIKit

class ListViewController: UITableViewController {
    
    @IBOutlet weak var name: UILabel! // 이름

    @IBOutlet weak var gender: UISegmentedControl! //남여
    
    @IBOutlet weak var married: UISwitch! // 결혼여부
    
    // 테이블뷰셀을 선택했을때 호출되는 메소드
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // 이름 클릭시 알림창을 띄워서 이름을 수정할수 있게한다.
        if indexPath.row == 0 {
            //입력이 가능한 알림창을 띄워 이름을 수정할 수 있도록 한다.
            let alert = UIAlertController(title: nil, message: "이름을 입력하세요", preferredStyle: .alert)
            //입력필드 추가
            alert.addTextField(){
                $0.text = self.name.text //이름레이블의 텍스트를 입력폼에 기본값으로 넣어줌
            }
            //버튼 및 액션추가
            alert.addAction(UIAlertAction(title: "OK", style: .default) {(_) in
                //사용자가 ok버튼을 누르면 입력 필드에 입력된 값을 저장한다.
                let value = alert.textFields?[0].text
                let plist = UserDefaults.standard //기본저장소객체가져오기
                plist.setValue(value, forKey: "name")//이름이라는 키로 저장
                plist.synchronize() //동기화처리
                // 수정된 값을 이름 레이블에도 적용한다.
                self.name.text = value
            })
            // 알림창을 띄운다.
            self.present(alert, animated: false, completion: nil)
        }
    }
    // 성별 액션메소드 
    @IBAction func changeGender(_ sender: UISegmentedControl) {
        let value = sender.selectedSegmentIndex // 0이면 남자, 1이면 여자
        
        let plist = UserDefaults.standard //기본저장소 객체를 가져온다.
        plist.set(value, forKey: "gender")// 젠더라는 키로 값을 저장한다.
        plist.synchronize() //동기화처리
    }
    // 결혼여부 액션메소드 
    @IBAction func changeMarried(_ sender: UISwitch) {
        let value = sender.isOn //true면 기혼
        // UserDefaluts에 키값형태로 저장 후 동기화한다.
        let plist = UserDefaults.standard
        plist.set(value, forKey: "married")
        plist.synchronize()
    }
    
    // 화면이 처음로딩될때에만 저장소에서 값을 읽어와 컨트롤러에 설정한다.
    //저장된 데이터가져오기*************************************************************
    override func viewDidLoad() {
        let plist = UserDefaults.standard
        
        //지정된 값을 꺼내어 각 컨트롤에 설정한다.
        self.name.text = plist.string(forKey: "name")
        self.married.isOn = plist.bool(forKey: "married")
        self.gender.selectedSegmentIndex = plist.integer(forKey: "gender")
    }
}

viewDidLoad에  작성이유  - 화면이 처음 로딩될때만 저장소에서 값을 읽어와 컨트롤에 설정한다. 

그 이유는 사용자 정보는 현재의뷰 컨트롤러에서만 수정할 수 있다.

사용자 정보를 설정하면, 굳이 저장소에서 다시 데이터를 불러와 적용하는 과정을 거치지 않아도 설정 과정에서 컨트롤 및 이름 레이블에 설정값이 표시된다. 화면이 메모리에서 제거되었다가 다시 로딩될 때에는 저장소에서 데이터를 읽어올 것이고,메모리에서 제거되지 않으면 설정한 컨트롤 및 이름 레이블 상태가 그대로 유지될 것이다. 앱을 종료한뒤에 다시 켜도 데이터가 유지된다.

 


추가) 탭제스처로 액션 메소드 처리하기

이름을 탭하면 알림창이 뜨는 부분을 탭제스쳐로 변경해서 처리해보겠다.

탭제스처를 사용하면, 테이블뷰의 델리케이트 메소드를 이용하지 않고도 원하는 코드를 실행할 수 있다.

이름을 탭하면 팝업창이 뜨도록 하기위해 이름에다가 Tap Gesture...를 끌어다가 놓는다.

제스처를 추가하면 세번째에 제스처 아이콘이 생긴다.

ListViewController.swift 와 메인스토리보드에 추가한 제스쳐 액션메소드를 연결한다.

새로생긴 아이콘을 ctrl누르고 끌어서 생성한다.

import UIKit

class ListViewController: UITableViewController {
    
    @IBOutlet weak var name: UILabel!

    @IBOutlet weak var gender: UISegmentedControl!
    
    @IBOutlet weak var married: UISwitch!
    
    // 이름액션제스쳐 추가*****************************************************************
    @IBAction func edit(_ sender: UITapGestureRecognizer) {
        
        //입력이 가능한 알림창을 띄워 이름을 수정할 수 있도록 한다.
        let alert = UIAlertController(title: nil, message: "이름을 입력하세요", preferredStyle: .alert)
        //이름레이블의 텍스트를 입력폼에 기본값으로 넣어줌
        alert.addTextField(){
            $0.text = self.name.text
        }
        //사용자가 ok버튼을 누르면 입력 필드에 입력된 값을 저장한다.
        alert.addAction(UIAlertAction(title: "OK", style: .default){(_) in
            let value = alert.textFields?[0].text
            //기본저장소객체가져오기
            let plist = UserDefaults.standard
            plist.setValue(value, forKey: "name")//이름이라는 키로 저장
            plist.synchronize()//동기화처리
            // 수정된 값을 이름 레이블에도 적용한다.
            self.name.text = value
        })
        self.present(alert,animated: false, completion: nil)
    }
    
    // 테이블뷰셀을 선택했을때 호출되는 메소드
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
//        if indexPath.row == 0 {
//            //입력이 가능한 알림창을 띄워 이름을 수정할 수 있도록 한다.
//            let alert = UIAlertController(title: nil, message: "이름을 입력하세요", preferredStyle: .alert)
//            //입력필드 추가
//            alert.addTextField(){
//                $0.text = self.name.text //이름레이블의 텍스트를 입력폼에 기본값으로 넣어줌
//            }
//            //버튼 및 액션추가
//            alert.addAction(UIAlertAction(title: "OK", style: .default) {(_) in
//                //사용자가 ok버튼을 누르면 입력 필드에 입력된 값을 저장한다.
//                let value = alert.textFields?[0].text
//                let plist = UserDefaults.standard //기본저장소객체가져오기
//                plist.setValue(value, forKey: "name")//이름이라는 키로 저장
//                plist.synchronize() //동기화처리
//                // 수정된 값을 이름 레이블에도 적용한다.
//                self.name.text = value
//
//            })
//            // 알림창을 띄운다.
//            self.present(alert, animated: false, completion: nil)
//        }
    }

    @IBAction func changeGender(_ sender: UISegmentedControl) {
        let value = sender.selectedSegmentIndex // 0이면 남자, 1이면 여자
        
        let plist = UserDefaults.standard //기본저장소 객체를 가져온다.
        plist.set(value, forKey: "gender")// 젠더라는 키로 값을 저장한다.
        plist.synchronize() //동기화처리
    }

    @IBAction func changeMarried(_ sender: UISwitch) {
        let value = sender.isOn //true면 기혼
        
        let plist = UserDefaults.standard
        plist.set(value, forKey: "married")
        plist.synchronize()
    }
    
    //저장된 데이터가져오기
    override func viewDidLoad() {
        let plist = UserDefaults.standard
        
        //지정된 값을 꺼내어 각 컨트롤에 설정한다.
        self.name.text = plist.string(forKey: "name")
        self.married.isOn = plist.bool(forKey: "married")
        self.gender.selectedSegmentIndex = plist.integer(forKey: "gender")
    }
}

이름 누르고, 인터렉션 체크박스 체크해준다.

뷰는 기본적으로 사용자와 상호반응하지 않도록 설계되어 있따. 이를 상호반응이 가능하도록 재처리한것이 UIControl 클래스인데, UIControl 클래스를 상속받지 않은 일반뷰 객체가 제스처를 사용하려면 시스템에 알려주어야한다. User Interaction Enabled가 이것을 처리하는 옵션이다. 제스처 체크 꼭해주기!

제스처 액션메소드를 연결하고 안에 작성을 해주었으니, 테이블뷰에 작성했던 코드는 삭제해준다. 

반응형
Comments