프로토콜이란?
기능의 조각 또는 특정 직무를 입히는 다른 요구사항들과 메서드 프로퍼티들의 청사진이다.
=> 프로토콜을 채택하는 타입은 이런 프로퍼티와 메서드를 가지는걸 보장합니다 라는 자격증과 비슷하다.
=> 프로토콜은 타입을 묶는 용도로도 사용하고 타입간의 결합도를 낮추기 위해도 사용한다.
[특징]
- 프로토콜은 열거형, 클래스, 구조에 의해 채택될 수 있다.
- 프로퍼티는 get인지 get set인지를 구분해주며 메서드는 이름과 매개변수 및 반환타입까지만 지정하- 여 본문은 구현하지않는다.
- 프로퍼티 선언지 let선언이 안되는이유 중 하나는 연산프로퍼티는 let으로 설정할 수 없다.
- getter는 무조건 가져야하며. set만 설정하면 variable with a setter must also have a getter라는 오류 메세지가 나온다.
- 타입프로퍼티는 static을 사용하고 class와 static을 구분하지않으며 class가 붙으면 상속시 서브클래스에서 재정의가 가능하다.
- gettable은 읽을 수 있으며 get set은 읽고 쓸수있는 기능을 가지는데 get이 읽기 전용만을 의미하지는 않는다. 실제로 채택받아서 사용할때 읽고 쓰기 모두 사용해도 문제가 없다.
- 프로퍼티에 get set을 설정받은 프로토콜을 채택하여 사용할때 프로퍼티를 get속성만으로 사용하게되면 준수하지못하다는 컴파일 오류가 난다. set의 속성을 넣어주는 이후로는 읽기 전용으로 사용할 수 없다는 것이다.
- get set중 get만 설정해놓으면 타입에서 채택받아서 사용할때 let을 설정할 수도 있다. 추가로 private(set)으로도 설정이 가능한데 private으로는 설정할 수 없다. 왜냐하먄 읽을 수 있는 자격이 있는건데 예를들어서 자동차운전면허를 땃는데 보여줘야 증명이되지 보여질 수 없으면 get이라는 성질의 의미가 없어지기 때문이다.
- protocol은 타입으로도 사용할 수 있으며 &을 이용하여 여러프로토콜을 중첩하여 사용도 가능하다. ex) let quokka: FullyName&Animal
- protocol을 채택한 내부의 기능들은 사용할 수 있으나 타입은 사용될 수 없다. 그럴땐 다운캐스팅으로 사용해 볼 수 있다.
- protocol내에 메서드를 정의할때 mutating을 붙여주면 채택받은 타입내에서 메서드를 사용할때 mutating을 안붙여줘도된다.
- class의 경우 init을 가지는 프로토콜을 재택하였을때 required를 붙이는게 필수로 요구된다. 하지만 final class는 필수로 요구되지않는다.
[프로토콜의 사용시 유의할점]
SOLID원칙 중 하나인 타입은 하나의 타입만을 준수하여 결합도를 낮춘다. 이는 코드 수정에 매우도움이되며 유지보수에 좋다.
그렇다고 모든 타입을 프로토콜을 사용하는게 좋을까 ??? 또 그렇지는 않다. 무조건 프로토콜 먼저 만들어 버린다고 하면 오버 엔지니어링이 발생할 수 있다. 정말 확장 가능성이 적은데 프로토콜로 확장가능성을 시도한다면 인력 및 시간낭비가 발생할 수 있다. 그래서 적절히 고려해야할 필요가 있다. 고로 무조건 결합도가 높다고 해서 안좋고 낮다고해서 좋다고 볼 수 는 없는것이다. 그치만 연습하는 입장에서는 결합도를 낮춰보는 연습이 필요한건 사실이기때문에 결합도를 낮춰보는 연습을 시도해보고 현업에 가서는 사용해야할 필요가 있는지 적절히 고려해보는것이 좋을것 같다.
# Delegate(위임)
[정의]
- 위임은 클래스나 구조체가 일부책임을 다른 유형의 인스턴스에 넘길 수 있도록 하는 디자인 패턴이다.
Delegate이용한 데이터 전달
[SecondView에서 FirstView로 돌아올때 데이터를 전달하면서 창을 닫는다.]
[첫번째 뷰에서 하는일 ]
- protocol 채택
- 실제구현
- 대리자 위임
extension UIViewController {
static var identifier: String {
return String(describing: self)
}
}
class FirstViewController: UIViewController, DeliveryDataProtocol {
func deliverydata(_ data: String) {
dataLabel.isHidden = false
dataLabel.text = data
}
@IBOutlet weak var dataLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
dataLabel.isHidden = true
dataLabel.textColor = .white
}
@IBAction func moveSecondView(_ sender: Any) {
guard let secondVC = self.storyboard?.instantiateViewController(withIdentifier: SecondViewController.identifier) as? SecondViewController else { return }
secondVC.delegate = self
present(secondVC, animated: true, completion: nil)
}
[두번째 뷰에서 하는일]
- 타입이 protocol인 property생성
- delegate사용
protocol DeliveryDataProtocol: AnyObject {
func deliverydata(_ data: String)
}
class SecondViewController: UIViewController {
var delegate: DeliveryDataProtocol?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .yellow
}
@IBAction func dissmissButton(_ sender: Any) {
delegate?.deliverydata("오늘 하루도 화이팅입니다!!")
dismiss(animated: true, completion: nil)
}
}
// 출력결과 -> FirstView에서 -> SecondView이동 -> SecondView화면닫기 -> FirstView에 "오늘 하루도 화이팅입니다!!" 데이터가 출력

- Reference
'iOS' 카테고리의 다른 글
[iOS] TableView만드는 첫번째 방법(feat. 임의의 Cell 지정) (0) | 2022.04.10 |
---|---|
[iOS] TableView란? 공식문서를 읽어보자 (0) | 2022.04.10 |
[에러]unrecognized selector sent to instance (0) | 2022.03.25 |
[iOS] Retain Cycle에 대해 알아보자(Feat. Delegate) (0) | 2022.03.11 |
[iOS] H.I.G(Human Interface Guidelines) iOS 테마 읽기 (0) | 2022.02.16 |