클래스 유형을 함수 매개 변수로 전달하는 방법
웹 서비스를 호출하고 JSON 응답을 다시 객체로 직렬화하는 일반 함수가 있습니다.
class func invokeService<T>(service: String, withParams params: Dictionary<String, String>, returningClass: AnyClass, completionHandler handler: ((T) -> ())) {
/* Construct the URL, call the service and parse the response */
}
내가 달성하려는 것은이 Java 코드와 같습니다.
public <T> T invokeService(final String serviceURLSuffix, final Map<String, String> params,
final Class<T> classTypeToReturn) {
}
- 내가 성취하려는 것에 대한 메소드 서명이 올바른가?
- 더 구체적
AnyClass
으로, 매개 변수 유형으로 지정 하는 것이 올바른 일입니까? - 메서드를 호출하면
MyObject.self
returningClass 값으로 전달 되지만 컴파일 오류 "식의 유형 '()'을 'String'으로 변환 할 수 없습니다."
CastDAO.invokeService("test", withParams: ["test" : "test"], returningClass: CityInfo.self) { cityInfo in /*...*/
}
편집하다:
나는 사용하여 시도 object_getClass
holex에서 언급 한 바와 같이,하지만 지금은 얻을 :
오류 : " 'CityInfo.Type'유형이 'AnyObject'프로토콜을 준수하지 않습니다."
프로토콜을 준수하기 위해 무엇을해야합니까?
class CityInfo : NSObject {
var cityName: String?
var regionCode: String?
var regionName: String?
}
당신은 잘못된 방법으로 접근하고있다 : 스위프트에, 오브젝티브 C는 달리, 클래스가 특정 유형이, 심지어 상속 계층 구조를 가지고 (즉, 경우에 클래스 B
에서 상속 A
후 B.Type
로부터도 상속 A.Type
) :
class A {}
class B: A {}
class C {}
// B inherits from A
let object: A = B()
// B.Type also inherits from A.Type
let type: A.Type = B.self
// Error: 'C' is not a subtype of 'A'
let type2: A.Type = C.self
당신은 사용하지 말아야하는 이유 AnyClass
당신이 정말로 허용 할 않는 한, 어떤 클래스를. 이 경우 매개 변수와 클로저의 매개 변수 T.Type
사이의 링크를 표시하므로 올바른 유형은 returningClass
입니다.
실제로 대신에 AnyClass
이를 사용하면 컴파일러가 메소드 호출에서 유형을 올바르게 유추 할 수 있습니다.
class func invokeService<T>(service: String, withParams params: Dictionary<String, String>, returningClass: T.Type, completionHandler handler: ((T) -> ())) {
// The compiler correctly infers that T is the class of the instances of returningClass
handler(returningClass())
}
지금의 인스턴스를 구성의 문제가있을 T
전달할는 handler
: 당신이 시도하고 실행 코드를 지금 컴파일러가 불평 할 경우 T
와 작도하지 않습니다 ()
. 그리고 올바르게 : T
특정 초기화 프로그램을 구현하도록 요구하려면 명시 적으로 제한해야합니다.
이것은 다음과 같은 프로토콜로 수행 할 수 있습니다.
protocol Initable {
init()
}
class CityInfo : NSObject, Initable {
var cityName: String?
var regionCode: String?
var regionName: String?
// Nothing to change here, CityInfo already implements init()
}
그런 다음 일반 제약 조건을 invokeService
에서 <T>
로 변경하기 만하면 됩니다 <T: Initable>
.
팁
"표현식 '()'을 (를) '문자열'로 변환 할 수 없습니다"와 같은 이상한 오류가 발생하면 메서드 호출의 모든 인수를 자체 변수로 이동하는 것이 유용한 경우가 많습니다. 오류를 일으키는 코드를 좁히고 형식 유추 문제를 발견하는 데 도움이됩니다.
let service = "test"
let params = ["test" : "test"]
let returningClass = CityInfo.self
CastDAO.invokeService(service, withParams: params, returningClass: returningClass) { cityInfo in /*...*/
}
Now there are two possibilities: the error moves to one of the variables (which means that the wrong part is there) or you get a cryptic message like "Cannot convert the expression's type ()
to type ($T6) -> ($T6) -> $T5
".
The cause of the latter error is that the compiler is not able to infer the types of what you wrote. In this case the problem is that T
is only used in the parameter of the closure and the closure you passed doesn't indicate any particular type so the compiler doesn't know what type to infer. By changing the type of returningClass
to include T
you give the compiler a way to determine the generic parameter.
you can get the class of AnyObject
via this way:
Swift 3.x
let myClass: AnyClass = type(of: self)
Swift 2.x
let myClass: AnyClass = object_getClass(self)
and you can pass it as paramater later, if you'd like.
I have a similar use case in swift5:
class PlistUtils {
static let shared = PlistUtils()
// write data
func saveItem<T: Encodable>(url: URL, value: T) -> Bool{
let encoder = PropertyListEncoder()
do {
let data = try encoder.encode(value)
try data.write(to: url)
return true
}catch {
print("encode error: \(error)")
return false
}
}
// read data
func loadItem<T: Decodable>(url: URL, type: T.Type) -> Any?{
if let data = try? Data(contentsOf: url) {
let decoder = PropertyListDecoder()
do {
let result = try decoder.decode(type, from: data)
return result
}catch{
print("items decode failed ")
return nil
}
}
return nil
}
}
Use obj-getclass
:
CastDAO.invokeService("test", withParams: ["test" : "test"], returningClass: obj-getclass(self)) { cityInfo in /*...*/
}
Assuming self is a city info object.
참고URL : https://stackoverflow.com/questions/24308975/how-to-pass-a-class-type-as-a-function-parameter
'IT' 카테고리의 다른 글
본문 또는 HTML 헤드에 스크립트를 작성해야합니까? (0) | 2020.06.27 |
---|---|
Android 용 XML 속성의 물음표 (?) (0) | 2020.06.27 |
iOS5 SDK의 자동 참조 계산에 대한 몇 가지 질문 (0) | 2020.06.27 |
다이나믹하고 개인화 된 웹 애플리케이션에 적합한 응답 시간은 무엇입니까? (0) | 2020.06.27 |
SQL WHERE 절이 단락 되었습니까? (0) | 2020.06.27 |