4T2F / ThinkBig2

🌟씽크빅 2팀 스터디 🌟
2 stars 0 forks source link

Swift의 @dynamicCallable과 @dynamicMemberLookup에 대해 설명해주세요. #21

Open Phangg opened 7 months ago

Phangg commented 7 months ago

Swift의 @dynamicCallable@dynamicMemberLookup에 대해 설명해주세요.

Phangg commented 7 months ago

@dynamicCallable

사용 예시

dynamicallyCall(withArguments: ) 메서드를 사용

@dynamicCallable
struct DynamicCallableExample {
    var persons: [String: String]

    func dynamicallyCall(withArguments args: [String]) {
        // TODO: - 구현 예정
    }
}

let layTheGroundWork = DynamicCallableExample(
    persons: [
        "phang": "Ateen",
        "hamfan": "Ateen",
        "kmh": "Ateen",
        "xohxe": "Study",
        "manchae": "Study",
    ]
)

// 구조체의 생성(initialize)이 아닌, 인스턴스 호출
print(layTheGroundWork())
//
print(layTheGroundWork("phang")) 
print(layTheGroundWork("manchae")) 
@dynamicCallable
struct DynamicCallableExample {
    var persons: [String: String]

    // persons 라는 dictionary 에서 value 를 찾아 출력하도록 함 ( 옵셔널은 빈 문자열 "" 로 처리 )
    func dynamicallyCall(withArguments args: [String]) {
        args.forEach {
            print(persons[$0] ?? "")
        }
    }
}

let layTheGroundWork = DynamicCallableExample(
    persons: [
        "phang": "Ateen",
        "hamfan": "Ateen",
        "kmh": "Ateen",
        "xohxe": "Study",
        "manchae": "Study",
    ]
)

print(layTheGroundWork("phang"))              // Ateen
print(layTheGroundWork("manchae", "xohxe"))   // Study Study ( 실제 출력은 한줄씩 출력 )

dynamicallyCall(withKeywordArguments: )

@dynamicCallable
struct DynamicCallableExample {
    var persons: [String: String]

    // persons 라는 dictionary 의 값을 가져오도록.. ( 옵셔널 빈 문자열로 처리 )
    func dynamicallyCall(withKeywordArguments args: [String: String]) {
        args.forEach {
            print(persons[$0.value] ?? "")
        }
    }
}

let layTheGroundWork = DynamicCallableExample(
    persons: [
        "phang": "Ateen",
        "hamfan": "Ateen",
        "kmh": "Ateen",
        "xohxe": "Study",
        "manchae": "Study",
    ]
)

print(layTheGroundWork("phang"))        // Ateen
print(layTheGroundWork("manchae"))      // Study
print(layTheGroundWork(a: "hamfan", b: "kmh", c: "xohxe"))      // Ateen Study Ateen
print(layTheGroundWork("hamfan", "kmh", "xohxe"))               // ERROR !!!!

dynamicallyCall(withArguments: ) 와 dynamicallyCall(withKeywordArguments: ) 메서드 둘 다 사용

@dynamicCallable
struct DynamicCallableExample {
    var persons: [String: String]

    func dynamicallyCall(withArguments args: [String]) {
        args.forEach {
            print("withArguments", persons[$0] ?? "")
        }
    }

    func dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, String>) {
        args.forEach {
            print("withKeywordArguments", persons[$0.value] ?? "")
        }
    }
}

let layTheGroundWork = DynamicCallableExample(
    persons: [
        "phang": "Ateen",
        "hamfan": "Ateen",
        "kmh": "Ateen",
        "xohxe": "Study",
        "manchae": "Study",
    ]
)

print(layTheGroundWork("phang"))        // withArguments Ateen
print(layTheGroundWork("manchae"))      // withArguments Study
print(layTheGroundWork(a: "hamfan", b: "kmh", c: "xohxe"))      // withKeywordArguments Ateen Study Ateen
print(layTheGroundWork("hamfan", "kmh", "xohxe"))               // withArguments Ateen Study Ateen


@dynamicMemberLookup

사용 예시

@dynamicMemberLookup
struct DynamicMemberLookupExample {
    var persons: [String: String]

    // subscript 처리 + 이번에는 옵셔널 반환으로 처리 / return 생략
    subscript(dynamicMember arg: String) -> String? {
        get {
            persons[arg]
        }
        set {
            persons[arg] = newValue
        }
    }
}

var layTheGroundWork = DynamicMemberLookupExample(
    persons: [
        "phang": "Ateen",
        "hamfan": "Ateen",
        "kmh": "Ateen",
        "xohxe": "Study",
        "manchae": "Study",
    ]
)

// subscript 을 사용
print(layTheGroundWork[dynamicMember: "phang"])     // Optional("Ateen")
// @dynamicMemberLookup 을 사용
print(layTheGroundWork.phang)                       // Optional("Ateen")
// nil 인 경우
print(layTheGroundWork.ciu)                         // nil

@dynamicMemberLookupKeyPath 같이 사용하기

코드

struct StudyGroup {
    let subject: String
    let location: String
}

@dynamicMemberLookup
struct Person {
    let name: String
    let age: String
    let group: StudyGroup

    // T -> 제네릭 사용
    subscript<T>(dynamicMember keyPath: KeyPath<StudyGroup, T>) -> T {
        group[keyPath: keyPath]
    }
}

let studyGroup = StudyGroup(subject: "iOS", location: "Discord")
let phang = Person(name: "changjun", age: "27", group: studyGroup)

print(phang.subject)        // iOS
print(phang.location)       // Discord
print(phang.name)           // changjun