Task 8) 비효율적 Alert 코드

soy·2024년 12월 23일

iOS-Task

목록 보기
10/12

기존 코드

extension MyPageViewController: MyPageViewLoginDelegate {
    func myPageViewDidRequestLogin() {
        let alert = UIAlertController(title: "로그인이 필요합니다.",
                                      message: "로그인 하시겠습니까?",
                                      preferredStyle: .alert)
                
        alert.addAction(UIAlertAction(title: "확인", style: .default, handler: { _ in
            print("확인 버튼 누름")
            
            // 로그인 화면으로 이동
            let signInVC = SigninViewController()
            let signInNavController = UINavigationController(rootViewController: signInVC)
            signInNavController.modalPresentationStyle = .fullScreen
            
            // 현재 윈도우 가져와서 루트 변경
            if let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? UIWindowSceneDelegate,
               let window = sceneDelegate.window {
                window?.rootViewController = signInNavController
                window?.makeKeyAndVisible()
            }
        }))
        alert.addAction(UIAlertAction(title: "취소", style: .destructive, handler: nil))
            
        self.present(alert, animated: true, completion: nil)
    }
    
    func myPageViewDidRequestLogOut() {
        let alert = UIAlertController(title: "로그아웃 하시겠습니까?", message: "",
                                      preferredStyle: .alert)
                
        alert.addAction(UIAlertAction(title: "확인", style: .default, handler: { _ in
            print("확인 버튼 누름")
            
            // 로그인 화면으로 이동
            let signInVC = SigninViewController()
            let signInNavController = UINavigationController(rootViewController: signInVC)
            signInNavController.modalPresentationStyle = .fullScreen
            
            // 현재 윈도우 가져와서 루트 변경
            if let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? UIWindowSceneDelegate,
               let window = sceneDelegate.window {
                window?.rootViewController = signInNavController
                window?.makeKeyAndVisible()
            }
        }))
        alert.addAction(UIAlertAction(title: "취소", style: .destructive, handler: nil))
            
        self.present(alert, animated: true, completion: nil)
    }
}

마이페이지에서

1) 로그아웃을 시도하는 경우
2) 로그인을 시도하는 경우

2가지의 경우의 알럿창을 만들어야 했다!

그런데 둘 다 로그인 화면으로 이동하게 하는 알럿이었고, 단순하게 알림창의 title과 message만 달랐음

이때 급하게 진행을 해서 일단 push하고 Merge를 해야했기에.. 중복 코드를 사용했고,, 내내 마음이 쓰였다 ㅜ_ㅜ

알럿 창을 만들어서, 로그인 화면으로 가는 로직이 동일하다!

그리하여 내가 개발한 파트의 리팩토링을 진행하기로 마음 먹음!


리팩토링 코드

단순하게 중복되는 코드만 따로 분리해줬다.

extension MyPageViewController: MyPageViewLoginDelegate {
    func myPageViewDidRequestLogin() {
        let alert = UIAlertController(title: "로그인이 필요합니다.",
                                      message: "로그인 하시겠습니까?",
                                      preferredStyle: .alert)
        showAlert(alert)
    }
    
    func myPageViewDidRequestLogOut() {
        let alert = UIAlertController(title: "로그아웃 하시겠습니까?", message: "",
                                      preferredStyle: .alert)
        showAlert(alert)
    }
    
    func showAlert(_ alert: UIAlertController) {
        alert.addAction(UIAlertAction(title: "확인", style: .default, handler: { _ in
            print("확인 버튼 누름")
            
            // 로그인 화면으로 이동
            let signInVC = SigninViewController()
            let signInNavController = UINavigationController(rootViewController: signInVC)
            signInNavController.modalPresentationStyle = .fullScreen
            
            // 현재 윈도우 가져와서 루트 변경
            if let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? UIWindowSceneDelegate,
               let window = sceneDelegate.window {
                window?.rootViewController = signInNavController
                window?.makeKeyAndVisible()
            }
        }))
        alert.addAction(UIAlertAction(title: "취소", style: .destructive, handler: nil))
            
        self.present(alert, animated: true, completion: nil)
    }
}

showAlert라는 함수를 생성하여 매개변수로 UIAlertController를 받아올 수 있도록 만들었다!

클로드에게 리팩토링 방향을 물어봤더니,

extension MyPageViewController: MyPageViewLoginDelegate {
    // 공통으로 사용되는 로그인 화면 전환 로직
    private func navigateToSignIn() {
        let signInVC = SigninViewController()
        let signInNavController = UINavigationController(rootViewController: signInVC)
        signInNavController.modalPresentationStyle = .fullScreen
        
        if let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? UIWindowSceneDelegate,
           let window = sceneDelegate.window {
            window?.rootViewController = signInNavController
            window?.makeKeyAndVisible()
        }
    }
    
    // 공통으로 사용되는 알럿 표시 로직
    private func showAlert(title: String, message: String, completion: (() -> Void)?) {
        let alert = UIAlertController(title: title,
                                    message: message,
                                    preferredStyle: .alert)
        
        alert.addAction(UIAlertAction(title: "확인", style: .default, handler: { _ in
            print("확인 버튼 누름")
            completion?()
        }))
        alert.addAction(UIAlertAction(title: "취소", style: .destructive, handler: nil))
        
        self.present(alert, animated: true, completion: nil)
    }
    
    func myPageViewDidRequestLogin() {
        showAlert(
            title: "로그인이 필요합니다.",
            message: "로그인 하시겠습니까?",
            completion: navigateToSignIn
        )
    }
    
    func myPageViewDidRequestLogOut() {
        showAlert(
            title: "로그아웃 하시겠습니까?",
            message: "",
            completion: navigateToSignIn
        )
    }
}

위와 같이 답변을 해주었다.
알럿을 표시해주는 함수와 화면 전환 함수도 분리했다.

-> 이렇게 분리하면 재사용성이 더 높아질 거 같다! 특히 showAlert라는 함수를 계속 사용할 수 있음..

코드를 더 자세히 살펴보면

private func showAlert(title: String, message: String, completion: (() -> Void)?)

completion: (() -> Void)?

  • 옵셔널 클로저를 파라미터로 받음
  • () -> Void는 파라미터 없고 반환값도 없는 클로저 타입
  • ?가 붙어서 클로저 자체가 옵셔널 (전달하지 않아도 됨)
alert.addAction(UIAlertAction(title: "확인", style: .default, handler: { _ in
	print("확인 버튼 누름")
	completion?() // 옵셔널체이닝
}))

completion?()

  • 옵셔널 체이닝으로 completion 클로저 실행
  • completion이 nil이 아닐 때만 실행됨
  • "확인" 버튼을 눌렀을 때 전달받은 클로저가 실행됨

completion을 옵셔널로 만들어주어 단순 알림용으로, nil인 경우에도 사용할 수 있게 함. . .

깨달은 것

  • 함수를 더 작은 단위로 사용할 것
  • 클로저를 더 잘 활용해보자! 억지로라도 사용하는 방법을 좀 익혀야할 듯 하다 , , ,
profile
soysoisoyysauce~

0개의 댓글