Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] Type Erase 테크닉 (some 키워드와 any 키워드 사용 방법, 제네릭, 프로토콜, associatedtype, existential any) 본문

iOS 응용 (swift)

[iOS - swift] Type Erase 테크닉 (some 키워드와 any 키워드 사용 방법, 제네릭, 프로토콜, associatedtype, existential any)

jake-kim 2023. 4. 3. 01:54

some 키워드와 any 키워드

  • 함수의 파라미터에 some과 any 키워드를 사용하면 자동으로 타입을 추론할 수 있게끔 컴파일러가 동작
  • 아래에서 알아볼 특정 케이스에서 protocol을 사용할때 컴파일에러가 나는 케이스가 존재하는데 이 컴파일에러를 없애고 간편하게 사용할 수 있도록 돕도록 나온것이 some과 any 키워드
  • 컴파일러가 더욱 유연하게 구체적인 타입을 추론할수 있게 만드는 키워드

Protocol 타입 컴파일 에러

  • 매개변수에 Protocol 타입을 직접 참조할 수 없는 케이스가 존재
    • 왜 참조를 할 수 없을까?
    • 프로토콜이 associatedtype을 선언하면 컴파일러가 해당 프로토콜을 참조를 제한하기 때문

프로토콜 내부에 associatedtype이 있는 경우, 이 프로토콜을 바로 참조할 수 없음

  • 만약 associatedtype이 프로토콜 내부에 없다면 바로 참조가 가능

에러 발생 x (정상 동작)

  • swift5.7 전까지는 protocol에서 associatedtype을 사용하면 generic를 사용하여 해결해야함

generic키워드를 사용하여 protocol을 참조 할 수 있도록 구현

  • 위 컴파일에러는 some과 any 키워드를 사용하면 바로 해결이 가능

some과 any 키워드를 사용하여 컴파일 에러 해결

예제 2)

  • users라는 Collection을 받고 내부 타입이 User로 지정하고 싶은 경우?
    • Collection의 Element는 associatedtype이라서 Collection 프로토콜을 그대로 참조할수 없는 상태
// Collection 내부에 있는 Element는 associatedtype이라 Collection 프로토콜을 바로 참조하면 컴파일에러 발생

protocol Collection<Element>: Sequence {
    associatedtype Element
    ...
}

Collection을 바로 참조하여 컴파일 에러 발생

  • swift5.7전까지는 generic을 사용해야했어서 선언부가 지저분한 상태

  • some과 any를 사용하면 해결

some 키워드와 any 키워드의 차이

  • 위에서 알아본대로 some과 any 키워드는 컴파일에러를 줄이고 간편하게 사용할 수 있도록 도와주는 역할
  • 차이점은?
    • some 키워드 - property, subscript, function에서만 사용 가능
    • any 키워드 - property, subscript, function, 다양한 키워드에서도 사용이 가능

ex) tableView에 들어갈 items 프로퍼티를 정의할때 Element타입을 프로토콜로 하고 싶은 경우?

  • 단, 이 protocol안에는 associatedtype이 존재
protocol ImageItem {
    associatedtype Item
    var image: Data { get }
    var item: Item { get }
}
  • 위에서 알아본대로 이 프로토콜은 함수의 파라미터에서 그대로 참조하면 컴파일에러가 발생

  • some 키워드를 사용해도, some은 [] 키워드 안에서 사용하지 못하므로 컴파일에러

  • any 키워드를 사용하면 컴파일에러 x

결론

  • associatedtype이 있는 protocol을 그대로 참조하면 컴파일 에러가 발생
  • 이 컴파일에러는 예전에 generic을 사용했지만 generic을 사용하면 복잡해지므로 some이나 any 키워드 사용할것
    • some 키워드 - property, subscript, function에서만 사용 가능
    • any 키워드 - property, subscript, function, 다양한 키워드에서도 사용이 가능 (array, dictionary, set)
  • any 키워드는 generic을 따로 선언해주지 않아도 되는 편리함이 존재
protocol ABC {
    associatedtype MyType
}

// 기존 - 제네릭 선언해야함
func printValue<T: ABC>(type: T) {
    print(type)
}

// any 키워드 사용 - 제네릭을 따로 선언해주지 않아도 됨
func printValue2(type: any ABC) {
    print(type)
}

* 전체 코드: https://github.com/JK0369/ExTypeErase

* 참고

https://www.swiftbysundell.com/questions/referencing-generic-protocols/

https://www.swiftbysundell.com/articles/referencing-generic-protocols-with-some-and-any-keywords/

Comments