포스트

MapKit (12)

Profile View Checked In/Out 구현

현재는 어떤 가게에 들어가야만 checked in/out에 대한 정보를 확인 할 수 있다. (설령 본인일지라도)

그래서 이제는 본인이 체크인을 했다면 프로필에서 체크인 상태를 확인 및 거기서도 체크 아웃할수있게 기능을 구현해본다.

버튼 디자인

우선 ProfileView에서 체크아웃 버튼을 디자인 해보도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
VStack(alignment: .leading, spacing: 8) {                
    HStack { // new
        CharactersRemainView(currentCount: viewModel.bio.count)
        Spacer()
        Button { // new
            
        } label: {
            Label("Check Out", systemImage: "mappin.and.ellipse")
                .font(.system(size: 12, weight: .semibold))
                .foregroundColor(.white)
                .padding(10)
                .frame(height: 28)
                .background(Color.grubRed)
                .cornerRadius(8)
        }
    }
}

우선 버튼을 하나 만들어 주었다. 버튼 디자인은 위와 같다.

그렇게해서 실행을 해보면

Image

이렇게 우측에 작게 체크아웃 버튼이 생긴걸 알 수 있다.

체크인/아웃시 버튼 다르게 하기

계속 체크아웃버튼만 나오게 할 수 없기에 유져의 체크인 상태를 확인하여 다르게 보이도록 한다.

우선 LocationDetailVM에있는 getCheckedInStatus 함수를 ProfileVM에 가져온다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func getCheckedInStatus() {
    guard let profileRecordID = CloudKitManager.shared.profileRecordID else { return }
    
    CloudKitManager.shared.fetchRecord(with: profileRecordID) { [self] result in
        DispatchQueue.main.async {
            switch result {
                case .success(let record):
                    if let _ = record[DDGProfile.kIsCheckedIn] as? CKRecord.Reference { // modifed
                        isCheckedIn = true // modifed
                    } else {
                        isCheckedIn = false // modifed
                    }
                case .failure(_):
                    break // modifed
            }
        }
    }
}

우선 isCheckedIn 부분을 기존의 방식에서 간단하게 바꾸었고, 그에따라 if let의 변수로 사용되었던 reference가 필요가 없어졌으므로 _로 바꿔주었다.

현재 failure 부분은 break로 간단하게 처리해둔상태

그리고 onAppear 부분에 뷰가 렌더링 될때마다 상태를 확인하도록하기 위헤 코드를 추가한다.

1
2
3
4
.onAppear {
    viewModel.getProfile()
    viewModel.getCheckedInStatus() // new
}

그리고 체크인 상태일때 버튼이 보여져야 하기에

1
2
3
4
5
6
7
if viewModel.isCheckedIn {
    Button {
        
    } label: {
        // 생략
    }
}

이렇게 if로 감싸준다.

우선 이렇게하고 실행하여 체크인 버튼이 보이는지 확인해보도록 한다.

Image

우선 잘 되는걸 알 수 있다.

Profile에서 체크아웃 구현

이제 굳이 해당 가게로 가서 체크아웃을 하는게 아닌, 프로필에서 바로 체크아웃을 구현해보도록 한다.

먼저 profilevm에서 해당 기능을 담당할 함수를 만들어보도록 한다.

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
func checkOut() {
    guard let profileID = CloudKitManager.shared.profileRecordID else {
        alertItem = AlertContext.unableToGetProfile
        return
    }
    
    CloudKitManager.shared.fetchRecord(with: profileID) { result in
        switch result {
        case .success(let record):
            record[DDGProfile.kIsCheckedIn] = nil
            
            CloudKitManager.shared.save(record: record) { [self] result in
                DispatchQueue.main.async {
                    switch result {
                    case .success(_):
                        isCheckedIn = false
                    case .failure(_):
                        alertItem = AlertContext.unableToCheckInOrOut
                    }
                }
            }
            
        case .failure(_):
            DispatchQueue.main.async {
                self.alertItem = AlertContext.unableToCheckInOrOut
            }
        }
    }
}

매커니즘은 간단하다 먼저 profileID를 가져오고 해당 id에 한해서 레코드를 조회하여 checkedin에 대한 값을 없애주고(클라우드), 이후 앱 내에서 해당 유저의 ischeckedIn 상태에 대해 변경을 해주는 것 이다.

이때 alert가 MainThread에서 작동해야 하므로 DispatchQueue를 사용해주었다.

다시 버튼에서 구현한 체크아웃 기능을 달아준다.

1
2
3
Button {
    viewModel.checkOut()
}

이제 실행을 해보면

Image

체크아웃이 되는걸 알 수 있다.


Github: Dub-Dub-Grub Repository

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