June 22, 2021, TIL (Today I Learned) - present modally TroubleShooting

Inwoo Hwang·2021년 8월 26일
0
post-thumbnail

Trouble: "Application tried to present modally a view controller...that is already being presented by"

상품을 등록하는 페이지를 구현 중 맞닥드린 문제는 이와 같습니다.

사용자가 상품등록시 비밀번호를 모두 숫자로 입력하거나 빈칸으로 냅두면 경고 알림장을 화면에 띄어주고 여기에 더불어 필수로 입력해야하는 칸을 비우고 Done 버튼을 클릭시 경고 메세지를 화면에 보여주는 로직을 짜고 있었습니다.

비밀번호의 알림같은 경우 문제 없이 잘 나타나는 것을 확인했습니다만 문제는 Done 버튼을 클릭하면 아래와 같은 오류가 뜨면서 앱이 crash 되는 것입니다.

Done 버튼을 클릭시 실행되는 메서드는 아래와 같습니다.

무조건 값이 들어가야 하는 textField(상품 이름, 가격, 수량, 화폐단위)를 배열로 만들어준 뒤 forEach 문을 돌면서 만약 textfieldtext가 빈 값이면 self?.present()를 통해서 알림을 띄어주는 방식으로 로직을 짰습니다. 그리고 마지막으로 상세정보 같은 경우 textField가 아니고 textView이기 때문에 별도로 조건문을 만들어서 알림창을 띄우도록 구현하였습니다. 도대체 뭐가 문제일까요?

func examineRequiredInformation() {
        let alertController = UIAlertController(title: "입력 오류", message: "필수항목을 모두 입력 해 주세요.", preferredStyle: .alert)
        let action = UIAlertAction(title: "OK", style: .default, handler: nil)
        
        alertController.addAction(action)
        
        [titleTextField, passwordTextField, priceTextField, stockTextField, currencyTextField].forEach { [weak self] textField in
            guard let text = textField.text else { return }
            if text.isEmpty {
                self?.present(alertController, animated: true, completion: nil)
            }
        }
        
        guard let detailedText = detailedInformationTextView.text else { return }
        if detailedText.isEmpty || detailedText == textViewDefaultMessage {
            self.present(alertController, animated: true, completion: nil)
        }
        
    }

TroubleShooting: 불완전한 로직에 의해서 alertcontroller가 겹치는 문제

제일 큰 문제는 for 돌 때 마다 alertControllerpresent 되는 것이었습니다. 상품명에 아무런 text가 없을 경우 한번 그리고 해당 alertController가 dismiss 되기 전에 다시한 번 priceTextField를 검사하고 텍스트가 없으면 또 다시 동일한 alertController가 화면에 보이게 되는데 이렇게 겹치는 것을 허락하지 않는다고 친절하게 오류메세지가 알려주던거더라구요

두 번째로 모든 textField를 검사한 뒤 textView(상세정보) 에서 또한 빈값이 존재한다면 해당 alertController가 호출 될 것이니 Xcode가 당연히 어떤 alert를 화면에 보여줘야 하는지 헷갈리는 것이 당연하다고 생각 되네요. 그래서 아래와 같이 코드를 고쳐보았습니다.

[titleTextField, passwordTextField, priceTextField, stockTextField, currencyTextField].forEach { [weak self] textField in
            guard let text = textField.text else { return }
            if text.isEmpty && self?.presentedViewController == nil {
                self?.present(alertController, animated: true, completion: nil)
            }
        }
        
        guard let detailedText = detailedInformationTextView.text else { return }
        if (detailedText.isEmpty || detailedText == textViewDefaultMessage) && self.presentedViewController == nil {
            self.present(alertController, animated: true, completion: nil)
        }

thanks to @yagom 👏

텍스트가 empty인 것을 검사하면서 추가로 이미 보여지고 있는 ViewController가 없는 경우에만 알림을 화면에 띄우도록 수정을 하였습니다. 텍스트 뷰 또한 이와 같이 수정하니 문제 없이 잘 돌아가는 것을 확인 할 수 있었습니다.

profile
james, the enthusiastic developer

0개의 댓글