[iOS] addAction의 동작 방식

황석범·2025년 1월 10일
1

내일배움캠프_iOS_5기

목록 보기
63/76
cell.playButton.tag = indexPath.row
cell.playButton.addAction(UIAction { [weak self] _ in
             ...생략...
}

위와 같은 형태로 cell의 버튼에 tag를 달아 cell에 있는 버튼이 눌릴 때 마다 버튼이 눌릴 때의 로직을 만들었는데 테이블 뷰가 리로드 될때 마다 액션이 중첩되어서 두 번 리로드 했으면 버튼이 두 번 눌리는 버그가 발생했다..


왜 그런 문제가 발생했을까?

  • addAction 메서드는 특정 이벤트(.touchUpInside 등)가 발생했을 때 실행할 UIAction을 버튼에 추가합니다. 이 메서드의 중요한 특징은 여러 번 호출되면 액션이 중복해서 추가됨

  • 위 코드에서 addAction을 한 번 호출하면 버튼이 클릭될 때 "Button clicked"가 출력됨

  • 그러나 addAction이 동일한 버튼에 대해 여러 번 호출되면, 기존 액션이 유지된 채로 새로운 액션이 추가됨


1. addAction과 addTarget의 차이

특성addActionaddTarget(_:action:for:)
핸들러클로저(UIAction)@objc 메서드
중복 액션 처리중복 액션이 누적됨동일한 target과 Selector는 덮어씀
코드 구조클로저를 사용하여 간결하게 작성 가능메서드를 별도로 정의해야 함
사용 가능 버전iOS 14 이상iOS 2.0 이상

실제로 위 코드에서 addTarget으로 변경하면 버그가 발생하진 않는다.
하지만 두 번 호출하는 것 자체가 문제이긴 하다...


2. addAction에서 중복 액션 처리

  • addAction은 UIButton에 클로저 기반 이벤트 핸들러(UIAction)를 추가합니다. 이 과정에서 버튼의 이벤트 처리기를 덮어쓰는 것이 아니라, 새로운 액션을 계속 추가합니다.

동작 원리

  • addAction을 호출할 때마다 버튼의 이벤트 처리기 리스트에 새 액션(UIAction)이 추가됩니다.
  • 기존의 액션을 제거하지 않으므로 동일한 버튼에 대해 여러 액션이 중복 호출될 수 있습니다.

let button = UIButton(type: .system)

for i in 0...3 {
    button.addAction(UIAction { _ in
        print("Action \(i)")
    }, for: .touchUpInside)
}

//결과
Action 0
Action 1
Action 2
Action 3

3. addTarget(_:action:for:)에서 중복 액션 처리

  • addTarget(_:action:for:)은 버튼의 이벤트와 특정 대상(target) 및 동작(action)을 연결합니다. 이 방식은 동일한 대상과 Selector 조합이 중복 추가되지 않는다는 특징이 있습니다.

동작 원리

  • addTarget은 UIButton의 이벤트와 특정 Selector 메서드를 연결합니다.
  • 동일한 target과 Selector 조합에 대해 중복 처리가 발생하면, 이전 액션이 덮어써집니다.
  • 새로 추가된 target과 Selector가 기존의 동일한 설정을 대체하므로, 이벤트가 중복되지 않습니다.
let button = UIButton(type: .system)

for i in 0...3 {
    button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
}

@objc func buttonTapped() {
    print("Button tapped")
}
//결과
Button tapped

정리하다보니까 당연한 것은 생각도 들고...

profile
iOS 공부중...

0개의 댓글

관련 채용 정보