본문 바로가기

iOS/왈

[WAL] 왈소리 온 거 다 읽었는데 도착 왈뿡이가 떠요

728x90

제목이 이게 뭐죠? 할 수 있는데 .. 왈 메인 화면을 만들 때 그리고 QA를 할 때 가장 .. 고민을 많이 한 부분이라 한번 기록을 해볼까 .. 한다 .. 절대로 니카내카하다가 토나와서 넘어온거 아니다. 

 

 

왈 메인 화면에서 사용자가 선택한 왈소리 유형, 시간대에 해당하는 왈소리가 랜덤으로 오게 되는데, 사용자별로 받게 되는 왈소리 개수도 다르고, 날마다 변하며, 그 중에는 사용자가 본인에게 보내는 왈소리도 있다.

 

그리고 시간대에 따라서, 왈소리를 읽은 여부에 따라서 다른 왈뿡이 캐릭터 및 텍스트가 보여야 하므로 그 때마다 UI를 분기처리 해야 한다. 

-> 여기까지가 메인에서 신경써야 하는 주요 로직이었다.

 

 

생각한 로직에 따라서 코드를 작성했고 나름 잘 로직을 분리했다고 생각했는데 .. 놓친 부분이 있었다. 바로 메인에 진입할 때가 아니라 사용자가 계속 메인에서 왈소리를 읽고 확인한 후에도 읽은 것에 대한 분기처리로 왈뿡이가 바뀌어야 한다는 것이었다. ⬇️

 

 

 

왈 메인 화면에서 왼쪽 이미지와 같이 왈소리가 오다가, 만약 왈소리를 모두 다 읽게 되면 오른쪽과 같이 도착 왈뿡이(그리고 도착 텍스트)로 바뀌어야 하는데 변하지 않는 이슈가 있었다.

 

 

 

그래서 생각한 로직은 다음과 같다. 

✔️ 사용자가 현재 읽을 수 있는 왈소리인가 (시간대에 맞는지 확인)

✔️ 사용자가 봤던 왈소리인가 (현재 읽을 왈소리가 남아 있는지, 다 도착한 것인지 등을 확인)

를 확인하기 위해 canOpen / isShown 프로퍼티를 통해 각 상황에 따라 분기처리를 했다.

 

예를 들어서 오늘 도착해야 하는 왈소리가 아침/점심/저녁 왈소리 한개씩 총 3개일 때,

점심이 지나고 저녁 전에 앱에 진입한 경우,

확인할 수 있는 왈소리는 총 2개이고 아직 하나도 확인하지 않았기 때문에 '확인해보세요' 왈뿡이가 나와야 한다.

 

각 왈소리 타입에 대해서 다른 왈뿡이가 나온 뒤,

다시 메인으로 왔을 때, 아직 오늘 올 왈소리를 모두 확인하 것이 아니기에 아직까지는 '확인해보세요' 왈뿡이가 나온다.

 

그리고 저녁 시간대가 지나서 앱을 실행하고 마저 도착한 왈소리를 모두 읽으면

그 때는 읽고 나서 바로 '오늘 왈소리가 전부 도착했어요' 왈뿡이가 나와야 한다. 

 

 

이런 상황을 모두 고려해서 데이터를 관리해야 한다.

이 때 나타날 수 있는 상황을 위에서 말한 세가지 고려사항을 바탕으로 분기처리하면 된다.

  1. 현재 확인할 수 있는 왈소리가 있는가
  2. 현재 시간이 언제인가
  3. 사용자가 본 왈소리의 개수는 몇개인가 

 

 

 

 

서버에서 넘겨주는 응답 데이터를 바탕으로 볼 수 있는 데이터, 본 데이터, 그리고 현재 사용자가 앱을 사용하고 있는 시간대에 따라 분기처리를 하면 다음과 같다. 

 

참고로, 왈뿡이의 상황에 따른 타입은 따로 열거형으로 관리했다.

WALStatus.swift 

enum WALStatus {
    case sleeping
    case arrived
    case checkedAvailable
    case checkedAll
    
