[SwiftUI] CloudKit: Images & Assets

Junyoung Park·2022년 8월 24일
0

SwiftUI

목록 보기
51/136
post-thumbnail
post-custom-banner

Upload images and CKAssets to CloudKit | Advanced Learning #23

CloudKit: Images & Assets

구현 목표

  • 이미지 저장을 위한 CKAsset 이용 → FileManager URL

구현 태스크


1. 이미지, 오디오 등 바이너리 데이터를 클라우드 데이터 내에 저장
2. 데이터 직접 저장 불가능 → 파일 매니저의 캐시 디렉토리 저장 및 해당 URL에 접근하는 CKAsset을 통해 접근

소스 코드

struct FruitModel: Identifiable {
    let id = UUID().uuidString
    let name: String
    let imageURL: URL?
    let record: CKRecord
}
  • 이미지 저장을 위한 프로퍼티 imageURLURL? 타입으로 추가
  • CAAsset 사용되는 URL
    private func addItem(name: String) {
        let newFruit = CKRecord(recordType: "Fruits")
        newFruit["name"] = name
        
        guard
            let image = UIImage(named: "peach"),
            let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first?.appendingPathComponent("peach.png"),
            let data = image.pngData() else { return }
        do {
            try data.write(to: url)
            let asset = CKAsset(fileURL: url)
            newFruit["image"] = asset
            saveItem(record: newFruit)
        } catch {
            print(error.localizedDescription)
        }
    }
  • 파일 매니저 캐시 디렉토리 URL을 통해 CKAsset 확보
            queryOperation.recordMatchedBlock = { (returnedRecordId, returnedResult) in
                switch returnedResult {
                case .success(let record):
                    guard let name = record["name"] as? String else { return }
                    let imageAsset = record["image"] as? CKAsset
                    let imageURL = imageAsset?.fileURL
                    returnedItems.append(FruitModel(name: name, imageURL: imageURL, record: record))
                    print(name)
                    break
                case .failure(let error):
                    print(error.localizedDescription)
                }
            }
  • URL 통한 이미지 어셋 접근
List {
                    ForEach(viewModel.fruits) { fruit in
                        HStack {
                            Text(fruit.name)
                                .font(.headline)
                                .fontWeight(.semibold)
                            Spacer()
                            if let url = fruit.imageURL, let data = try? Data(contentsOf: url), let image = UIImage(data: data) {
                                Image(uiImage: image)
                                    .resizable()
                                    .scaledToFit()
                                    .frame(width: 50, height: 50)
                            }
                        }
                        .contentShape(Rectangle())
                        .onTapGesture {
                            viewModel.selectedFruit = fruit
                            viewModel.isUpdatingItem = true
                        }
                    }
                    .onDelete(perform: viewModel.deleteItem)
                }
                .listStyle(.plain)
  • UI 뷰의 아이템을 보여주는 리스트 뷰
  • 이미지 URL을 통해 데이터 패치

구현 화면

profile
JUST DO IT
post-custom-banner

0개의 댓글