아요 개발 일기

[iOS] 델리 게이트 - Delegate 본문

iOS

[iOS] 델리 게이트 - Delegate

소진이 2023. 1. 3. 15:29

안녕하세요. 소진입니다 :-)

오늘은 델리게이트에 대해 알아보도록 하겠습니다!

 

먼저, 델리게이트 개념을 알기 전에 프로토콜에 대한 개념을 알아야 하는데요.

프로토콜에 대해 잘 모르신다면 Protocol 포스팅을 참고해주세요!


델리게이트란?


 

delegate의 사전적의미는 대표 혹은 위임이라고 합니다. 의미 그대로 할 일을 대신 해준다고하는데..

"어떤 객체가 해야 하는 일을 부분적으로 확장해서 대신 처리한다."라고 설명하기도 하네요!

 


의미에 대해서는 이해가는데 대체 어디서 사용하는걸까요???

 

특정 객체와 상호 작용할 때 메시지를 넘기면 그 메시지에 대한 책임은 델리게이트로 위임됩니다.

그리고 델리 게이트 메서드는 해당 역할을 수행하며 처리 결과나 메시지 등을 받습니다.

 

즉, 사용자가 객체를 터치했을 때 해야 할일을 델리게이트 메서드에 구현하고,

해당 객체가 터치 되었을 때 델리게이트가 호출되어 위임받는 일을 하게 되는 것 입니다. 

 

쉽게 말해 아래와 같은 그림으로 진행되는 것이죠.

출처 - boostrcurse 야곰 iOS 프로그래밍

 


 

프로토콜 개념을 알아야 하는 이유는?

 

그 이유는 델리게이트가 프로토콜로 구현되기 때문입니다!

 

여기서 간단하게 프로토콜에 대해 설명하자면, 일종의 약속, 규약이라고 할 수 있습니다.

 

'편지를 보내는 방법' 이라는 프로토콜이 있다고 가정하면,

내부에는 수신자, 발신자, 수신자 주소, 발신자 주소, 날짜 내용물 등이 들어있다고 생각하면 됩니다.

무슨 상황이든지 위와 같은 기본적인 요소를 담고 있어야 겠죠?


계속 글로만 말하니깐 정확히 델리게이트를 어떻게 이용하는지 모르겠죠??

 

아래 예시 코드를 보면서 같이 이해해봅시다!

 

먼저, FuelPumpDelegate프로토콜을 구현하여 연료의 양에 따라 필요한 알림을 전달하는 함수를 생성하였습니다.

protocol FuelPumpDelegate {
    func lackFuel()
    func fullFuel()
}

class FuelPump {
    var maxGage: Double = 100.0
    var delegate: FuelPumpDelegate? = nil
    
    var fuelGage: Double {
        didSet {
            if oldValue < 10 {
                // 연료가 부족해지면 델리게이트의 lackFule 메소드를 호출한다.
                self.delegate?.lackFuel()
            } else if oldValue == self.maxGage {
                // 연료가 가득차면 델리게이트의 fullFuel 메소드를 호출한다.
                self.delegate?.fullFuel()
            }
        }
    }
    
    init(fuelGage: Double = 0) {
        self.fuelGage = fuelGage
    }
    
    // 연료펌프를 가동한다.
    func startPump( ) {
        while (true) {
            if (self.fuelGage > 0) {
                self.jetFuel()
            } else {
                break
            }
        }
    }
    
    // 연료를 엔진에 분사한다. 분사할 때마다 연료 게이지의 눈금은 내려간다.
    func jetFuel( ) {
        self.fuelGage -= 1
    }
}

class Car : FuelPumpDelegate {
    var fuelPump = FuelPump(fuelGage: 100)
    
    init() {
        self.fuelPump.delegate = self
    }
    
    // fulePump가 호출하는 메소드입니다.
    func lackFuel() {
        // 연료를 보충한다.
    }
    
    // fulePump가 호출하는 메소드 입니다.
    func fullFuel() {
        // 연료 보충을 중단한다.
    }
    
    // 자동차에 시동을 겁니다.
    func start() {
        fuelPump.startPump()
    }
}

FuelPump 클래스는 FuelPumpDelegate 프로토콜을 delegate 프로퍼티에 저장해 두고 호출하도록 선언해놓은 것을 알 수 있죠??

그 후 Car 클래스를 선언하여 FuelPump 클래스에게 값을 넘겨주는 인스턴스를 생성하고, FuelPumpDelegate 프로토콜을 참조 순서로 진행됩니다. 즉, 실행 시 연료가 부족하면 delegate 객체를 통해서 lackFuel() 메소드를 호출하게되는 겁니다.

 

쉽게 말해, 연료가 충분하거나 부족할때 

Car -> FuelPump -> PuelPumpDelegate 순으로 값을 받아오는거라고 생각하시면 쉽습니다!!

 


 

이렇게 델리게이트 참조를 통해 메소드를 호출할 인스턴스 객체를 전달 받고,

이 인스턴스 객체가 구현하고 있는 프로토콜에 선언된 메소드를 호출하는 것이 델리게이트(션)이라고 할 수 있습니다.

 

 

이러한 델리게이트 (프로토콜)을 활용하여 코드를 구현하는 것을 델리게이트 패턴이라고 합니다.

그럼 이제 델리게이트 패턴에 대해서 자세히 알아 보겠습니다.


델리게이트 패턴이란?


객체 지향 프로그래밍에서 하나의 객체가 모든 일을 처리하는 것이 아니라 처리해야 할 일 중 일부를 다른 객체에 넘기는 것을 뜻합니다.

 

또 글로만 이야기 하니깐 와닿지 않죠??

 

 

우선 라벨, 버튼, 텍스트 필드를 아래와 같이 메인 스토리 보드에 배치합니다!

 

 

텍스트 필드에 텍스트를 쓰고 버튼을 누르면 해당 텍스트를 라벨에 나오도록 할겁니다!

 

먼저 아래와 같이 Outlet 변수를 만들고, @IBAction 함수를 만들어 줍니다.

함수 내부 코드는 "라벨에 텍스트 필드에 있는 값을 써주겠다" 라는 뜻 입니다.

 

 

그렇게 하고 실행을 시키면 아래와 같이 라벨과 텍스트 필드의 값이 동일하게 나옵니다!

 

 

이제 delegate를 사용해 볼까요????

 

아래와 같이 UITextFieldDelegate 프로토콜을 채택해 준 후 textFieldShouldReturn 함수를 추가해줍니다.

 textFieldShouldReturn은 UITextFieldDelegate 안에 정의되어있는 함수입니다.

동작을 대신해 줄 함수를 프로토콜에서 불러와 안에 구현만 하면됩니다.

 

 

그 후 실행한 후 엔터를 누르면 ( 버튼 X)

이렇게 잘 옮겨지게 됩니다!!

 

 

 

 

참고 사이트

docs.swift.org/swift-book/LanguageGuide/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID276

bite-sized-learning.tistory.com/118

zeddios.tistory.com/8

www.boostcourse.org/mo326/lecture/16856

the-brain-of-sic2.tistory.com/9?category=779576

magi82.github.io/ios-delegate/

 

 

 

'iOS' 카테고리의 다른 글

[iOS] AVKit과 AVFoundation  (1) 2023.01.03
[iOS] Navigation Controller  (1) 2023.01.03
[iOS] Cocoa Touch Framework  (2) 2023.01.02
[iOS] Code base로 UI 구현 (StoryBoard를 사용하지 않고 UI 구현하기)  (0) 2023.01.02
[iOS] UICollectionView  (0) 2023.01.02