2017-08-19 50 views
0

我正在從swift數據塊中讀取設置,並且希望將其填充到結構中以便於訪問和輸入正確性。有沒有一種簡潔的方式來分配值的結構成員?如使用下標來自我?Swift:從值數組批量分配struct成員

let settings : [UInt] = [5, 5, 121, 700, 108, 1452, 6655, 10] 

struct Header { 
    var version    : UInt8? 
    var options    : UInt8? 
    var records    : UInt16? 
    var timeout    : UInt16? 
    var left    : UInt16? 
    var right    : UInt16? 
    var middle    : UInt16? 
    var speed    : UInt8? 

    init(values: [UInt]) { 
     let m = Mirror(reflecting: self) 
     var labels : [String] = [] 
     for (n, _) in m.children { 
      labels.append(n!) 
     } 

     for (h, v) in zip(labels, values) { 
      print("\(h) -> \(v)") 
      self[h] = v  //error: type 'Header' has no subscript members 
     } 
    } 
} 

let h = Header(values: settings) 

跟進
感謝您的解決方案,ColGraff。

在我的情況數據來自於從多個地方,在值的陣列的形式。下面將幫助

let settings : [UInt] = [5, 5, 121] 
let labels : [Header.Keys] = [.version, .options, .records] 
var data : [Header.Keys : UInt] = [:] 
zip(labels, settings).forEach { data[$0] = $1 } 
+0

眼看自己不是字典或數組,下標不起作用。 – ryantxr

回答

3

一個被廣泛接受的做事的方式就像你說的是:

struct Header { 
    let version : UInt 
    let options : UInt 
    let records : UInt 
} 

// adds marshaling from a `Dictionary` 
extension Header { 
    enum Keys: String { case version, options, records} 

    init?(settings: [Keys:UInt]) { 
    guard let version = settings[.version] else { return nil } 
    guard let options = settings[.options] else { return nil } 
    guard let records = settings[.records] else { return nil } 
    self = Header(version: version, options: options, records: records) 
    } 
} 

let data: [Header.Keys: UInt] = [.version: 5, .options: 5, .records: 121] 

if let foo = Header(settings: data) { 
    print(foo) // Header(version: 5, options: 5, records: 121) 
} 

如果你喜歡,你可以用Array甚至String但代替像Dictionary結構一個Dictionary是你正在問的很自然的結構。有些人甚至用JSON這樣的字符串編碼DictionaryArray結構。

是的,您可以使用Mirror以更自動的方式執行此類操作,但這可能會非常棘手並導致問題。編寫一個更具體的編組數據的方式通常更安全。

更高級的用法和討論是this chat room

+0

這很好。你可以添加一個如何創建結構實例的例子嗎? – ryantxr

+0

是的,我已經加入並澄清了這個例子。 – ColGraff

+0

我正在抓住這個主意。這似乎是一個非常有用的模式。 – ryantxr

0

備用啓發解決方案:

let settings : [UInt] = [5, 5, 121, 700, 108, 1452, 6655, 10] 

enum Fields: String { 
    case version, options, records, timeout, left, right, middle, speed 
} 

struct Header { 
    var version    : UInt8? 
    var options    : UInt8? 
    var records    : UInt16? 
    var timeout    : UInt16? 
    var left    : UInt16? 
    var right    : UInt16? 
    var middle    : UInt16? 
    var speed    : UInt8? 

    init(values: [UInt]) { 
     let m = Mirror(reflecting: self) 
     var labels : [Fields] = [] 
     for (n, _) in m.children { 
      labels.append(Fields(rawValue: n!)!) 
     } 

     zip(labels, values).forEach { l, v in 
      switch l { 
      case .version: self.version = UInt8(v) 
      case .options: self.options = UInt8(v) 
      case .records: self.records = UInt16(v) 
      case .timeout: self.timeout = UInt16(v) 
      case .left : self.left = UInt16(v) 
      case .right : self.right = UInt16(v) 
      case .middle : self.middle = UInt16(v) 
      case .speed : self.speed = UInt8(v) 
      default:() 
      } 
     } 
    } 
} 

var h = Header(values: settings) 
print(h.version) 
h.version = 7 
print(h.version) 

現在,如果我只能找出如何產生從結構動態枚舉...