본문 바로가기

개발/Swift

[Swift] Protocol 알아보기

반응형

참고!

Mutating = 객체를 바꾸는 함수
get, set = get은 읽기 전용, set은 쓰기 전용 
ㄴ 단 set은 var로 선언된 것에만 가능하다.
ㄴ set이 있다면 자동으로 mutating이 들어가있다고 볼 수 있다.

구조체는 값 타입이다.
힙 내부에 존재하지 않아서 구조체를 전달할 때 사본이 복사된다.
하지만 스위프트에선 CopyAndWrite 기능으로 내용이 변경되었을 때만 복사해서 쓴다.

 

Protocol 

- 프로토콜은 언제 어디서 사용하고 왜 사용하는지 등의 용도가 굉장히 중요하다 
- 프로토콜은 API에서 원하는 것을 불러오는 방식이다. 구현이라기 보다 변수와 함수의 리스트다.
- API를 매우 유연하게 만든다. 구별 가능함에 대한 권한을 주는데 유용하다.
- 변수와 함수 선언만 하기 때문에 저장 공간이 따로 없고 데이터의 상속도 없다.
- 간단하게 말하면 하나의 타입이다. 

- Objective-C에서 프로토콜은 메소드가 선택적이라 메소드나 변수를 구현할지 말지 선택할 수 있다.
Swift의 프로토콜 위에 @objc를 붙이면 Objective-C의 프로토콜 형태로 사용할 수 있다 (어떤 메소드를 구현할지 말지)
Objective-C의 프로토콜은 블라인드 형식의 뷰와 컨트롤러 사이의 커뮤니케이션에서 사용한다.

 

프로토콜 선언

- 구현은 클래스와 비슷하다
- 프로토콜에서 상속의 의미는 해당 프로토콜을 사용하기 위해 추가적으로 구현해야하는 프로토콜을 의미한다
- 프로토콜은 코드가 없는 순수한 선언이다

- 변수를 넣을때 읽기와 쓰기가 가능한지 알려주는 get set을 사용한다
- struct에 의해 구현되어서 그 내용을 수정한다면 mutating 표시를 써줘야한다
- protocol 뒤에 붙는 :class 는 클래스에서만 구현되는 프로토콜을 의미한다. (mutating을 쓸 일이 없음을 알린다.)
- struct의 경우 슈퍼 클래스가 없기 때문에 enum이나 struct 뒤에 프로토콜을 쓴다.
- 클래스에 init을 쓰는 경우 서브 클래스에서 혼동할 수 있기에 required init으로 표시해주어야한다. 

 

protocol Moveable {
    mutating func move(to point: CGPoint)
}

class Car : Moveable { // 클래스는 참조 타입이라 mutating이 필요 없다
    func move(to point: CGPoint) { _ }
    func changeOil()
}

struct Shape: Moveable {
    mutating func move(to point: CGPoint) { _ }
    func draw()
}

let prius : Car = Car()
let square : Shape = Shape()

var thingToMove : Moveable = prius // prius는 Moveable 프로토콜을 구현하기 때문에 가능하다
thingToMove.move(to: _) //가능
thingToMove.changeOil() // 불가능, Moveable에 해당되지 않음
thingToMove = squre


let thingsToMove : [Moveable] = [prius, squre] // 가능

func slide(slider: Moveable){
    let positionToSlideTo = _
    slider.move(to: positionToSlideTo)
}
 
slide(prius) // 가능
slide(squre) // 가능


func slipAndSlide(x: Slippery & Moveable) // 여러개의 프로토콜을 사용하는 방법 : &
slipAndSlide(x: prius)


 

 

UIScrollView의 delegate 예제

컨트롤러는 힙에 유지시키고 있는 뷰를 가리키는 많은 포인터를 가지고 있다
자신의 will, did, should 를 받는 것을 가리킨다.
weak 으로 선언된 변수가 힙을 빠져나가려고 하면 nil로 바꾸고 더 이상 메시지를 보내지 않는다.
위 과정을 거쳐 뷰는 컨트롤러를 힙 안에 두지 않게 된다.

scrollView.delegate는 UIScrollViewDelegate를 따른다.
프로토콜을 따르기에 myViewController에서 자기 자신을 delegate로 설정할 수 있다.
뷰가 will, did 등을 컨트롤러한테 보낼 수 있게 된다.

weak var delegate : UIScrollViewDelegate?

@objc protocol UIScrollViewDelegate {
    optional func scrollViewDidScroll(scrollView: UIScrollView)
    optional func viewForZooming(in scrollView: UIScrollView) -> UIView
    ...
}

class myViewController : UIViewController, UIScrollViewDelegate { _ }
...
scrollView.delegate = self
...

 

 

Hashable 프로토콜

Hashable은 Equatable이라는 다른 프로토콜로부터 온 것이다. 
무언가를 해시할 때 고유한 해시 같아 보이지만 그것을 보장할 수 없어서-
등호를 사용해 실제로 두 개가 동일한지 확인해야만 한다.
만약 어떤 것이 해시 가능하려면, 다른 어떤 것과 동일한지 먼저 확인해야한다.

protocol Hashable : Equatable {
    var hashValue: Int { get } // 받기 전용 변수로 해시를 의미한다.
}

 

Equatable 프로토콜

하나의 함수를 가지고 있고 정적 함수라서 타입에 관여한다.
self가 곧 타입이다. 만약 Int로 구현한다면 self는 Int가 된다.
해시 가능하기 위해서는 Equatable이 필요하다.

protocol Equatable {
    static func ==(lhs: Self, rhs: Self) -> Bool
}

 

 

출처 www.edwith.org/swiftapp/lecture/26622

반응형

'개발 > Swift' 카테고리의 다른 글

[Swift] NSAttributedString  (0) 2021.02.25
[Swift] 문자열 색인  (0) 2021.02.25
[Swift] 프로토콜 지향 프로그래밍  (0) 2020.08.13
[Swift] Typealias  (0) 2020.03.12
[Swift] Protocol  (0) 2020.03.08