TIL

[Sesac IOS] 38일차 TIL

Leaned

Realm DB 백업

1) .realm 파일 자체를  백업

  • 앱에서 사용하는 DB 파일의 스키마와 복구할 파일의 스키마가 동일할 때
    단순히 파일을 교체하여 쉽게 백업 및 복구가 가능함.
  • 하지만 사용자의 앱 버전마다 스키마가 다를 경우 사용하는 DB의 구조가
    각각 다르기 때문에 복구 시 충돌이 발생할 수 있음.
  • 또한 백업한 데이터를 Realm이 아닌 데이터베이스에서 사용하기 어렵다는 단점이 있음.

2) Json으로 변환하여 백업

  • 마이그레이션, 스키마 업데이트 등 DB 구조 변화에 유연하게 대응할 수 있으며
    Realm외에 다른 데이터베이스 또는 다른 플랫폼에서 비교적 사용하기 편리함.
  • 단, 개발 시간이 늘어날 수 있다는 단점이 있음.

파일 앱을 활용한 백업 및 복구

  • Zip 라이브러리를 사용해서 백업할 파일 압축 및 파일 앱에 저장
func zipFiles(targetToZip paths: [DesignatedPath]) {
    
    guard let documentURL = getDocumentDirectory() else { return }
    
    let paths = paths.map{ documentURL.appendingPathComponet(pathComponent: $0) }.filter { FileManager.default.fileExists(atPath: $0.path) }
    
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
    
    let fileName = dateFormatter.string(from: Date())
    
    let destinationPath = documentURL.appendingPathComponet(pathComponent: .zipFilePath(fileName: fileName))
    
    do {
        // 모달 dragToDown 제스처 막기
        self.isModalInPresentation = true
        
        try Zip.zipFiles(paths: paths, zipFilePath: destinationPath, password: nil) { progress in print(progress) }
        
        // UIActivityViewController로 파일 앱에 저장하거나 이메일로 전송 등
        let vc = UIActivityViewController(activityItems: [destinationPath], applicationActivities: nil)
        
        self.present(vc,animated: true)
        
        self.isModalInPresentation = false

    } catch { self.isModalInPresentation = false }
}
  • UIDocumentPickerViewController를 사용한 복구
// 파일 앱에서 zip파일만 보이게 설정
let vc = UIDocumentPickerViewController(forOpeningContentTypes: [.archive], asCopy: true)

vc.delegate = self

present(vc, animated: true)
// UIDocumentPickerDelegate 메서드
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        
        // 파일 앱에서 선택한 파일의 URL
        guard let src = urls.first else {
            showAlert(title: "선택한 파일의 경로를 찾을 수 없습니다.")
            return
        }
        // 저장할 디렉토리 경로
        guard let documentURL = getDocumentDirectory() else {
            showAlert(title: "저장할 디렉토리의 경로를 찾을 수 없습니다.")
            return
        }
        
        // 저장할 파일 이름을 포함한 전체 URL
        let dst = documentURL.appendingPathComponent(src.lastPathComponent)
        
        if FileManager.default.fileExists(atPath: dst.path) {
            showAlert(title: "같은 이름의 파일이 존재합니다.", message: "삭제 후 다시 시도해주세요")
            return
        } else {
            do {
                try FileManager.default.copyItem(at: src, to: dst)
                showAlert(title: "파일 가져오기 성공", message: "백업 파일을 선택해주세요")
                fetchFilesInDocument()
            } catch {
                showAlert(title: "파일 가져오기 실패")
            }
        }
        
    }
  • URL 객체로 파일 크기, 생성 날짜 얻기
// UITableViewCell Method
func configureCellWithURLResources(url: URL) {
        
        var config = self.defaultContentConfiguration()
        
        do {
            
            let resource = try url.resourceValues(forKeys: [.creationDateKey, .fileSizeKey, .volumeAvailableCapacityForImportantUsageKey])
            
            let sizeString = String(format: "%.2f", Double(resource.fileSize ?? 0) / pow(10, 6))
            let date = resource.creationDate
            let dateString = date?.formatted(date: .abbreviated, time: .shortened)
            
            config.secondaryText = "\(sizeString)MB / \(dateString ?? "")"
            
        } catch {
            print(error)
        }
        
                
        config.text = url.lastPathComponent
        config.image = .init(systemName: "folder.fill")
        
        self.contentConfiguration = config
        
    }
  • 디렉토리 URL로 저장 가능한 공간 확인하기
guard let documentURL = getDocumentDirectory() else {
    showAlert(title: "파일이 저장된 경로를 찾을 수 없습니다")
    return
}

do {
    
    let resource = try documentURL.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey])
    
    print(resource.volumeAvailableCapacityForImportantUsage)
    
} catch {
    print(error)
}

 


이상입니다.

참고 자료 : https://developer.apple.com/documentation/foundation/urlresourcekey/checking_volume_storage_capacity

 

Apple Developer Documentation

 

developer.apple.com

 

'TIL' 카테고리의 다른 글

[Sesac IOS] 40일차 TIL  (0) 2022.08.31
[Sesac IOS] 39일차 TIL  (0) 2022.08.29
[Sesac IOS] 37일차 TIL  (0) 2022.08.25
[Sesac IOS] 36일차 TIL  (0) 2022.08.24
[Sesac IOS] 34~35일차 TIL  (0) 2022.08.22