iOS 내부의 파일에 접근하기 위해서 Swift 에서는 3가지 작업 클래스를 제공한다 해당 클래스를 이용하면 기기 내부에 파일에 접근하여 읽기, 수정, 삭제, 파일이동 등등 여러가지 작업이 가능하다 크게 3가지 클래스가 있지만 오늘 다뤄볼 클래스는 FileManager 클래스 이다.
클래스 종류
- FileManager - 파일 생성, 이동, 읽기, 쓰기, 삭제 및 파일 정보 가져오기 가능
- FileHandle - 지정된 바이트 청크 수만큼 내용을 읽고 쓰기 가능(?)
- Data - 파일 읽기, 저장 버퍼를 제공
FileHandle 의 경우 자세히 다뤄보지는 않았지만 조금 더 세세한 파일 컨트롤이 가능하다고 알고있다.
기기 디렉토리 경로
작업을 하기전에 기기의 디렉토리 경로를 알아보고 해당 경로에 접근하는 방법을 알아보자 우리는 시뮬레이터를 이용해서 작업을 할것이다.
시뮬레이터 기본경로
/Users/<user name>/Library/Developer/CoreSimulator/Devices/<device id>/data/Containers/Data/Application/<app id>/Documents
실제기기 기본경로
/var/mobile/Containers/Data/Application/<app id>/Documents
실제 시뮬레이터와 실제 기기의 경로는 다르다 시뮬레이터의 경우 내PC 내부에 Devices 라는 경로에서 기기마다 관리가 되고있다.
만약 디바이스 내부에 경로에 접근하고 싶다면 터미널을 실행시키고 cd 시뮬레이터 경로 를 입력해주면 된다.
FileManager
FileManager 클래스 생성
let fileManager = FileManager.default
fileManager를 생성해주자 default란 앱내에서 단일 인스턴스를 사용하는 것을 말한다.
현재 경로 가져오기
let currentPath = fileManager.currentDirectoryPath
현재 내가 위치한 디렉토리의 경로를 가져온다 처음 실행시 루트경로(/) 가 나타난다.
특정 경로 가져오기
let docsPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask)
document 경로를 가져올 수 있다. userDomainMast 란 현재 로그인한 유저를 의미한다.
let docsPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0].path
[URL] 형식으로 리턴되기 때문에 문자열로 변경을 원하는 경우 해당 방식으로 저장해준다.
디렉토리 목록 읽기
let currentPath = fileManager.currentDirectoryPath
do {
let files = try fileManager.contentsOfDirectory(atPath: currentPath)
for file in files.sorted() {
let filePath = currentPath + "/" + file
if let attribs: NSDictionary = try? fileManager.attributesOfItem(atPath: filePath) as NSDictionary,
let size = attribs["NSFileSize"] as? Int64 {
print("fileName: \(file) fileSize: \(size) bytes")
}
}
} catch {
print(error)
}
contentsOfDirectory(atPath: "경로 문자열") 를 입력해주면 입력된 경로의 파일목록을 반환한다 반환된 배열을 이용하여 현재 경로와 파일명을 조합하여 현재 파일의 이름과 파일 사이즈 등을 나열할 수 있다.
파일 생성
let destinationPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("datafile.dat").path
let text = "some text"
let databuffer = text.data(using: String.Encoding.utf8)
fileManager.createFile(atPath: destinationPath, contents: databuffer, attributes: nil)
데이터버퍼를 생성해준뒤 특정 경로에 데이터를 저장한다 appendingPathComponent 에는 파일의 경로 및 파일명을 써준다.
디렉토리 생성
do {
let destinationPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("Backup").path
try fileManager.createDirectory(atPath: destinationPath, withIntermediateDirectories: true)
} catch let error {
print("Error :\(error.localizedDescription)")
}
디렉토리를 만드느 경우 에러를 반환하기 때문에 do-catch 문에서 try를 이용해준다.
파일 복사 & 파일 확장자 확인
do {
let sourcePath = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0].path // 현재 로그인한 유저의 Document 경로 가져오기
let destinationPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("Backup").path
try fileManager.createDirectory(atPath: destinationPath, withIntermediateDirectories: true) // Backup 디렉토리 생성
let files = try fileManager.contentsOfDirectory(atPath: sourcePath)
for file in files {
let filePath = sourcePath + "/" + file
let fileExtension = (file as NSString).pathExtension.lowercased() // 파일 확장자 확인
if fileExtension == "dat" {
let destinationFile = destinationPath + "/" + file // Document/Backup/파일명
try fileManager.copyItem(atPath: filePath, toPath: destinationFile)
}
}
} catch {
}
copyItem(atPath:"원본파일 경로", toPath:"대상파일 경로") 를 이용하여 파일을 복사할 수 있다.
파일 데이터 읽기
let sourceFile = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("datafile.dat").path
do {
let data = Data(contentsof: URL(fileURLWithPath: sourceFile))
if let text = String(data: data, encoding: .utf8) {
print(text) // 파일의 데이터를 문자열로 출력
}
} catch {
}
파일 데이터 쓰기
let destinationFile = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("result.txt").path
do {
var myText = "myText"
// 문자열을 데이터 형식으로 변환
if let myTextData = myText.data(using: .utf8) {
try myTextData.write(to: URL(fileURLWithPath: destinationFile)) // 데이터저장
}
} catch {
}
FileManager를 이용하여 기기 내부에 File을 핸들하는 방법을 알아보았다 재밌기도 하면서 복잡한것 같다고 느껴졌다
시간이 나면 FileManager를 이용하여 시각적으로 파일들을 볼 수 있는 뷰어도 만들어볼까 생각중이다!!!
'iOS' 카테고리의 다른 글
SwiftUI 앱에서 Coordinator Pattern 적용하기 (0) | 2024.08.08 |
---|---|
[iOS/SwiftUI] firebase로 피드 데이터 가져오기 (1) | 2023.12.24 |
[SwiftUI] UIViewRepresentable을 이용하여 SwiftUI에서 UIKit 뷰 사용하기 (0) | 2023.12.16 |
[iOS/SwiftUI] @StateObject, @ObservedObject의 차이점 (1) | 2023.11.20 |