포스트

MapKit (10)

오래간만에 업로드

이번엔 LocationDetailView를 조금 더 보완한다.

Update Check-In Status

우선 열거형인 enum을 통해 checkin/out에 관한걸 만들어준다.

1
2
3
4
// LocationDetailViewModel
enum CheckInStatus {
    case checkedIn, checkedOut
}

이제 ViewModel에 Status를 업데이트하는 함수를 만들어준다.

1
2
3
4
5
func updateCheckInStatus(to checkinStatus: CheckInStatus) {
    // 1. Retrieve the DDGProfile
    // 2. Create a reference to the location
    // 3. Save the updated profile to CloudKit   
}

주석을 보면 알겠지만 3단계에 걸쳐서 업데이트를 하게된다.

CloudKitManager에서 변수를 하나 만들어준다. var profileRecordID: CKRecord.ID?

옵셔널인 이유는 프로필이 없는 경우도 있기 때문

이전에 유저레코드를 가져오는걸 했었다.

유저레코드가 존재한다면 굳이 새로 호출할 필요없이 여기서 바로 profileRecordID에 값을 부여하는 식으로 한다.

1
2
3
4
5
6
7
8
9
func getUserRecord() {
    CKContainer.default().fetchUserRecordID { recordID, error in
        // 생략
            
        if let profileReference = userRecord["userProfile"] as? CKRecord.Reference { // Added
            self.profileRecordID = profileReference.recordID
        }
    }
}

유져가 프로필을 새로 만들었을 경우엔 RecordID가 없으므로

ProfileViewModel에서 내용을 추가해준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// ProfileViewModel
func createProfile() {
    //생략
    
    showLoadingView()
    
    CloudKitManager.shared.batchSave(records: [userRecord, profileRecord]) { result in
        DispatchQueue.main.async { [self] in
            hideLoadingView()
            
            switch result {
            case .success(let records):
                for record in records where record.recordType == RecordType.profile {
                    existingProfileRecord = record
                    CloudKitManager.shared.profileRecordID = record.recordID // Added
                }
                alertItem = AlertContext.createProfileSuccess
            case .failure(_):
                // 생략
            }
        }   
    }
}

이제 LocationDetailViewModel로 가서 updateCheckInStatus 함수에 내용을 추가해주자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
func updateCheckInStatus(to checkinStatus: CheckInStatus) {
    // 1. Retrieve the DDGProfile
    
    guard let profileRecordID = CloudKitManager.shared.profileRecordID else {
        // show an alert
        return
    }
    
    CloudKitManager.shared.fetchRecord(with: profileRecordID) { [self] result in
        switch result {
        case .success(let record):
    // 2. Create a reference to the location
            switch checkinStatus {
            case .checkedIn:
                record[DDGProfile.kIsCheckedIn] = CKRecord.Reference(recordID: location.id, action: .none)
            case .checkedOut:
                record[DDGProfile.kIsCheckedIn] = nil
            }
            
    // 3. Save the updated profile to CloudKit
            CloudKitManager.shared.save(record: record) { result in
                switch result {
                case .success(_):
                    // update our checkedInProfile array
                    print("✅ checked In/Out Successfully")
                case .failure(_):
                    print("❌ Error saving record")
                }
            }
        case .failure(_):
            print("❌ Error fetching record")
        }
    }

}

우선은 프린트를 통해 제대로 되는지 안되는지를 확인하고, 이후에 Alert로 바꾸면 된다.

그리고

1
2
3
Button {
    viewModel.updateCheckInStatus(to: .checkedOut) // new
}

LocationDetailView에 해당 버튼을 눌렀을때 작동하게끔 이제 코드를 추가해준다.

Show Checked In Profiles

CloudKitManager에서 다음과 같이 함수를 만들어 준다.

해당함수는 체크인한 프로필들을 가져오는 역할을 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func getCheckedInProfiles(for locationID: CKRecord.ID, completed: @escaping (Result<[DDGProfile], Error>) -> Void) {
    let reference = CKRecord.Reference(recordID: locationID, action: .none)
    let predicate = NSPredicate(format: "isCheckedIn == %@", reference)
    let query = CKQuery(recordType: RecordType.profile, predicate: predicate)
    
    CKContainer.default().publicCloudDatabase.perform(query, inZoneWith: nil) { records, error in
        guard let records = records, error == nil else {
            completed(.failure(error!))
            return
        }
        
        let profiles = records.map { $0.convertToDDGProfile() }
        completed(.success(profiles))
    }
}

Github: Dub-Dub-Grub Repository

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.