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 라이센스를 따릅니다.