2015-11-03 87 views
1

讓說我下面的代碼獲取數組類型元素的(通過反射)

class Foo { 
} 

var fooArray : Array<Foo> = Array<Foo>() 
// This is important because in my code I will get Any (vs Array<Foo) 
var fooArrayAny : Any = foo 

我希望能夠得到一個類型出可變fooArrayAny的。

如果我有fooArray,我會做這樣的事情:

let type = fooArray.dynamicType.Element().dynamicType 

然而,這並不fooArrayAny工作。它說,它沒有成員元素()

+0

fooArray.dynamicType.Element()被實例化的Foo,而不會返回一個類型。什麼類型的對象是在foo中,你期望從中得到什麼? –

+0

@ChrisGulley:我忘了在最後添加dynamicType以獲得它的類型 –

回答

2

如果設置NSObject的基類美孚的,那麼你可以使用下面的代碼:

class EVReflectionTests: XCTestCase {  
    func testArrayInstance() { 
     let fooArray : Array<Foo> = Array<Foo>() 
     let fooArrayAny : Any = fooArray 
     if let arr = fooArray as? Array { 
      let i = arr.getArrayTypeInstance(arr) 
      print("i = \(i)") 
     } 
    } 
} 

class Foo: NSObject { 
} 



extension Array { 
    public func getArrayTypeInstance<T>(arr:Array<T>) -> T { 
     return arr.getTypeInstance() 
    } 

    public func getTypeInstance<T>() -> T { 
     let nsobjectype : NSObject.Type = T.self as! NSObject.Type 
     let nsobject: NSObject = nsobjectype.init() 
     return nsobject as! T 
    } 
} 

該代碼的一個片段我庫EVReflection

更新:

我注意到,在上面的代碼錯誤。我用fooArray而不是fooArrayAny。當將其更改爲fooArrayAny時,我得到與編譯器沒有該元素相同的錯誤。玩過這個之後,我發現了一個可行的解決方案。它再次具有我的EVReflection庫的部分代碼。

class EVReflectionTests: XCTestCase {  
    func testArrayInstance() { 
     let fooArray : Array<Foo> = Array<Foo>() 
     let fooArrayAny : Any = fooArray 

     if let _ = fooArrayAny as? NSArray { 
      var subtype: String = "\(Mirror(reflecting: fooArrayAny))" 
      subtype = subtype.substringFromIndex((subtype.componentsSeparatedByString("<") [0] + "<").endIndex) 
      subtype = subtype.substringToIndex(subtype.endIndex.predecessor()) 
      print("The type of the array elements = \(subtype)") 
      if let instance = swiftClassFromString(subtype) { 
       print("An instance of the array element = \(instance)") 
       let type = instance.dynamicType 
       print("An instance of the array element = \(type)") 
      } 
     } 
    } 

    // All code below is a copy from the EVReflection library. 

    func swiftClassFromString(className: String) -> NSObject? { 
     var result: NSObject? = nil 
     if className == "NSObject" { 
      return NSObject() 
     } 
     if let anyobjectype : AnyObject.Type = swiftClassTypeFromString(className) { 
      if let nsobjectype : NSObject.Type = anyobjectype as? NSObject.Type { 
       let nsobject: NSObject = nsobjectype.init() 
       result = nsobject 
      } 
     } 
     return result 
    } 

    func swiftClassTypeFromString(className: String) -> AnyClass! { 
     if className.hasPrefix("_Tt") { 
      return NSClassFromString(className) 
     } 
     var classStringName = className 
     if className.rangeOfString(".", options: NSStringCompareOptions.CaseInsensitiveSearch) == nil { 
      let appName = getCleanAppName() 
      classStringName = "\(appName).\(className)" 
     } 
     return NSClassFromString(classStringName) 
    } 

    func getCleanAppName(forObject: NSObject? = nil)-> String { 
     var bundle = NSBundle.mainBundle() 
     if forObject != nil { 
      bundle = NSBundle(forClass: forObject!.dynamicType) 
     } 

     var appName = bundle.infoDictionary?["CFBundleName"] as? String ?? "" 
     if appName == "" { 
      if bundle.bundleIdentifier == nil { 
       bundle = NSBundle(forClass: EVReflection().dynamicType) 
      } 
     appName = (bundle.bundleIdentifier!).characters.split(isSeparator: {$0 == "."}).map({ String($0) }).last ?? "" 
     } 
     let cleanAppName = appName 
      .stringByReplacingOccurrencesOfString(" ", withString: "_", options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil) 
      .stringByReplacingOccurrencesOfString("-", withString: "_", options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil) 
     return cleanAppName 
    } 
} 

class Foo: NSObject { 
} 

此代碼的輸出將是:

The type of the array elements = Foo 
An instance of the array element = <EVReflection_iOS_Tests.Foo: 0x7fd6c20173d0> 
An instance of the array element = Foo 
+0

我注意到代碼中有錯誤。我向awnser添加了新的代碼。 –

+1

我試圖解決完全相同的問題JSON序列化/反序列化(因爲我對我看到的幾個庫不滿意)。我發佈了這個問題,並在一個小時內發現了你的庫,並愉快地扔掉了我寫的所有代碼 –

0
class Foo { 
    var foo: Int = 1 
} 
struct Boo { 
    var boo: String = "alfa" 
} 

func f(array: Any) { 
    let mirror = Mirror(reflecting: array) 
    let arraytype = mirror.subjectType 
    switch arraytype { 
    case is Array<Foo>.Type: 
     let fooArray = array as! Array<Foo> 
     print(fooArray) 
    case is Array<Boo>.Type: 
     let booArray = array as! Array<Boo> 
     print(booArray) 
    default: 
     print("array is not Array<Foo> nor Array<Boo>") 
     break 
    } 
} 
var fooArray : Array<Foo> = [] 
fooArray.append(Foo()) 
var anyArray : Any = fooArray // cast as Any 
f(anyArray)      // [Foo] 
var booArray : Array<Boo> = [] 
booArray.append(Boo()) 
anyArray = booArray    // cast as Any 
f(anyArray)      // [Boo(boo: "alfa")] 
var intArray : Array<Int> = [] 
anyArray = intArray    // cast as Any 
f(anyArray)      // array is not Array<Foo> nor Array<Boo> 
+0

這將是一種工作。但是,每次需要支持新類型時,我都必須擴展開關盒。我正在尋找一些更通用的方法 –

+0

通用的方法?同比仍然需要知道如何使用不同類型的表演。 – user3441734

相關問題