ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Delegate 패턴
    iOS 앱 2023. 3. 31. 19:24

    Delegate 패턴은 왜 사용하는가?

    : Delegate(대리자), 직접 행동하는 것이 아닌, 해야 할 행동을 위임한다. 

     

    1. 두 객체의 소통을 위한 delegate pattern

    두 객체를 연결해 주고 싶을 때 사용 

    -> 이벤트를 받은 객체와 이를 처리할 객체가 다른 경우에 사용한다. 

     

    2. UI요소에서의 delegate pattern

    인스턴스가 직접적으로 행위를 실행하기 어려운 경우에 사용한다. UI요소의 경우에는 직접 내부 코드를 수정할 수 없는 경우에 사용한다. 

    UITableview의 내부 코드는 숨겨져있다. 

    따라서, delegate를 지정하고, 이 delegate에서 할 행동을 선언해주어야한다. 

     

     

    Delegate 패턴 예시

    protocol Remotecontrol{
        func chanelUp()
    }
    
    class RemoteController {
        var delegate : Remotecontrol?
        
        func remoteControllerChanelUp() {
            delegate?.chanelUp()
        }
    }
    
    class TV : Remotecontrol {
        func chanelUp() {
            print("TV chanel Up")
        }
    }
    
    
    let remote = RemoteController()
    let samTV = TV()
    
    remote.delegate = samTV
    remote.remoteControllerChanelUp() //  ("TV chanel Up")출력

    리모컨이 TV의 채널을 올리는 상황, 

    TV는 리모컨의 명령을 받을 수 있는 단자가 필요하다. 

    이때, 리모컨을 인식할 수 있는 형식임을 Protocol로 보증. 

     

    Protocol로 TV가 해야 하는 행동을 나열한다. 

    위 코드에서는 chanelUp()

    chanelU메서드 구현은 TV 클래스에서 해주어야한다. 

     

    TV는  chanelUp() 메서드가 실행된 경우 어떤 행동을 할지 정의한다. 

     

    리모컨은 delegate 프로퍼티로 samTV 선언

    remote.delegate = samTV

    리모컨에서

    remoteControllerChanelUp() 메서드 실행시, 

     

    samTV의 

    chanelUp() 매서드가 실행된다. 

    remote.remoteControllerChanelUp()

     

    delegate pattern 사용시 주의사항: 강한 참조 순환(Strong Reference Cycle)

     

    : delegate 프로퍼티 정의 시 weak으로 선언 필요 (서로를 참조하는 경우)

    class RemoteController {
    	//⭐️weak으로 선언
        weak var delegate : Remotecontrol?
        
        func remoteControllerChanelUp() {
            delegate?.chanelUp()
        }
    }

    UITextFieldDelegate 사용 예시

    import UIKit
    
    //뷰컨트롤러에서 UITextFieldDelegate 채택
    class ViewController: UIViewController, UITextFieldDelegate {
    
        @IBOutlet weak var textField: UITextField!
        
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            //delegate설정, 여기서의 self는 viewcontroller를 의미
            textField.delegate = self
            
            setup()
        }
        
        func setup() {
            textField.keyboardType = UIKeyboardType.emailAddress
            textField.placeholder = "이메일 입력"
            textField.borderStyle = .roundedRect
            textField.clearButtonMode = .always
            textField.returnKeyType = .go
        }
        
        //텍스트 필드의 입력을 시작할 때 호출 (시작할지 말지의 여부 허락하는 것)
        func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
            return true
        }
        
        // 시점 - 텍스트 필드의 입력이 시작되는 시점
        func textFieldDidBeginEditing(_ textField: UITextField) {
            print("유저가 텍스트 필드의 입력을 시작함.")
        }
        
        func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
            
            let maxLength = 10
            let currentString: NSString = (textField.text ?? "") as NSString
            let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
            return newString.length <= maxLength
            
        }
    
        @IBAction func inputbtnPressed(_ sender: UIButton) {
            print(textField.text)
            textField.text = ""
            
        }
    }

    textFieldViewController에게 행동을 위임함.

    textField에서 어떤 행동이 일어났을때 이를 ViewController에 알린다. 

     

    :ViewControllertextField의 delegate가 된다. 

    textField.delegate = self

    textField -> 리모컨

    ViewController -> TV

     

     

     

     func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
            let maxLength = 10
            let currentString: NSString = (textField.text ?? "") as NSString
            let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
            return newString.length <= maxLength
        }

    textField에서 사용자의 입력이 시작된 것을 ViewController에 알리고, 

    이를 바탕으로 ViewController는 메서드(textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool)를 실행시켜서 Bool타입을 반환한다. 

    이 때, Bool타입인 false가 오면 textField는 입력을 막는다.

     

     

Designed by Tistory.