섹션13: 프로토콜과 델리게이트 패턴 (복습)

인생노잼시기·2021년 7월 27일
0

📱Udemy iOS

목록 보기
14/20

protocols and extensions

UITextFieldDelegate가 protocol이라니? 머선일이고

프로토콜은 조건이 만족했을 때 주어지는 자격증명같은 것이다

protocal MyProtocol {
	//Define requirements
}
struct MyStruct: MyProtocol {}
class MyClass: MyProtocol {}
// 프로토콜은 class와 struct 모두에서 사용이 가능
// 추상메서드만 사용해야하고 상속받는 경우 무조건 구현해야 한다
protocol CanFly {
    func fly()
}

class Bird {
    
    var isFemale = true

    func layEgg() {
        if isFemale {
            print("new bird")
        }
    }

}

// 상속 inheritance
// 상속은 class에서는 되지만 struct에서는 불가능 -> protocol 사용
class Eagle: Bird, CanFly {
    func fly() {
        print("the eagle flaps")
    }
    
    func soar() {
        print("glide")
    }

}

class Penguin: Brid {
    func swim() {
        print("paddle")
    }
}

//비행기와 새들이 날아다니는 박물관
//CanFly 프로토콜을 데이터타입으로 넘김(adopt)
struct FlyingMuseum {
    func flyingDemo(flyingObject: CanFly) {
        flyingObject.fly()
    }    
}

struct  Airplane: CanFly {
    func fly() {
        print("the airplane flys")
    }
}

let myEagle = Eagle()
myEagle.fly()

// 펭귄도 새의 일종이지만 날지 못함
// 상속받고 싶지만 모든 속성이 일치하지 않는 문제 발생
// fly를 CanFly프로토콜에서 사용하고 Bird만 상속받아 문제 해결
let myPenguin = Penguin()
myPenguin.layEgg()
myPenguin.swim()
//myPenguin.fly()

let museum = FlyingMuseum()
let airplane = Airplane()
airplane.fly()
museum.flyingDemo(flyingObject: airplane)

https://docs.swift.org/swift-book/LanguageGuide/Protocols.html

The Delegate Design Pattern

디자인 패턴이란?
A proven solution to a common problem 흔한 문제를 해결하기 위해 증명된 해결방법

프로토콜을 사용함
프로토콜 UITextFieldDelegate를 adopt했기 때문에 textFieldDidBeginEditing()을 구현해야 한다 (위에서 fly()메서드와 동일) required implementation

왜 UITextField는 viewControler에게 권한을 위임했을까?
문제상황:

어떤 클래스에서 UITextField를 사용하는지 알 수 없기 때문에
UITextField를 사용자가 사용할 때마다
아무 클래스에서나 동작을 알아챌 수 있도록 하기 위함이다 (UITextField의 재사용성)
UITextField는 바뀔 필요가 없다
UITextField 프로토콜 데이터 타입을 선언하고
클래스에 상관없이 delegate.textFieldDidBeginEditing()을 trigger하면 된다

How does the WeatherViewController actually sign up to be notified by the text field?
텍스트 필드에 의한 알람을 받기 위해 뷰컨트롤러는 어떻게 참여하는가?
해결방법: delegate pattern
let textField = UITextField() // 재사용가능한 UI text field object가 필요하다
textField.delegate = self // textField의 대리자를 viewController로 설정한다
뷰컨트롤러는 프로토콜을 상속받아 메서드를 구현하고
텍스트필드에서 메서드를 실행시키면 된다

Top Secret: Apple's code (147강)

UIKit, UITextField, UILable, UIButtons 등은 애플 소유의 코드이다 (오픈소스가 아니다)
어떻게 UITextField가 delegate를 구현하고 delegate.textFieldDidBeginEditing()을 유발하는지 알 수 없다

delegate는 AdvancedLifeSupport(protocol(qualification))를 취득한 사람(class)만 가질 수 있다
EmergencyCallHandler(textField)는 누가 delegate를 가졌는지 상관없이 명령을 내리면 된다

File> New> Project > macOS > command Line Tool

// CPR 자격증 (프로토콜)
protocol AdvancedLifeSupport {
    func performCPR()
}

class EmergencyCallHandler {
    var delegate: AdvancedLifeSupport?
    
    func assessSituation() {
        print("Can you tell me what happend?")
    }
    
    func medicalEmergency() {
        delegate?.performCPR()
    }
}

struct Paramedic: AdvancedLifeSupport {
    init(handler: EmergencyCallHandler) {
        handler.delegate = self
    }
    
    func performCPR() {
        print("chest compressions")
    }
}

class Doctor: AdvancedLifeSupport {
    init(handler: EmergencyCallHandler) {
        handler.delegate = self
    }
    func performCPR() {
        print("doctors do chest compressions")
    }
    func useStethescope() {
        print("heart sound")
    }
}

class Surgeon: Doctor {
    override func performCPR() {
        super.performCPR()
        print("Sings")
    }
    func useElectricDrill() {
        print("Whirr")
    }
}

let emilio = EmergencyCallHandler()

//let pete = Paramedic(handler: emilio)
let angela = Surgeon(handler: emilio)
// pete인지 angela인지 상관없이 emilio가 하는 일은 동일하다

emilio.assessSituation()
emilio.medicalEmergency()

Swift extensions

extend the functionality: 기능 추가
기차 노선 연장하는 것과 비슷
기능을 추가하려는 타입의 구현된 소스 코드를 알지 못하거나 볼 수 없다 해도, 타입만 알고 있다면 그 타입의 기능을 확장할 수도 있습니다.

import UIKit

extension UIButton {
    func makeCircular() {
        self.clipsToBounds = true
        self.layer.cornerRadius = self.frame.size.width / 2
    }
}

let button = UIButton(frame: CGRect(x: 0, y:0, width: 50, height: 50))
button.backgroundColor = .red

button.makeCircular()

class, protocol, extension이 어떻게 다른가?

  • class는 class 데이터 타입만 상속이 가능한 반면,
    protocol과 extension은 모든 데이터 타입을 상속할 수 있다

  • class는 상속 후 재정의 가능하지만(수직), extension은 상속 후 재정의가 불가능하다(수평)
    예시 Double 타입
    그러면 Double 타입이 채택하고 준수해야 하는 수많은 프로토콜은 어디로 갔을까요? 어디에서 채택하고 어디에서 준수하도록 정의되어 있을까요?
    당연히 답은 익스텐션입니다.
    이처럼 스위프트 표준 라이브러리 타입의 기능은 대부분 익스텐션으로 구현되어 있습니다.

  • protocol은 중괄호를 포함한 init하지 않아서 상속 받은 후에는 반드시 구현해야 한다면,
    extension은 initialize할 수 있다.

Adoptiong Protocols

뷰 컨트롤러는 다양한 프로토콜을 상속받고 있는데
각각의 프로토콜을 분리해서 상속한 후 확장하면 컨트롤러를 깔끔하게 쓸 수 있다.

extension 확장할 타입 이름: 프로토콜1, 프로토콜2, 프로토콜3 {
    // 프로토콜 요구사항 구현
}
profile
인생노잼

0개의 댓글