    var subTitle: String {
        switch self {
        case .sleeping:
            return "왈뿡이가 자는 시간이에요. 아침에 만나요!"
        case .arrived, .checkedAvailable, .checkedAll:
            return "다들 밥 잘 먹어! 난 뼈다구가 젤루 좋아"
        }
    }
    
    var content: String {
        switch self {
        case .sleeping:
            return ""
        case .arrived:
            return "왈소리가 도착했어요\n발바닥을 눌러 확인해주세요"
        case .checkedAvailable:
            return "왈소리가 열심히 달려오고 있어요"
        case .checkedAll:
            return "오늘의 왈소리가 전부 도착했어요"
        }
    }
    
    var walImage: UIImage {
        switch self {
        case .sleeping:
            return WALIcon.imgWalBBongSleeping.image
        case .checkedAll, .checkedAvailable:
            return WALIcon.imgWalBBongWaiting.image
        case .arrived:
            let walArrivedImageList: [UIImage] = [WALIcon.imgWalBBongArrive1.image,
                                                  WALIcon.imgWalBBongArrive2.image,
                                                  WALIcon.imgWalBBongArrive3.image]
            return walArrivedImageList.randomElement() ?? WALIcon.imgWalBBongArrive1.image
        }
    }
}

 

✅ 왈뿡이가 자고 있는 상태 (오전 12시부터 오전 8시까지)

 

✅ 왈소리가 도착했고, 확인할 수 있는 왈소리가 없을 때

-> 시간을 확인해서 오전 12시부터 오전 8시 사이라면 -> 자고 있는 상태

-> 그 외의 시간이라면 -> 아직 오는 중 (= "왈소리가 오는 중이에요")  

 

✅ 왈소리가 도착했고, 확인 할 수 있는 왈소리가 있을 때 아직 다 확인하지 않은 경우 

-> "왈소리가 도착했어요 발바닥을 눌러 확인해주세요" 

 

✅ 왈소리가 도착했고, 확인할 왈소리가 있을 때 모두 확인한 경우 

-> 오늘 와야 하는 총 왈소리의 개수와 확인한 왈소리가 같다면, 오늘의 왈소리는 다 읽었으므로 -> "오늘의 왈소리가 전부 도착했어요"

-> 오늘 와야 하는 총 왈소리의 개수보다 적다면, 아직 남았으므로 -> "왈소리가 오는 중이에요"

 

 

메인에 진입할 때 전체 왈소리의 개수, 확인할 수 있는 왈소리의 개수, 확인한 왈소리의 개수, 현재 시간대 등을 고려하면 아래와 같다.

    func getMainInfo() {
        MainAPI.shared.getMainData { mainData, err in
            guard let mainData = mainData else {
                return
            }
            
            DispatchQueue.main.async {
                guard let data = mainData.data else { return }
                self.mainData = data
                self.dataCount = data.count
                
                self.walCollectionView.reloadData()
                self.updateCollectionViewLayout()
                
                // 현재 볼 수 있는 개수와 이미 확인한 개수를 변수로 관리 한다.
                var isShownCount: Int = 0
                var canOpenCount: Int = 0
                
                // 메인 데이터의 아이템을 하나씩 꺼내서 
                for item in self.mainData {
                    // 이미 본 것과 
                    if item.isShown {
                        isShownCount += 1
                    }
                    // 확인할 수 있는 왈소리의 개수를 센다.
                    if item.canOpen {
                        canOpenCount += 1
                    }
                }
                
                // 만약 현재 확인할 수 있는 왈소리가 없다면, 그것은 두 가지 경우를 의미한다. 
                if canOpenCount == 0 {
                    let stringDate = self.dateFormatter.string(from: self.date)
                    guard let intDate = Int(stringDate) else { return }
                    // 만약 사용자가 따로 설정한 시간대가 아니라면 오전 12시부터 오전 8시까지는 
                    if intDate >= 0 && intDate <= 7 {
                        왈뿡이가 자고 있다.
                        self.walStatus = .sleeping
                    } else {
                        // 또는 점심,저녁을 신청한 사용자의 경우 아침에는 확인할 수 없다.
                        // 이런 경우에는 새로운 왈소리를 기다려야 하는 상황이므로 "왈소리가 열심히 달려오고 있어요"가 나와야 한다.
                        self.walStatus = .checkedAvailable
                    }
                } else {
                    // 만약 확인할 수 있는 왈소리가 있을 경우,
                    // 사용자가 확인한 왈소리와 확인할 수 있는 왈소리가 같을 때 두가지 경우가 있다. 
                    if isShownCount == canOpenCount {
                        // 만약 오늘 와야 하는 왈소리를 모두 읽은 경우라면 
                        if isShownCount == self.dataCount {
                            // 다 읽은 상태로 처리하고 
                            self.walStatus = .checkedAll
                        } else {
                            // 현재 점심 왈소리까지만 읽을 수 있을 때, 즉 저녁 왈소리는 아직 읽을 수 있는 상황이 아닐 경우,
                            // 점심 왈소리까지 읽었다면 아직 도착할 왈소리가 남아 있으므로 "왈소리가 열심히 달려오고 있어요"가 나와야 한다.
                            self.walStatus = .checkedAvailable
                        }
                    } else {
                        // 만약 사용자가 볼 수 있는 왈소리와 본 왈소리가 다르다는 것은 아직 덜 확인했다는 것이므로, 왈소리를 확인해보라는 문구가 나와야 한다. 
                        self.walStatus = .arrived
                    }
                }
            }
        }
    }

 

 

