Open Phangg opened 7 months ago
@dynamicCallable
@dynamicCallable
을 사용하면, 인스턴스 호출이 가능dynamicallyCall(withArguments: )
와 dynamicallyCall(withKeywordArguments: )
메서드를 필수로 사용
( 경우에 따라, 하나만 혹은 둘 다 사용 )@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"))
dynamicallyCall(withArguments: )
메서드에서 [String] 을 프로퍼티의 타입으로 받고 있는데, "phang" 은 String 인데..?layTheGroundWork.dynamicallyCall(withArguments: ["phang"])
로 작동@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(withArguments: )
메서드에 제약조건이 있음@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 !!!!
persons[$0.value]
에서 value 라고 하는게 맞아..?
일단.. 이것도 마찬가지로 layTheGroundWork.dynamicallyCall(withKeywordArguments: ["": "phang"])
로 코드가 실행이 됨
이때, args 의 value 를 이용해서 persons 의 value 를 구하게 됨
근데 그러면 왜 key 가 "" 로 들어갈까? ( 그냥 그렇게 되는거임.. )
layTheGroundWork(a: "hamfan", b: "kmh", c: "xohxe")
처럼 key 값을 직접 지정할 수 있음layTheGroundWork("hamfan", "kmh", "xohxe")
는 왜 에러일까?
음.. 그 이유는 프로퍼티의 타입이 중복된 키값을 허용하지 않는 dictionary 이기 때문!
만약 저 코드가 에러가 나지 않기를 바란다면, 위에서 말한대로 키값을 설정하거나, 중복 키값을 허용하는 KeyValuePairs<String, String>
타입을 사용하면 됨@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
@dynamicCallable
보다 먼저 소개된 Attribute이름
에 대해서 .이름
같은 형태로 사용 가능 함 ( dot syntax )subscript (dynamicMemberLookup: )
메서드를 필수로 사용
subscript 를 모른다면, @JooYoungNoh 가 정리한 subscript 관련 스터디 내용 을 보고 오자..!
사실 이 subscript 가 사용 가능한 이유는 지난주에 제가 진행한 스터디 내용 의 Custom Collection 파트를 보면 subscript 가 Collection 의 기본 구현 메서드임을 알 수 있음@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
@dynamicMemberLookup
때문에, layTheGroundWork 에는 .phang
, .ciu
으로 접근할 수 있는 프로퍼티가 없지만 dot syntax
를 사용 할 수 있는 것..!dynamicMember
프로퍼티도 제약이 있는데, ExpressibleByStringLiteral 프로토콜을 채택하고 있어야 함
@dynamicMemberLookup
과 KeyPath
같이 사용하기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
Swift의
@dynamicCallable
과@dynamicMemberLookup
에 대해 설명해주세요.@dynamicCallable
을 사용하여 사용자 정의 호출 가능 타입을 만드는 방법과 사용 예시를 들어주세요.@dynamicMemberLookup
을 활용하여 동적으로 속성에 접근하는 방법과 실제 사용 사례를 소개해주세요.