예전에 iOS 개발을 하셨던 분들은 UIAlertView와 그 델리게이트 메서드인 clickedButtonAtIndex:, didDismissWithButtonIndex: 때문에 한 번쯤은 고생해 보셨을 것입니다. 저 역시 Alert가 백그라운드 전환(Home 버튼)이나 다른 Alert와 얽히는 상황에서 델리게이트가 예상대로 호출되지 않아 며칠 동안 디버깅(삽질)을 했던 기억이 있습니다.
하지만 이제는 상황이 많이 달라졌습니다. UIAlertView는 iOS 8에서 이미 deprecated 되었고, iOS 13 이후로는 사실상 쓰지 않는 레거시 API입니다. 현재는 UIAlertController를 사용하는 것이 정석이며, 예전처럼 didDismissWithButtonIndex에 의존해 상태를 관리하는 방식은 더 이상 추천되지 않습니다.
1. 예전 문제 요약: UIAlertView + didDismissWithButtonIndex
당시 문제가 되었던 시나리오는 대략 다음과 같습니다.
- 다운로드 완료 시점에
UIAlertView를 띄운다. - Alert가 떠 있는 동안 사용자가 Home 버튼을 눌러 앱이 백그라운드로 간다.
- 포그라운드로 복귀하는 과정에서
willPresentAlertView,didPresentAlertView,didDismissWithButtonIndex호출 순서가 꼬인다. - Alert가 사용자 입력 없이 저절로 닫히거나, 이미 해제된 Alert가 다시 나타나면서 다른 View에서 처리되어
EXC_BAD_ACCESS가 발생하는 현상.
이 문제를 회피하기 위해, 예전에는 다음과 같은 꼼수를 쓰기도 했습니다.
clickedButtonAtIndex:대신didDismissWithButtonIndex:에서 처리alertView.superview상태 등을 보고 정상 닫힘 / 비정상 닫힘을 구분- 비정상 케이스에서는
dismissWithClickedButtonIndex:animated:를 직접 호출하거나, Alert를 재출력
하지만 이 모든 접근은 지금 기준으로는 더 이상 유지할 가치가 없는 레거시 패턴입니다. 현재 프로젝트에서는 UIAlertView 자체를 사용하지 않는 것이 맞습니다.