🟢 그리고 이 때 주의할 점이 있다.

(-> 이 부분이 제목 QA에 대한 해결방법이다.)

 

왈소리를 확인하기 위해 발바닥을 탭하고 다시 탭하면 메인으로 돌아오는데, 이 때 ViewController가 전환되는 것이 아니므로 위의 getMainInfo() 메서드가 호출되지 않아, 확인한 것에 대해서 갱신이 되지 않는다.

즉, 오늘 총 왈소리가 3개이고, 저녁 시간대가 지나서 모두 확인이 가능한 상태일 때, 모든 왈소리를 읽고 나면 메인 화면에서도 바로 (따로 앱을 끄고 다시 실행하거나 다른 화면을 갔다가 들어오지 않아도) 도착 왈뿡이(= 새로운 왈소리를 기다려보세요)가 아니라 모두 확인 왈뿡이(=오늘 왈소리를 다 읽었어요)가 나타나야 한다. 

 

 

그러므로 왈소리를 확인할 때,

즉 발바닥을 탭할 때마다 서버 통신을 해서 isShown을 false에서 true로 바꿔주도록 하고, 이 때 응답 데이터로 메시지만 받는 것이 아니라 데이터를 다시 받아서 위의 분기처리를 진행하고 상태를 업데이트 해주면 된다. 

 

    private func updateMainData(item: Int) {
        MainAPI.shared.updateMainData(item: self.mainData[item].id) { mainData, error in
            guard let mainData = mainData else { return }
            guard let data = mainData.data else { return }
            
            self.mainData = data
            self.dataCount = data.count
            
            DispatchQueue.main.async {
                var isShownCount: Int = 0
                var canOpenCount: Int = 0
                
                for item in self.mainData {
                    if item.isShown {
                        isShownCount += 1
                    }
                    
                    if item.canOpen {
                        canOpenCount += 1
                    }
                }
                
                if canOpenCount == 0 {
                    let stringDate = self.dateFormatter.string(from: self.date)
                    guard let intDate = Int(stringDate) else { return }
                    
                    if intDate >= 0 && intDate <= 7 {
                        self.walStatus = .sleeping
                    } else {
                        self.walStatus = .checkedAvailable
                    }
                } else {
                    if isShownCount == canOpenCount {
                        if isShownCount == self.dataCount {
                            self.walStatus = .checkedAll
                        } else {
                            self.walStatus = .checkedAvailable
                        }
                    } else {
                        self.walStatus = .arrived
                    }
                }
            }
            
        }
    }

 

... 흠 .. 중복되는 코드가 있어서 .. 수정을 좀 .. 해야 할 것 같네 .. 

일단 로직은 이렇게 구현하면 문제없이 .. ? 아마도 .. 원하는 상태로 잘 나온다. 

'iOS > ' 카테고리의 다른 글

[왈] Mal 어쩌구 오류  (0) 2022.09.27