iOS | addTarget 위치

일어나 개발해야지·2023년 8월 31일

Intro

     let isDoneButton : UIButton = {
            let button = UIButton()
            //        button.backgroundColor = UIColor.red
    button.translatesAutoresizingMaskIntoConstraints = false
            button.addTarget(self, action: #selector(isDoneChange), for: .touchUpInside)
            return button
        }()
    
// WARNING: 'self' refers to the method 'CustomCell.self', which may be unexpected
// Suggestion:  Use 'CustomCell.self' to silence this warning
// 해석: 'self'는 예상치 못한 'CustomCell.self' 메서드를 나타낸다.
 

Fix 적용

    let isDoneButton : UIButton = {
        let button = UIButton()
        //        button.backgroundColor = UIColor.red
        button.translatesAutoresizingMaskIntoConstraints = false
        button.addTarget(CustomCell.self, action: #selector(isDoneChange), for: .touchUpInside)
        return button
    }()
    
// Error : Thread 1: "+[iOS_Todo_App_Update.CustomCell isDoneChange]: unrecognized selector sent to class

해결 : Add target의 위치이동

    let isDoneButton : UIButton = {
         let button = UIButton()
         button.translatesAutoresizingMaskIntoConstraints = false
         return button
     }()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
      
        isDoneButton.addTarget(self, action: #selector(isDoneChange), for: .touchUpInside)
    
    }    
    

Add target의 위치가 포인트 인듯한데
왜 init아래 있어야해 했는지 이유를 알고 싶었다.

해석 1

제공된 코드에서는 클로저를 사용하여 isDoneButton이라는 속성을 정의하고 있습니다. 이 속성은 UIButton의 인스턴스로 설정되며, 특정한 구성을 포함하여 addTarget(:action:for:) 메서드를 사용하여 타겟-액션 관계가 설정됩니다. 타겟은 self로 설정되고, 액션은 isDoneChange 메서드로 지정됩니다.
만난 경고 메시지:
vbnet
Copy code
WARNING: 'self' refers to the method 'CustomCell.self', which may be unexpected
Suggestion: Use 'CustomCell.self' to silence this warning
이 경고는 클로저 내에서 self 사용이 예상치 못한 결과를 가져올 수 있다는 것을 알려줍니다. 클로저가 실행되는 컨텍스트가 예상한 것과 다를 수 있으며, CustomCell의 인스턴스 대신 CustomCell.self를 사용하게 될 수 있습니다. 제안은 명시적으로 CustomCell.self를 사용하여 의도를 명확하게 하라는 것입니다.
이 경고가 발생하는 이유는 Swift에서 클로저나 중첩 함수 내에서 self를 사용하면 포함하는 타입의 인스턴스를 캡처합니다. 이 경우 클로저를 실행하는 컨텍스트는 클래스의 메타타입인 CustomCell.self입니다.
특정한 상황에서는 클로저 내에서 속성이나 메서드를 액세스할 때, self를 사용하면 의도한 인스턴스 대신 메타타입(CustomCell.self)을 캡처할 수 있습니다.
이 문제를 해결하고 addTarget(
:action:for:)가 CustomCell의 특정 인스턴스와 함께 올바르게 설정되도록 하려면, 버튼을 서브뷰로 설정하는 init 메서드 내에 addTarget 구성을 이동시켜야 합니다. 이렇게 함으로써 클로저가 self를 캡처하는 동작에 의존하는 대신 CustomCell의 인스턴스와 관련된 액션을 설정할 수 있습니다.
요약하면, 경고와 제안은 클로저 내에서 self 사용이 의도한 인스턴스 대신 메타타입을 캡처할 수 있는 잠재적인 문제를 가리키며, addTarget 구성을 init 메서드 내에 이동하여 CustomCell의 올바른 인스턴스와 액션이 연결되도록 하는 것입니다.

해석2

addTarget(:action:for:) 메서드는 컨트롤(예: 버튼)과 타겟 객체 및 액션 메서드를 연결하는 데 사용됩니다. 코드에서 addTarget(:action:for:) 메서드는 isDoneButton에서 호출되고, 버튼이 탭될 때 (for: .touchUpInside) 타겟 객체에 대해 isDoneChange 메서드가 호출되어야 함을 지정합니다.
경고 메시지 "'self' refers to the method 'CustomCell.self', which may be unexpected"은 액션의 대상으로 어떤 인스턴스의 self를 사용해야 하는지 결정하는 데 모호성이 있을 수 있다는 것을 나타냅니다. 이 경고가 발생하는 이유는 isDoneButton 초기화 중 클로저 내부에서 사용하고 있기 때문입니다.
이 경고를 해결하기 위해 Xcode는 'self' 대신 'CustomCell.self'를 사용하도록 제안합니다. 'CustomCell.self'를 지정함으로써 클래스 자체를 명시적으로 참조하게 되며, 인스턴스가 아닌 클래스 자체를 참조함으로써 모호성을 제거하고 올바른 타겟을 참조할 수 있게 됩니다.
클로저 내부에서 있는 addTarget(:action:for:) 호출문을 클로저 밖인 init(style:reuseIdentifier:) 내부로 이동시키면 이 문제가 해결됩니다. 왜냐하면 더 이상 클로저 내부가 아니라 인스턴스 메서드 내부에서 사용하기 때문에 'self'가 기본적으로 해당 클래스의 인스턴스를 가리키게 되어 모호성이 없어집니다.
요약하자면, 클로저 내부에서 있는 addTarget(
:action:for:) 호출문을 클로저 외부인 init(style:reuseIdentifier:) 내부로 이동함으로써, 'self'가 의도한대로 해당 커스텀 셀 클래스의 인스턴스를 올바르게 참조하도록 보장합니다.

0개의 댓글