💡 백업 / 복구
개인 앱의 경우 개개인에게 백업 복구의 책임을 넘긴다.
개발자 → 기능만 제공, 백업 알아서,,
구글 드라이브, 드랍박스로 백업하기
→ 써드파티 프로그램의 정책으로 유지보수 비용이 높다
아이폰 파일 앱 사용하여 백업 복구하도록 하기
1. realm 파일 자체를 압축
마이그레이션 대응이 잘 되어야 한다.
사용자가 백업해두고 한참 뒤에 복구할 수 있기 때문
realm 파일을 복구할 때는 복구 완료 후 앱을 껐다 켜야 함
2. json으로 압축하기
다른 sql을 쓰더라도 대응하기 좋음
🔎 realm 파일 압축하기
- 백업하고자 하는 파일들의 경로 배열 생성
var urlPaths = [URL]()
- 도큐먼트 위치
guard let path = documentDirectoryPath() else {
print("도큐먼트 위치에 오류가 있습니다.")
return
}
- 백업하고자 하는 파일 경로 ex) ~
//~~~/Document/default.realm
let realmFile = path.appendingPathComponent("default.realm")
- 3번 경로가 유효한지 확인
guard FileManager.default.fileExists(atPath: realmFile.path) else {
print("백업할 파일이 없습니다.")
return
}
- 압축하고자 하는 파일을 배열에 추가
urlPaths.append(realmFile)
- 압축
압축 오픈소스
https://github.com/marmelroy/Zip
보안, 진행률 등 소스 사용할 수 있다
do {
let zipFilePath = try Zip.quickZipFiles(urlPaths, fileName: "JYArchive")
print("location: \(zipFilePath)")
} catch {
print("압축을 실패했어요")
}
💻 전체 코드
// 1. 백업하고자 하는 파일들의 경로 배열 생성
var urlPaths = [URL]()
// 2. 도큐먼트 위치
guard let path = documentDirectoryPath() else {
print("도큐먼트 위치에 오류가 있습니다.")
return
}
// 3. 백업하고자 하는 파일 경로 ex) ~~~/~~/~~~/Document/default.realm
let realmFile = path.appendingPathComponent("default.realm")
//4. 3번 경로가 유효한지 확인
guard FileManager.default.fileExists(atPath: realmFile.path) else {
print("백업할 파일이 없습니다.")
return
}
// 5. 압축하고자 하는 파일을 배열에 추가
urlPaths.append(realmFile)
// 6. 압축
do {
let zipFilePath = try Zip.quickZipFiles(urlPaths, fileName: "JYArchive")
print("location: \(zipFilePath)")
} catch {
print("압축을 실패했어요")
}
압축한 백업 파일 이름을 테이블 뷰에 보여준다.
🔎 복구하기
func fetchZipList() -> [String] {
var list: [String] = []
do {
guard let path = documentDirectoryPath() else { return list }
let docs = try FileManager.default.contentsOfDirectory(at: path, includingPropertiesForKeys: nil)
let zip = docs.filter { $0.pathExtension == "zip"}
for i in zip {
list.append(i.lastPathComponent)
}
} catch {
print("ERROR")
}
return list
}
💡 백업 파일을 아이폰 파일 앱에 저장하기
💡 앱 삭제 후 다시 빌드하여 복구하기
고려해볼 것
- 파일 없음
- 저장 공간
- 인디케이터 + 클릭 방지
- 복구 후 zip 파일 제거
- 선택한 앱의 구조와 맞는 zip 파일인지 체크
파일 앱에서 접근 할 파일의 확장자를 제한
✅ didPickDocumentsAt
파일 앱에서 선택한 파일로 복구하기
guard let selectedFileURL = urls.first else { // 파일 앱 내의 url 주소
print("선택한 파일에 오류가 있어요")
return
}
guard let path = documentDirectoryPath() else {
print("도큐먼트 위치에 오류가 있어요")
return
}
도큐먼트 폴더 내 저장할 경로 설정
let sandboxFileURL = path.appendingPathComponent(selectedFileURL.lastPathComponent)
~~~/~~~/document/default.realm
-> 최종 url 만들기
경로에 복구할 파일(zip)이 이미 있는지 확인
이미 파일이 있다면
경로에 복구 할 파일이 없을 때
💻 압축 해제 코드
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
guard let selectedFileURL = urls.first else { // 파일 앱 내의 url 주소
print("선택한 파일에 오류가 있어요")
return
}
guard let path = documentDirectoryPath() else {
print("도큐먼트 위치에 오류가 있어요")
return
}
// 도큐먼트 폴더 내 저장할 경로 설정
let sandboxFileURL = path.appendingPathComponent(selectedFileURL.lastPathComponent)
print(sandboxFileURL)
// 경로에 복구할 파일(zip)이 이미 있는지 확인
if FileManager.default.fileExists(atPath: sandboxFileURL.path) {
let fileURL = path.appendingPathComponent("JYArchive.zip")
do {
try Zip.unzipFile(fileURL, destination: path, overwrite: true, password: nil, progress: { progress in // 진행률
print("progress: \(progress)")
}, fileOutputHandler: { unzippedFile in // 압축 해제 완료
print("압축 해제 완료: \(unzippedFile)")
})
} catch {
print("압축 해제 실패")
}
} else {
// 경로에 복구할 파일이 없을 때의 대응
do {
try FileManager.default.copyItem(at: selectedFileURL, to: sandboxFileURL)
let fileURL = path.appendingPathComponent("JYArchive.zip")
try Zip.unzipFile(fileURL, destination: path, overwrite: true, password: nil, progress: { progress in // 진행률
print("progress: \(progress)")
}, fileOutputHandler: { unzippedFile in // 압축 해제 완료
print("압축 해제 완료: \(unzippedFile)")
})
} catch {
print("압축 해제 실패")
}
}
}
백업 버튼 누르면
~~/document/default.realm 파일을 압축하여 저장한다.
백업 파일은 같은 이름으로 설정하면 덮어쓰기된다.
- 복구해서 압축을 풀었으면 zip 파일을 제거해야 한다. zip 파일 삭제하지 않으면 계속 남게된다.
- 사용자가 아무 zip파일을 선택할 수 있다.
- 하지만 해당 앱과 구조가 다른 파일일 수 있다
- 압축 해제 후 파일 이름과 개수를 체크
'iOS > 🔎 swift 정리하기' 카테고리의 다른 글
MapKit CustomAnnotation (0) | 2023.10.10 |
---|---|
[iOS/Swift] MapKit - 원하는 곳에 어노테이션을 찍어보자 (0) | 2023.10.01 |
[iOS/Swift] Realm - Migration (0) | 2023.09.16 |
[iOS/Swift] Realm - 이미지 파일 저장하기 (0) | 2023.09.16 |
[iOS/Swift] Realm - CRUD (0) | 2023.09.16 |