2017-05-07 16 views
1

문자열 값을 루트 값으로 표시하는 outlineView를 구현하고 싶습니다.Swift 3 - 확장 가능한 항목이있는 NSOutlineView

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라는 당신에 속성을 선언하고 일부 Item의 사용 itemsForNumberOf 도우미 함수를 반환합니다.

class TestController: NSViewController, NSOutlineViewDataSource, NSOutlineViewDelegate { 

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

    @IBOutlet weak var outlineView: NSOutlineView! 
} 
TestController 오버라이드 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?) -> Anyitem의 하위 항목을 반환합니다. item이 "항목 1"이고 index이 1이면 반환 값은 "하위 항목 1.2"입니다.

func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int는``의 자식 수를 반환합니다. item이 "항목 1"이면 반환 값은 2입니다.