관리 메뉴

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

[iOS - swift] @dynamicCallable 개념 (dynamicallyCall) 본문

iOS 응용 (swift)

[iOS - swift] @dynamicCallable 개념 (dynamicallyCall)

jake-kim 2024. 3. 15. 01:19

@dynamicCallable 개념

  • Factory 패턴과 유사하지만 더욱 진화한 형태
    • 한 예제로 enum으로 type을 명시하고, 메소드를 static으로하여 특정 값을 생성하는 유형
enum SomeModelFactory {
    static func make() -> Int {}
}
  • 아래에서 더 알아볼 dynamicCallable을 사용한 SomeModelFactory를 사용하면 별도의 메서드 호출 없이, 해당 인스턴스에 소괄호와 함께 값을 넣어서 바로 사용이 가능
    • 값을 넣을때 argument label을 미리 모델에서 정의해준 값이 아닌 동적으로 아무 값이나 사용도 가능 (아래 c1(a:1, 2)) 예제에서 "a"값도 사용하는쪽에서 "b", "c" 아무런 값을 넣어도 무방
let c1 = SomeModelFactory()
print(c1)
print(c1())
print(c1(1, 2))
print(c1(a: 1, 2))

/*
 Model()
 0
 2
 ["": 2, "a": 1]
 */
  • 응용하면 좋은 곳: 앱 로그
    • 아래처럼 구현하면 age라는 필드를 따로 AppLog에서 "age"라는 필드를 지정할 필요도 없고 사용하는쪽에서 확장성 있게 구현이 가능
AppLog(age: 1)

@dynamicCallable 사용 방법

  • proprety wrapper 사용하던것처럼 struct같은 키워드 위에 @dynamicCallable을 붙여서 사용
    • 단, 이 키워드를 붙이면 메서드 정의가 필요
// error: @dynamicCallable attribute requires 'SomeModelFactory' to have either a valid 
// 'dynamicallyCall(withArguments:)' method or 'dynamicallyCall(withKeywordArguments:)' method

@dynamicCallable
struct SomeModelFactory {
}
  • @dynamicCallable 키워드는 struct, class, enum, protocol 모두 사용 가능

https://github.com/apple/swift-evolution/blob/main/proposals/0216-dynamic-callable.md

    • 위에서 정의하라는 메서드는 dynamicallyCall 이름인 두 가지 메서드
      • dynamicallyCall(withArguments:): 일반 값
      • dynamicallyCall(withKeywordArguments:): key-value 쌍으로 이루어져 있으며, 사용하는쪽에서 argument label이 key값으로 들어옴
  • 첫번째 메서드 정의
func dynamicallyCall(withArguments args: [Int]) -> Int {
    args.count
}

// 사용하는 쪽
let c1 = SomeModelFactory()
print(c1)
print(c1())
print(c1(1, 2))

/*
 Model()
 0
 2
*/
  • 두 번째 메서드 정의
func dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, Int>) -> [String: Int] {
    var dict = [String: Int]()
    args
        .forEach { dict[$0.key] = $0.value }
    return dict
}

// 사용하는 쪽
let c1 = SomeModelFactory()
print(c1(a: 1, 2))
// ["": 2, "a": 1]

 

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

* 참고

- https://github.com/apple/swift-evolution/blob/main/proposals/0216-dynamic-callable.md

Comments