2015-02-07 90 views
1

所有這些都是關於包裝任何對象或類型(= Any)並且能夠檢查類型是否相等。作爲類型和值的包裝器,可以很好地工作。我的問題是,我想拋出一個對象,通過反射找到它的屬性,併爲每個屬性創建一個封裝(包裝)類型的屬性。問題是反射的屬性總是Type Any - 我需要轉換爲它們的真實類型(例如String)。將反射物體的屬性恢復爲其原始類型

例情況搞清楚:

// Functions to check equality of Types 
func unsafeGetTypeId(type: Any.Type) -> uintptr_t { 
    return unsafeBitCast(type, uintptr_t.self) 
} 
func areOfSameType(v1: Any, v2: Any) -> Bool { 
    return unsafeGetTypeId(reflect(v1).valueType) == unsafeGetTypeId(reflect(v2).valueType) 
} 

class ZType { 

} 

class ZTypeT<T> { 
    var value: Any? 
    init() { 

    } 
    init(value: T) { 
     self.value = value 
    } 
} 

class SampleClass { 
    var sampleProperty : String 
    init(aString: String) { 
     self.sampleProperty = aString 
    } 
} 

var sample = SampleClass(aString: "Hans") 

var t1 = ZTypeT<String>() 
var t2 = ZTypeT(value: sample.sampleProperty) 
areOfSameType(t1, t2) // true 

var mirror = reflect(sample) 
for var index=0; index<mirror.count; ++index { 
    let (propertyName, childMirror) = mirror[index] 

    var tTestAgainst = ZTypeT<String>() 

    // This is obviously of type Any so it won`t be ZTypeT<String>() but ZTypeT<Any>() 
    var tMirrorProp = ZTypeT(value: childMirror.value) 
    areOfSameType(tMirrorProp, tTestAgainst) // false 

    // So how could i cast the value back to it`s type? This would work but it should be generic : i don`t know the type beforehand 
    var tMirrorPropCasted = ZTypeT(value: childMirror.value as String) 
    areOfSameType(tMirrorPropCasted, tTestAgainst) // false 
} 

正如你可以看到所有的作品如預期,直到tMirrorProp,因爲這會不會是String類型。如果我投了它,我的支票將再次成爲真實 - 但我不知道這種類型是無法投射的。有沒有人知道解決方案來解決這個問題。使用Swift-Classes的解決方案是首選,但與NSObject(s)協同工作的解決方案仍然存在問題。

+0

也許這個代碼可以幫助。它能夠將對象解析爲字典。 https://github.com/evermeer/EVCloudKitDao/blob/master/AppMessage/AppMessage/CloudKit/EVReflection.swift – 2015-02-17 22:05:29

回答

0

正如您已經說過的,實例化正確類型的唯一方法是將childMirror.value轉換爲正確的類型。你可以通過爲每種類型添加一個開關來實現。然後對比使用NSStringFromClass(tMirrorPropCasted.dynamicType)的對象你會得到這樣的:

var tMirrorPropCasted : ZTypeT<Any> 

var theValue = anyValue 
let mi:MirrorType = reflect(theValue) 
if mi.disposition == .Optional { 
    if mi.count == 0 { // Optional.None 
     theValue = NSNull() 
    } else { 
     let (name,some) = mi[0] 
     theValue = some.value 
    } 
} 

switch(theValue) { 
     case let intValue as Int: 
      tMirrorPropCasted = ZTypeT(value: childMirror.value as Int) 
     case let doubleValue as Double: 
      tMirrorPropCasted = ZTypeT(value: childMirror.value as Double) 
     case let stringValue as String: 
      tMirrorPropCasted = ZTypeT(value: childMirror.value as String) 
     case let boolValue as Bool: 
      tMirrorPropCasted = ZTypeT(value: childMirror.value as Bool) 
     case let anyvalue as NSObject: 
      tMirrorPropCasted = ZTypeT(value: childMirror.value as NSObject) 
     default: 
      tMirrorPropCasted = ZTypeT(value: childMirror.value) 
     } 

但不是檢查對象的類型,你也可以檢查值屬性的類型。該屬性仍將具有原始類型的信息。所以你可以做的是測試

if NSStringFromClass(tTestAgainst.value.dynamicType) == NSStringFromClass(tMirrorProp.value.dynamicType) { 
    NSLog("Same type") 
} 
+0

感謝您的回答。因爲我想使用反射測試agains類型不是一種選擇(這是一個「知道類型」的特殊情況IMO雖然它應該與我不知道的類一起工作:))你是對的檢查值而不是類型,實際上這是我目前的解決方法。但悲傷但卻是真實的 - 這將失敗與選擇權。我將不得不等待改進的重新驗證庫,我想。有一件事讓我覺得如此,蘋果開發者告訴我,他們只使用反射工具輸出。我必須檢查反射中的選項是否記錄爲可選字符串,例如.. – Alex 2015-02-18 09:57:24

+0

您可以測試可選項(各種)。你可以檢查反射(theValue).disposition == .Optional然後如果反射(theValue).count == 0,那麼值爲零,你不能得到類型,否則你可以得到反射(theValue)。[ 0] .1.value – 2015-02-18 10:44:11

+0

我用附加代碼更新了選項 – 2015-02-18 10:50:08