(Swift) Device 내부 Document에 image 저장, 불러오기, 삭제하기

Hanulyun
6 min readFeb 24, 2020

--

  • Swift 5 기준

일반 메모나 할일 앱처럼 Device 내부에 이미지를 저장하고 불러와 사용할 때가 있죠. 싱글톤을 활용해 간편하게 사용할 수 있는 방법을 공유합니다.

Save Image

우선 ImageFileManager 라는 class 를 만들어서 싱글톤으로 활용해요. 그리고나서 Device Document에 이미지를 저장해볼게요.

class ImageFileManager {
static let shared: ImageFileManager = ImageFileManager()
// Save Image
// name: ImageName
func saveImage(image: UIImage, name: String,
onSuccess: @escaping ((Bool) -> Void)) {
guard let data: Data
= image.jpegData(compressionQuality: 1)
?? image.pngData() else { return }
if let directory: NSURL =
try? FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false) as NSURL {
do {
try data.write(to: directory.appendingPathComponent(name)!)
onSuccess(true)
} catch let error as NSError {
print("Could not saveImage🥺: \(error), \(error.userInfo)")
onSuccess(false)
}
}
}
}

사용방법은 아래와 같아요. Image File Name 을 매번 지정해줄 수 없으니까 간편한 방법으로 unique name을 만들어 줄 수 있는 코드를 쓸거예요.

// UniqueName.jpeg
let uniqueFileName: String
= "(ProcessInfo.processInfo.globallyUniqueString).jpeg"
ImageFileManager.shared
.saveImage(image: image,
name: uniqueFileName) { [weak self] onSuccess in
print("saveImage onSuccess: \(onSuccess)")
}

onSuccess 일 때 이후에 필요한 처리를 해주면 되겠죠? 이후에 저장된 이미지를 불러오려면 저장할 때 사용했던 uniqueFileName 를 알고 있어야해요.

Get Image

그럼 저장했던 image를 불러오는 코드를 알아볼게요. ImageFileManager 에 계속해서 아래 코드를 추가해요.

// named: 저장할 때 지정했던 uniqueFileName 
func getSavedImage(named: String) -> UIImage? {
if let dir: URL
= try? FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false) {
let path: String
= URL(fileURLWithPath: dir.absoluteString)
.appendingPathComponent(named).path
let image: UIImage? = UIImage(contentsOfFile: path)

return image
}
return nil
}

그럼 가져온 이미지를 보여줄 수 있는 샘플 코드를 볼게요.

if let image: UIImage 
= ImageFileManager.shared.getSavedImage(named: "fileName") {
imageView.image = image
}

image를 저장하고, 가져오기까지 했으니 이제 삭제 해 볼까요?

Delete Image

Delete 도 마찬가지로 imageName을 알고 있어야해요. ImageFileManager 에 아래 코드를 추가할게요. document에서 해당 fileName이 있는지 확인하고, 있으면 삭제하는 로직이예요.

func deleteImage(named: String, 
onSuccess: @escaping ((Bool) -> Void)) {
guard let directory =
try? FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false) as NSURL
else { return }
do {
if let docuPath = directory.path {
let fileNames = try
FileManager.default.contentsOfDirectory(atPath: docuPath)
for fileName in fileNames {
if fileName == named {
let filePathName = "\(docuPath)/\(fileName)"
try FileManager.default.removeItem(atPath: filePathName)
onSuccess(true)
return
}
}
}
} catch let error as NSError {
print("Could not deleteImage🥺: \(error), \(error.userInfo)")
onSuccess(false)
}
}

그럼 아래처럼 delete가 잘 되는지 테스트해볼게요.

ImageFileManager.shared.deleteImage(named: url) { onSuccess in
print("delete = \(onSuccess)")
}

참 쉽죠? 🙆‍♀️

Conclusion

이제껏 만들었던 앱은 항상 이미지를 서버에 보내고, 서버에서 url을 받아와 보여주는 형태였기 때문에 내부 document에 이미지를 저장하고, 불러오는걸 공부해봤어요.

유틸리티 앱에서는 이것보다 파일을 관리하는 더 좋은 방법이 있을 수 있을 것 같아서 개발하게되면 공부를 더 해보려고 합니다. 😃

Github: https://github.com/hanulyun/ImageFileManager

--

--

Hanulyun
Hanulyun

Written by Hanulyun

iOS 주니어 개발자입니다. 개발하면서 막히는 부분을 해결한 후 기록으로 남깁니다. #Swift