네트워크 연결이 끊겼을 때의 처리가 구현되어 있지 않아, 네트워크 재연결이 되었을 때 BLE로 연동한 혈당 데이터가 동기화되지 않는 문제가 발생했습니다.
이 문제를 해결하기 위해서 네트워크 연결이 끊겼을 때 경고창을 띄우도록 구현했습니다.
서버에 재요청하는 시나리오는 다음과 같습니다.
팝업
띄움설정
과 재시도
버튼 두 개를 생성샘플 코드
먼저 경고 팝업을 싱글톤으로 생성
final class CustomAlert {
static let shared = CustomAlert()
private init() { }
func showNetworkAlert(function: @escaping () async -> Void) {
let alert = UIAlertController(title: "네트워크 연결 오류", message: "네트워크 연결이 끊겼습니다.", preferredStyle: .alert)
// 설정 이동 액션
let settingsAction = UIAlertAction(title: "설정", style: .default) { _ in
print("설정 진입!")
guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
self.retry(function: function)
}
}
alert.addAction(settingsAction)
// 재시도 액션
let retryAction = UIAlertAction(title: "재시도", style: .default) { _ in
print("retryAction 진입!")
self.retry(function: function)
}
alert.addAction(retryAction)
UIWindow.keyWindow?.rootViewController?.present(alert, animated: true, completion: nil)
}
// 재시도할 함수 실행 함수
private func retry(function: @escaping () async -> Void) {
Task {
await function() // 연결 재시도
}
}
}
ViewModel
에서 서버에 요청 후, 네트워크 연결이 끊겼을 시, 팝업을 표시하도록 구현
// PostTableViewModel
final class PostTableViewModel {
var posts: [Post] = []
var filteredPosts: [Post] = []
func request(targetType: TargetType) async {
switch targetType {
case .getPosts:
do {
try await NetworkManager.shared.request(targetType: .getPosts) { [weak self] (result: Result<[Post], NetworkError>) in
switch result {
guard let self = self else { return }
case .success(let posts):
self.posts = posts
if posts.isEmpty {
print(NetworkError.noData)
return
}
case .failure(let error):
CustomAlert.shared.showNetworkAlert { [weak self] in
await self.request(targetType: targetType)
}
}
}
} catch {
// 네트워크 에러 발생 시, 경고 팝업 표시
await MainActor.run {
CustomAlert.shared.showNetworkAlert { [weak self] in
await self?.request(targetType: targetType)
}
}
}
}
}
}
ViewController
에서는 ViewModel
을 통해 서버에 요청
// ViewController
func fetchPosts() {
Task { [weak self] in
guard let self = self else { return }
await self.postTableViewModel.request(targetType: .getPosts)
await MainActor.run { [weak self] in
guard let self = self else { return }
self.postTableView.reloadData()
}
}
}