2016-06-28 13 views
0

2次元辞書の理解に少し問題があります。私の関数はセクションを持つUITableViewの辞書を返す必要があります。 1のテンプレートタイプは複数のテンプレート文字列を持つことができます。したがって、fetchedDataに類似の型を持つ2つ以上のテキストがある場合、それらは1つのキー文字列で配列[String]になければなりません。 以下のコードは、コンパイラの観点からは絶対に正しいです。私のことは間違っていますが、素晴らしい自動補完は私にすべてがOKだと思うようにします。 明らかにそれは空の辞書[:]Swift 1D 2D to Dictionary

func fetchTemplates() -> Dictionary<String, [String]> { 
    var templates: Dictionary<String, [String]> = [:] 
    let fetchRequest: NSFetchRequest<Template> = Template.fetchRequest() 
    fetchRequest.sortDescriptors = [SortDescriptor.init(key: "templateType", ascending: true)] 
    let fetchedData = try! context.fetch(fetchRequest) 
    if (!fetchedData.isEmpty) { 
     for templateItem in fetchedData { 
      templates[templateItem.templateType!]?.append(templateItem.templateText!) 
     } 
     return templates 
    } 
    else { 
     return templates 
    } 
} 

P.S.を返します。 fetchedDataリターン:

<Template: 0x003281h4> (entity: Template; id: 0x003281h4 <x-coredata:///Template/> ; data: { 
    templateText = "Example"; 
    templateType = "First"; 
}) 
+0

サイドノート: '!fetchedData.isEmpty'のチェックは不要です。空の場合、forループは0回繰り返され、スキップされます。 – Alexander

答えて

1

問題は、この行にある:var templates: Dictionary<String, [String]> = [:]

templates[templateItem.templateType!]?.append(templateItem.templateText!) 

templatesは、この行で初期化されました。この時点で、templatesは空の辞書です。

は年代順に、ダウンが起こるのステップにそのラインを破るのをしてみましょう:

  1. templateItem.templateTypeにアクセスして、開封さを強制されます。 nilの場合、クラッシュが発生します。
  2. templateItem.templateType!は、templates辞書のキーとして使用されます。これは常にnilを返します。ディクショナリは空であるため、これを含むキーの値はありません。
  3. ?.append()は、nilで呼び出されていないという条件で呼び出されます。 nilで呼び出された場合、何も起こりません。

3が原因です。あなたは1つが、まだキーのために存在していない場合は、新しい配列を初期化する必要があります。

func fetchTemplates() -> Dictionary<String, [String]> { 
    var templates: Dictionary<String, [String]> = [:] 
    let fetchRequest: NSFetchRequest<Template> = Template.fetchRequest() 
    fetchRequest.sortDescriptors = [SortDescriptor.init(key: "templateType", ascending: true)] 
    let fetchedData = try! context.fetch(fetchRequest) 
    if (!fetchedData.isEmpty) { //see note 2 
     for templateItem in fetchedData { 
      let type = templateItem.templateType! 
      var array = templates[type] ?? [] //see note 1 
      array!.append(templateItem.templateText!) 
      templates[type] = array 
     } 
     return templates 
    } 
    else { 
     return templates 
    } 
} 

この機能を簡素化することができる。

func fetchTemplates() -> [String : [String]] { 
    let fetchRequest = Template.fetchRequest() 
    fetchRequest.sortDescriptors = [SortDescriptor(key: "templateType", ascending: true)] 

    let fetchedData = try! context.fetch(fetchRequest) 

    var templates = [String, [String]]() 
    for templateItem in fetchedData { 
     let type = templateItem.templateType! 
     templates[type] = (templates[text] ?? []) + [templateItem.templateText!] 
    } 
    return templates 
} 

と削減を代わりに使用することができます。

func fetchTemplates() -> [String : [String]] { //see note 3 
    let fetchRequest = Template.fetchRequest() //see note 4 
    fetchRequest.sortDescriptors = [SortDescriptor(key: "templateType", ascending: true)] //see note 5 

    let fetchedData = try! context.fetch(fetchRequest) 

    return fetchedData.reduce([String, [String]]()){templates, templateItem in 
     (templates[templateItem.tempalteText!] ?? []) + [templateItem.templateText!] 
    } //see note 6 
} 

ノート

場合
  1. 0はnilではなく、arrayに割り当てられています。それ以外の場合は、新しい配列([])が `array 'に割り当てられます。
  2. このチェックは、明示的な型signiture
  3. X.init()のためだけ[String : [String]]
  4. 必要はちょうどX()
  5. 空虚チェックは不要であると書かれていない、と全体forことができるよう
  6. Dictionary<String, [String]>を書き込むことができ、不要ですループをreduceコールに変更することができます。
0

問題がある:辞書が空であるため

templates[templateItem.templateType!]は常にnilです。

したがって、何も追加することはできません。