나의 발자취

[iOS] 로컬에 데이터를 저장하는 PList 본문

앱 개발/iOS

[iOS] 로컬에 데이터를 저장하는 PList

달모드 2024. 10. 21. 12:47

새롭게 Property List 파일을 생성한다.

 

 

클릭해서 보면, Root 는 Dictionary로 되어있다. 이걸 Array로 바꾼다. (왜냐하면 최종적으로 보여지는 데이터 포맷은 array여야 하므로)

 

하위 경로에 생성될 데이터는 한 인물에 대한 정보이므로, Dictionary type으로 바꿔준다.

 

 

상세 데이터를 정의해주고, Cmd+C/ V 를 해준다.

 

 

 

이렇게 뷰도 만들어준다.

 

코코아 터치클래스 만들고 연결해주기.

데이터는 plist에 담겨있다. 이제 Bundle이라는 것을 만들게 되는데, 우리가 만드는 bts.plist, image 같은 것들을 하나로 모아서 zip 파일로 만든다. 그 이후 샌드박스에다가 복사를 해서 그것을 실행을 하게 된다.

그럼 우리가 만든 plist는 번들 안에 담기게 되는데, 번들에서 그것을 가져와야 한다. 그 작업을 해볼 것이다.

 

iOS의 디렉토리 구조를 보게 되면, 아래와 같이 되어있다.

iOS는, 보안상으로 같은 앱을 폴더이름을 모르게 (정수 및 해싱된 이름으로?) 생성한다. 그래서 유저마다 폴더명이 다를것이다.

어쨌든, 이 다른 폴더를 런타임때 읽어와야한다.

 

 

Bundle Container에 번들이 담기고, Data Container에 필요한 내용들이 저장된다. iCloud는 안할것

어쨌든 이 세 디렉토리가 다 한군데에 모여있는 것이 아니다.

 

MainTableViewController에 가서, 번들을 만들어줄것이다.

viewDidLoad() 아래에 번들을 정의해준다.

 

번들은 일반적으로 하나지만, 번들을 나눠줄 수 있다. 

이 코드는 번들 중에 메인 번들을 찾는 것이다.

 

그리고 만들었던 plist를 찾을 수 있도록 헤주는데, 보통은 첫번째거를 많이 사용한다.

 

번들URL을 찍어보자.

 

이와 같이 나온다. 이 경로가 의미하는 것은?

 

 

Optional(file:///Users/lia/Library/Developer/CoreSimulator/Devices/C1BDEEF7-D4C4-46C1-A421-A347FD940093/data/Containers/Bundle/Application/FC2393F2-4F64-4D0E-9140-6A96D8C1E3A8/PListTest.app/bts.plist)

 

 

맥에 깔려있는 시뮬레이터의 경로

디바이스(시뮬레이터)의 이름

3개(번들, 데이터, iCLoud) 의 컨테이너 중 하나인, Bundle Container

IDFA

번들

을 의미한다. 아까 유저별로 경로가 다 다르다고 했는데...

 

이 모든 경로를 다 복사해서, 파인더 

 

 

 

 

엔터를 하면, 여기에 경로가 생긴것을 볼 수 있다.

 

 

아까 root를 Array로 설정했었다. 그러나 Swift에서 제공하는 기본 Array는 고급 기능이 없어서, 우리가 필요한 기능이 있는 NSArray 프레임워크를 쓸 것이다. NSMutableArray와 NSArray가 있는데, 기본 Array는 let / var로 선언했지만, NS~~~의 경우에는 unmutable는 성능이 더 좋다. 따라서 꼭 필요한거는 mutable을 쓰고 아닌건 기본적으로 다 unmutable를 써준다.

 

guard처리를 해주었고,

fileManager선언을 해준다. fileManager는 클래스 이름인데, FileManager.default라고 하면 fileManager에 인스턴스가 있으면 걔로 하고, 없으면 새로 만들어서 주라는 싱글톤 객체이다. 하나의 인스턴스만을 생성한다는 것이다.

 

 

다시 돌아가서 일전에 얘기했던 NSArray를 쓸건데, 보면 throws가 있다 -> 예외처리를 해줘야한다. (try-catch)

참고로, 하드웨어에 접근하는 것들은 모두 예외처리를 해주어야 한다! 

do {
            let bts = try NSArray(contentsOf: bundleURL, error: <#T##()#>)
        } catch {
            print("PList 읽기 오류")
        }

 

 

 

왜 imageName는 옵셔널 해제를 하고 넣고, 나머지는 그냥 했을까?

member["image"]는 타입이 UIImage? 이지만,

 

 

그럼, 이제 도큐먼트 폴더에 접근해서 데이터를 수정하는 것을 할 수 있는 작업을 할것이다.

도큐먼트 폴더는 데이터 컨테이너 폴더 안에 있다.

 

새로운 Utils.swift 파일을 생성하고, 여기에 파일명을 넘겨주면 해당 파일이 존재하는 도큐먼트 URL을 반환해주는 함수를 구현해줄것이다.

 

 

for: 어떤 경로인지?

in: 누가 쓰는것인지? (시스템이? / 사용자가?)

 

만약 allDomainsMask를 하면, documentsDirectory를 다 가져오는 것이다.

지금과 같이 선언하면, 이 경로는 하나밖에 없게 된다.

그렇기 때문에 ducomentsURLs[0]으로 바로 가져올 수 있게 된다.

 

PathComponent: 경로를 구분할 때의 컴포넌트(맥에서는 /, 윈도우에서는 \를 쓴다. )

 

 

NSArray를 NSMutableArray로 바꿔준다.

그리고, 

번들은 딱 한번만 복사를 실행할건데, 도큐먼트 폴더에 없으면 복사를 하는거고 있으면 하면 안된다.

따라서 아래와 같이 선언을 해주고, 디버깅을 위해 targetURL을 출력해준다.

 

 

아까와는 달리, Bundle의 자리에 Data가 온 것을 알 수 있다.

 

여기까지의 이름만 복사해서, 파인더 Go 메뉴를 통해 해당 폴더로 가기를 해준다.

그리고, 계층적으로 보기 위해 View > as Columns로 보면 아래와 같이 나온다.

현실적으로 번들에서 바로 쓸 일은 없다. 

 

 


여기에서, 데이터와 테이블 row 수가 안맞으면 앱이 터지기 때문에 시뮬레이션 뷰에서 데이터를 삭제하면, 실제 데이터도 삭제를 해주는 작업을 여기서도 해준다.

Comments