본문 바로가기
iOS/Swift배우기

[Swift] Protocol 배우기

by 붕어사랑 티스토리 2024. 3. 19.
반응형

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols/

 

Documentation

 

docs.swift.org

 

 

1. 프로토콜이란?

 

그냥 다른언어 인터페이스랑 똑같다고 생각하면 된다. 그런데 Swift 이놈은 용어가 너무 다르다.

 

 

생긴건 아래와 같다

protocol SomeProtocol {
    var mustBeSettable: Int { get set }
    var doesNotNeedToBeSettable: Int { get }
}

 

protocol AnotherProtocol {
    static var someTypeProperty: Int { get set }
}

 

  • 프로토콜 안에있는 변수들은 Property Requirement 라고 한다.
  • get, set 키워드로 gettable과 settable을 지정해 줄 수 있다.
  • static이 붙은 변수 이름은 type property라고 하며, 안붙으면 instance property 라고 한다
  • type property를 구현할때도 항상 static을 붙여주어야 한다.

 

 

2. Function Requirements

 

물론 함수도 아래처럼 선언이 가능하다

 

protocol SomeProtocol {
    static func someTypeMethod()
    func someInstanceMethod() -> Double
}

 

 

static이 붙은건 type method라고 한다. 안붙은건 instance method

 

 

 

 

 

 

3. Mutating Function Requirements

 

 

Structureenumerations은  value type이다. 클래스와 같이 참조 타입이 아니라는 뜻.

value type은 인스턴스 메소드가 값을 바꾸려고 하면 에러를 낸다. 이럴때 mutating이라는 키워드를 항상 붙여줘야 한다.

프로토콜에서도 만약 mutating을 하려 한다면 아래처럼 키워드를 붙여주어야 한다.

 

protocol Togglable {
    mutating func toggle()
}

enum OnOffSwitch: Togglable {
    case off, on
    mutating func toggle() {
        switch self {
        case .off:
            self = .on
        case .on:
            self = .off
        }
    }
}
var lightSwitch = OnOffSwitch.off
lightSwitch.toggle()
// lightSwitch is now equal to .on

 

 

 

 

 

4. Initializer Requirements

생성자도 아래처럼 프로토콜에 작성 가능하다. 이때 클래스에서 구현할 때 반드시 required 키워드를 붙여주어야 한다!

 

 

protocol SomeProtocol {
    init(someParameter: Int)
}


class SomeClass: SomeProtocol {
    required init(someParameter: Int) {
        // initializer implementation goes here
    }
}

 

 

아래와 같이, 오버라이드도 하고 프로토콜도 따라야 한다면, required와 override를 같이 적어준다

 

protocol SomeProtocol {
    init()
}


class SomeSuperClass {
    init() {
        // initializer implementation goes here
    }
}


class SomeSubClass: SomeSuperClass, SomeProtocol {
    // "required" from SomeProtocol conformance; "override" from SomeSuperClass
    required override init() {
        // initializer implementation goes here
    }
}

 

 

 

5. Delegation

아래 코드는 공식문서에서 나오는 Delegation 예제이다. 애플은 delegation pattern 정말 좋아한다. 그냥 참고용으로 보는걸 추천

 

 

다만 아래 예제에서 배워갈만한 부분은 weak 키워드이다! Strong Reference Cycle(대충 순환참조)을 방지하기 위해 항상 weak을 써야함을 잊지 말자

 

class DiceGame {
    let sides: Int
    let generator = LinearCongruentialGenerator()
    weak var delegate: Delegate?


    init(sides: Int) {
        self.sides = sides
    }


    func roll() -> Int {
        return Int(generator.random() * Double(sides)) + 1
    }


    func play(rounds: Int) {
        delegate?.gameDidStart(self)
        for round in 1...rounds {
            let player1 = roll()
            let player2 = roll()
            if player1 == player2 {
                delegate?.game(self, didEndRound: round, winner: nil)
            } else if player1 > player2 {
                delegate?.game(self, didEndRound: round, winner: 1)
            } else {
                delegate?.game(self, didEndRound: round, winner: 2)
            }
        }
        delegate?.gameDidEnd(self)
    }


    protocol Delegate: AnyObject {
        func gameDidStart(_ game: DiceGame)
        func game(_ game: DiceGame, didEndRound round: Int, winner: Int?)
        func gameDidEnd(_ game: DiceGame)
    }
}


class DiceGameTracker: DiceGame.Delegate {
    var playerScore1 = 0
    var playerScore2 = 0
    func gameDidStart(_ game: DiceGame) {
        print("Started a new game")
        playerScore1 = 0
        playerScore2 = 0
    }
    func game(_ game: DiceGame, didEndRound round: Int, winner: Int?) {
        switch winner {
            case 1:
                playerScore1 += 1
                print("Player 1 won round \(round)")
            case 2: playerScore2 += 1
                print("Player 2 won round \(round)")
            default:
                print("The round was a draw")
        }
    }
    func gameDidEnd(_ game: DiceGame) {
        if playerScore1 == playerScore2 {
            print("The game ended in a draw.")
        } else if playerScore1 > playerScore2 {
            print("Player 1 won!")
        } else {
            print("Player 2 won!")
        }
    }
}


let tracker = DiceGameTracker()
let game = DiceGame(sides: 6)
game.delegate = tracker
game.play(rounds: 3)
// Started a new game
// Player 2 won round 1
// Player 2 won round 2
// Player 1 won round 3
// Player 2 won!

 

 

이외에도 너무 많지만.. 대충 여기까지만 알아도 개발가능할듯

반응형

'iOS > Swift배우기' 카테고리의 다른 글

[Swift] PropertyWrapper 사용법  (0) 2024.03.22
[SwiftUI] 자식에게 State 전달하기  (0) 2024.03.21
SwiftUI에서 {} 동작 원리  (0) 2024.03.20
[Swift] Generic이란  (0) 2024.03.20
[Swift] inout 파라미터  (0) 2024.03.20

댓글