티스토리 뷰

UIAlertController를 사용하다보면 반복적으로 코드를 사용하게 된다.

BaseViewController 클래스를 따로 만들어서 해당 클래스에 메서드를 만들어서 사용을 했었는데 매니저를 따로 만드는게 좋지 않을까 싶어서 정보를 찾아보았다.

 

매니저(헬퍼)를 만들어서 코드의 중복을 줄이거나, 프로토콜을 사용하는 두가지 방법을 확인해보자. 

 

UIAlertController의 반복적인 사용

예시1)

let ac = UIAlertController(title: "알림", message: "메시지", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "확인!", style: .default, handler: nil))
present(ac, animated: true)

예시2)

let ac = UIAlertController(title: "삭제", message: "정말로 삭제하시겠습니까?", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "삭제", style: .destructive, handler: { (_) in
            // delete here
}))
ac.addAction(UIAlertAction(title: "취소", style: .cancel, handler: nil))
present(ac, animated: true)

위와 같은 식으로 alert을 띄우는데, 매번 해당 코드를 작성하거나, 하나의 뷰 컨트롤러에 여러 텍스트로 경고를 띄워야 하는 경우가 발생할 수 있다.

 

 

헬퍼 클래스 접근

class AlertHelper {
    static func showAlert(title: String?, message: String?, over viewController: UIViewController) {
        let ac = UIAlertController(title: title, message: message, preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "확인", style: .default, handler: nil))
        viewController.present(ac, animated: true)
    }
}

가볍게 핼퍼 클래스를 위와 같이 만들어서 사용할 수 있다.

 

class AlertHelper {
    static func showAlert(title: String?, message: String?, over viewController: UIViewController) {

        assert((title ?? message) != nil, "Title OR message must be passed in")

        let ac = UIAlertController(title: title, message: message, preferredStyle: .alert)
        ac.addAction(.gotIt)
        viewController.present(ac, animated: true)
    }
}

extension UIAlertAction {
    static var gotIt: UIAlertAction {
        return UIAlertAction(title: "확인", style: .default, handler: nil)
    }
}

아니면 위와 같이 사용할 수도 있다.
assert 메서드를 추가해서 title과 message의 nil 여부를 체크하고, 확인 action을 extenstion으로 정의했다.

 

실제로 사용할 때는 뷰컨트롤러안에서 아래와 같이 사용할 수 있다.

AlertHelper.showAlert(title: "알림", message: "중요한 텍스트 입니다.", over: self)

 

삭제 버튼의 Alert 리팩토링

삭제 버튼과 어떤 동작이 필요한 경우를 살펴보자.


AlertHelper 클래스에 아래 코드를 추가

typealias Action = () -> ()
    
static func showDeleteConfirmation(title: String, message: String?, onConfirm: @escaping Action, over viewController: UIViewController) {
	let ac = UIAlertController(title: title, message: message, preferredStyle: .alert)

	ac.addAction(UIAlertAction(title: "삭제", style: .destructive, handler: { (_) in
		onConfirm()
	}))

	ac.addAction(.cancel)

	viewController.present(ac, animated: true)
}

UIAlertAction Extension에 아래 코드를 추가

static var cancel: UIAlertAction {
	return UIAlertAction(title: "취소", style: .cancel, handler: nil)
}

 

클로저를 사용해서 삭제 동작을 작동시킬 수 있다.

AlertHelper.showDeleteConfirmation(title: "삭제타이틀", message: "삭제메시지", onConfirm: {
	print("정말로 삭제 작업 실행")
}, over: self)

 

추가로(선택사항), 헬퍼를 싱글톤 패턴으로 사용하고자 AlertHelper 클래스에 아래 코드를 추가하고, 현재 타입 메서드인 showAlert 메서드와 showDeleteConfirmation 메서드의 앞의 static을 삭제했다. 

static let shared = AlertHelper()
private init() { }

 

사용은 아래와 같이 할 수 있다.

AlertHelper.shared.showAlert(title: nil, message: "메시지", over: self)

AlertHelper.shared.showDeleteConfirmation(title: "삭제타이틀", message: "삭제메시지", onConfirm: {
	print("정말로 삭제 작업 실행")
}, over: self)

 

프로토콜 접근

두번째 방법으로, 프로토콜을 사용하는 방법을 알아보자.

protocol AlertsPresenting: UIViewController { }

extension AlertsPresenting {
    func showAlert(title: String?, message: String?) {

        assert((title ?? message) != nil, "Title OR message must be passed in")

        let ac = UIAlertController(title: title, message: message, preferredStyle: .alert)
        ac.addAction(.gotIt)

        present(ac, animated: true)
    }
}
extension UIAlertAction {
    static var gotIt: UIAlertAction {
        return UIAlertAction(title: "확인", style: .default, handler: nil)
    }

    static var cancel: UIAlertAction {
        return UIAlertAction(title: "취소", style: .cancel, handler: nil)
    }

}

AlertsPresenting 이라는 프로토콜을 생성한다.

프로토콜 extension을 통해서 showAlert 메서드를 구현해준다. (프로토콜 지향 프로그래밍)

class ViewController: UIViewController, AlertsPresenting

사용하고자 하는 뷰컨트롤러에 프로토콜을 채택시켜주면, 뷰컨트롤러 안에서 아래 코드와 같이 사용 가능하다.

showAlert(title: "알림 타이틀", message: "알림 메시지")

 

추가로,

extension UIViewController: AlertsPresenting { }

UIViewController의 extension에 해당 프로토콜을 채택시켜주면 모든 뷰컨트롤러에서 alert메서드들을 사용할 수 있다.

 

 

 

 

참고 : https://nemecek.be/blog/51/refactoring-uialertcontroller-helper-class-and-protocol-approaches#the-repetitive-code

댓글