2. 현재(iOS 13+ 기준)에는 UIAlertController를 사용
지금은 알림을 띄울 때 다음과 같이 UIAlertController를 사용합니다.
let alert = UIAlertController(
title: "다운로드 완료",
message: "\(townName) 데이터 다운로드가 완료되었습니다.",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "확인", style: .default) { _ in
// 사용자가 '확인' 버튼을 눌렀을 때 처리
self.handleDownloadCompleted()
})
present(alert, animated: true)
예전처럼 didDismissWithButtonIndex로 분기할 필요 없이, UIAlertAction의 핸들러 클로저에서 바로 로직을 처리하면 됩니다.
2-1. Home 버튼(백그라운드 전환)과 Alert의 관계
iOS 13+에서 UIAlertController는 View 컨트롤러의 생명주기와 함께 관리되며, 앱이 백그라운드로 전환될 경우 시스템이 Alert를 적절히 내려줍니다. 일반적인 케이스에서는 개발자가 따로 dismiss()를 호출하지 않아도 예전처럼 애매한 상태의 Alert가 남아서 문제가 되는 경우는 거의 없습니다.
다만, 중요한 비즈니스 로직을 “Alert가 닫히는 순간”에만 의존해서 처리하는 패턴은 지금도 추천되지 않습니다. 그 대신:
- 다운로드 완료 등의 상태는 별도의 모델/상태 변수로 관리
- Alert는 단순히 "상태를 사용자에게 보여주는 UI"로만 사용
- 앱이 다시 Foreground가 되었을 때, 상태를 보고 Alert를 다시 보여줄지 여부를 판단
3. 예전 로직을 UIAlertController 기준으로 옮기는 예
원래 코드 개념은 다음과 같습니다.
- 다운로드 완료 후 네트워크 상태 체크
- 정상 다운로드 시
Yes/NoAlert 출력 - Alert가 비정상적으로 닫힌 경우 다시 Alert를 보여줌
현재 기준에서는 다음과 같이 단순화할 수 있습니다.
// 다운로드 완료 처리 예시
func handleDownloadFinished(allSpot: Int) {
// 1. 상태 업데이트
self.isDownloading = false
self.downloadedSpotCount += allSpot
// 2. DB 갱신 등 비즈니스 로직 처리
updateTownAndCityInfo()
// 3. Alert 출력 (네트워크, 결과 안내 등)
presentDownloadCompletedAlert()
}
private func presentDownloadCompletedAlert() {
let townName = self.downloadTargetTown.name
let alert = UIAlertController(
title: "다운로드 완료",
message: "\(townName) 데이터 다운로드가 완료되었습니다.\n바로 보시겠습니까?",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "예", style: .default) { _ in
self.showDownloadedTown()
})
alert.addAction(UIAlertAction(title: "나중에", style: .cancel, handler: nil))
// 이미 표시 중인 Alert가 있다면 dismiss 후 다시 표시하는 식으로 중복 방지 가능
if let presented = self.presentedViewController as? UIAlertController {
presented.dismiss(animated: false) {
self.present(alert, animated: true)
}
} else {
self.present(alert, animated: true)
}
}
여기서는 더 이상 didDismissWithButtonIndex를 신경 쓸 필요가 없습니다. 중요한 것은 “Alert가 비정상적으로 사라져도 비즈니스 로직이 꼬이지 않게 설계하는 것”입니다.
4. 예전 코드와의 차이 정리
| 예전 방식 (UIAlertView) | 현재 방식 (UIAlertController) |
|---|---|
Delegate 패턴 (clickedButtonAtIndex:, didDismissWithButtonIndex:) |
UIAlertAction의 핸들러 클로저에서 직접 처리 |
| Home 버튼 / 백그라운드 전환 시 Delegate 순서 꼬임 | 시스템이 VC 수명 주기와 함께 Alert를 관리, 대부분 자연스럽게 정리 |
Alert가 “비정상 닫힘”인지 확인하기 위해 alertView.superview 등 점검 |
중요 상태는 모델로 관리, Alert는 단순 UI 역할 |
dismissWithClickedButtonIndex:animated:를 직접 호출해 꼼수로 제어 |
필요 시 presentedViewController 체크 후 dismiss()만 사용 |
5. 정리
UIAlertView와didDismissWithButtonIndex를 둘러싼 문제는 레거시 이슈가 되었다.- 현재는
UIAlertController+UIAlertAction핸들러 조합으로 Alert 관련 로직을 처리하는 것이 표준이다. - Alert가 언제, 어떻게 닫히는지에 의존하는 설계에서 벗어나, 상태(모델)와 UI를 분리하는 방향으로 구조를 잡는 것이 장기적으로 안전하다.
기존 레거시 프로젝트를 유지보수하면서 UIAlertView 관련 버그를 만난다면, 가능하면 그 부분만이라도 UIAlertController 기반으로 점진적으로 전환해 보는 것을 추천드립니다.
'IT·디지털 > IT 개발자 팁' 카테고리의 다른 글
| ASP.NET Web Service: wsdl.exe 유틸리티 사용법 정리 (0) | 2013.09.10 |
|---|---|
| [iOS] 옛날 아이폰5 해상도 대응 방식, 지금은 어떻게 해야 할까? (2025년 최신 기준) (0) | 2013.01.08 |
| 스마트폰 디바이스별 해상도 정리 (2025년 기준) (4) | 2012.08.22 |
| DOS 배치 파일을 쉘 스크립트로 변환하기 (0) | 2011.10.14 |
| 안드로이드 MediaPlayer 최신 사용법 정리(2025 ver.) (0) | 2011.02.17 |