2017-05-07 16 views
1

文字列値をルート値として表示するoutlineViewを実現したいと思います。Swift 3 - NSOutlineView with expandable items

import Cocoa 


class TestController: NSViewController, NSOutlineViewDataSource, NSOutlineViewDelegate { 


    @IBOutlet weak var outlineView: NSOutlineView! 

var items: [String] = ["Item 1", "Item 2", "Item 3", "Item 4","Item 5"] 

func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any { 
     return items[index] 
    } 


    func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool { 
     return true 
    } 


    func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int { 
     if item == nil { 
     return items.count 
     } 
     return 0 
    } 


    func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? { 

     let v = outlineView.make(withIdentifier: "HeaderCell", owner: self) as! NSTableCellView 
     if let tf = v.textField { 
      tf.stringValue = item as! String 
     } 
     return v 
    } 

} 

これが結果です::次のコードは、私の作品

enter image description here

しかし、私は(例えば)項目1に別の文字列値を割り当てることができるか、わかりません。私はそのようなものを実現したい:

+Item 1 
++Sub Item 1.1 
++Sub Item 1.2 

+Item 2 
++Sub Item 2.1 

+Item 3 
++Sub Item 3.1 
++Sub Item 3.2 
++Sub Item 3.3 

... 

誰か私を助けることができますか?

答えて

0

単純なString配列はあまり使用されません。少なくともサブ項目を表示するには辞書が必要です。私は小さなヘルパーモデルを紹介することをお勧めします、Itemと呼ぶことができます。それは名前を保持し、いくつかの子供たちのアイテム、それらはサブアイテムになります。

struct Item { 
    let name: String 
    var childrens: [Item] = [] 

/// Create a helper function to recursivly create items 
/// 
/// - Parameters: 
/// - parents: number of parent items 
/// - childrens: number of children for each parent item 
/// - Returns: array of Item 
static func itemsForNumberOf(parents: Int, childrens: Int) -> [Item] { 
    var items: [Item] = [] 
    for parentID in 1...parents { 
     var parent = Item(name: "Index \(parentID)",childrens: []) 
     for childrenID in 1...childrens { 
      let children = Item(name: "Index \(parentID).\(childrenID)",childrens: []) 
      parent.childrens.append(children) 
     } 
     items.append(parent) 
    } 
    return items 
} 

}

あなたのViewControllerのプロパティを宣言しitemsと呼ばれ、itemsForNumberOfヘルパー関数を使用して、いくつかのItem年代を返します。 TestController

class TestController: NSViewController, NSOutlineViewDataSource, NSOutlineViewDelegate { 

    let items: [Item] = { 
     return Item.itemsForNumberOf(parents: 5, childrens: 3) 
    }() 

    @IBOutlet weak var outlineView: NSOutlineView! 
} 

viewDidLoad()関数をオーバーライドし、あなたのViewControllerにデリゲートやデータソースを割り当てます。

override func viewDidLoad() { 
    super.viewDidLoad() 
    self.outlineView.delegate = self 
    self.outlineView.dataSource = self 
} 

NSOutlineViewDataSourceのマニュアルをチェックし、特定のこのAPI

func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any { 
    if item == nil { 
     return items[index] 
    } 

    if let item = item as? Item, item.childrens.count > index { 
      return item.childrens[index] 
    } 

    return "" 
} 

戻り、受信した項目の子に基づいてプロパティをexpandalbe。再び

func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int { 
    if item == nil { 
     return items.count 
    } 

    if let item = item as? Item { 
     return item.childrens.count 
    } 

    return 0 
} 
を子供のプロパティを使用してカウントしたサブ項目を返すための>拡張

func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool { 
    guard let item = item as? Item else { 
     return false 
    } 

    return !item.childrens.isEmpty 
} 

同じ -
それが空の場合、子供たち - それが空でない場合
>拡張可能ではないが、子供を持っていませんが

viewFor機能では、nilをすべて返すことを確認する必要があります。Itemタイプでは表示されません。

func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? { 

     guard let item = item as? Item else { 
      return nil 
     } 

     let v = outlineView.make(withIdentifier: "HeaderCell", owner: self) as! NSTableCellView 
     if let tf = v.textField { 
      tf.stringValue = item.name 
     } 
     return v 
    } 
} 

そして、あなたはこのようなもので終わる必要があります。
enter image description here

0

階層データを表示する場合は、データを単純な文字列の配列にすることはできません。アイテム文字列の代わりに、title/nameおよびchildrenプロパティを持つ辞書またはカスタムオブジェクトを使用します。 childrenプロパティは、子アイテムの配列です。

func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Anyは、の子を返します。 itemが "Item 1"で、indexが1の場合、戻り値は "Sub Item 1.2"です。

func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Intは ``の子の数を返します。 itemが "Item 1"の場合、戻り値は2です。