📗 Call must be made on main thread 에러
- 현재 작성된 코드
guard (200..<300).contains(statusCode) else {
var title: String
var message: String
switch statusCode {
case 401..<500:
title = "클라이언트 요청 에러"
message = "클라이언트에서의 네트워크 연결 혹은 입력값이 잘못되어 데이터를 받아오지 못하였습니다"
case 501..<600:
title = "서버 에러"
message = "서버의 문제가 생겨 데이터를 받아오지 못하였습니다"
default:
title = "알 수 없는 에러"
message = "알 수 없는 에러로 데이터를 받아오지 못하였습니다"
}
// 1. alert 창 구성
let alert = UIAlertController(title: title,
message: message,
preferredStyle: .alert)
// 2. alert button 구성
let check = UIAlertAction(title: "확인", style: .default)
// 3. alert에 button 추가
alert.addAction(check)
DispatchQueue.main.async { [weak self] in
guard let self else { return }
present(alert, animated: true)
}
return
}
- URLSession의 dataTask 메서드를 통해 받아온 response 값의 status code 를 확인하여 에러를 가지고 있는 status code를 만나면 Alert를 뷰에 띄어준다.
- 처음에는 기본적인 present 메서드를 호출하였고
present(viewControllerToPresent: UIViewController, animated: Bool)
- 이 상태로 앱을 빌드한 결과
- 아래 스크린샷으로 보여지는 에러를 만나게 됐다.
- 그래서 global thread에서 돌렸던 상황에서 아래 코드를 통해 main thread로 다시 thread를 main thread로 돌려놓았고 다시 빌드해 본 결과
DispatchQueue.main.async { [weak self] in
guard let self else { return }
present(alert, animated: true)
}
- 화면에 Alert이 잘 보여지는 것을 볼 수 있다.
📘 Unsupported enumeration of UIWindowScene windows on non-main thread. 경고문
하지만 처음부터 계속 보여지고 있었지만 내가 보지 못하고 있던 경고문이 있었는데
Unsupported enumeration of UIWindowScene windows on non-main thread.
라는 경고문이 계속 Xcode 상에 출력이 되고 있었다.
의미부터 이해가 잘 가지 않아 해석하는 데 시간을 좀 썼다.
- 생각을 해본 결과 의미는
main thread
가 아닌 다른thread
즉,global thread
에서UIWindowScene
의windows
를 열거할 수 없다. 열거할 수 없다
라는 말은 좀 더 공부를 해봐야갰지만 말 그대로 열거 즉, 보여주면 안된다?(작성하면 안된다? 생성하면 안된다?) 무슨 말일까 생각해보면 어쨌든 계층 구조를 살펴봤을 때UIScreen - UIWindowScene - UIWindow - UIView
의 순서로 쌓여진다.
- 이 결과, UIView가 메모리에 올라가는 상황, 인스턴스가 생성되는 시점 자체가 global thread 가 아닌 main thread 여야만 했던 것이 아닐까 라는 생각이 든다
📚 문제
- 그렇다면 나의 코드에서는 어떤 부분이 문제였을까?
- 그렇다 위의 코드를 다시 살펴보면 나는 present() 즉, 사용자가 보는 화면에 보여지는 시점에
global thread
였던 현재의thread
를main thread
로 변경해주었다. 시점 자체가 잘못되었던 것이다.
// 1. alert 창 구성
let alert = UIAlertController(title: title,
message: message,
preferredStyle: .alert)
// 2. alert button 구성
let check = UIAlertAction(title: "확인", style: .default)
// 3. alert에 button 추가
alert.addAction(check)
DispatchQueue.main.async { [weak self] in
guard let self else { return }
present(alert, animated: true)
}
UIAlertController
는UIViewController
를 상속받고 있는 객체이고,UIViewController
는UIView
를 base로 구성되는 객체였기 때문에 나는UIAlertController
의인스턴스
를 생성해줬던 시점이 문제였던 것이다
⭐️ 문제 해결
global thread
에서main thread
로 변경해주던시점
을UIAlertController
의인스턴스를 생성하는 시점
으로 변경하면서 경고문구가 사라졌다.
DispatchQueue.main.async { [weak self] in
guard let self else { return }
// 1. alert 창 구성
let alert = UIAlertController(title: title,
message: message,
preferredStyle: .alert)
// 2. alert button 구성
let check = UIAlertAction(title: "확인", style: .default)
// 3. alert에 button 추가
alert.addAction(check)
present(alert, animated: true)
}
- 결과
'iOS > UIKit' 카테고리의 다른 글
RxSwift + TableView + MVVM + Input & Output 에서 TableViewCell 내부 disposeBag 중첩현상 (0) | 2024.08.06 |
---|---|
UIKit에서 UICollectionView에 SkeletonView 간단하게 사용해보기 (2) | 2024.06.21 |
UIKit - resignFirstResponder() & becomeFirstResponder() (2) | 2024.06.02 |
UIKit - IBOutlet, IBAction 연결관계 에러 해결 방법 (0) | 2024.05.20 |
UIKit - Default Button 이상현상 해결법 (0) | 2024.05.20 |