我找到雷Wenderlitch的教程質量差異很大。這些笑話,冗長的句子,假設你對Swift一無所知的一步一步的手持操作對我來說太過噁心。這是一個簡潔的教程,涵蓋了大綱視圖的基礎知識。
瞭解NSOutlineView
的關鍵是,你必須給每個行的唯一標識符,是一個字符串或代表該行的對象。 NSOutlineView
稱之爲item
。基於此item
,您將查詢您的數據模型以用數據填充大綱視圖。
Interface Builder中設置
我們將使用一個只有兩列很簡單NSOutlineView
:關鍵和價值。
選擇第一列並將其標識符更改爲keyColumn
。然後選擇第二柱,並改變其標識符以valueColumn
:
設置該小區的標識符outlineViewCell
。你只需要做一次。
代碼
複製並粘貼以下到您的ViewController.swift
:
// Data model
struct Person {
var name: String
var age: Int
var birthPlace: String
var birthDate: Date
var hobbies: [String]
}
class ViewController: NSViewController {
@IBOutlet weak var outlineView: NSOutlineView!
// I assume you know how load it from a plist so I will skip
// that code and use a constant for simplicity
let person = Person(name: "Harry Watson", age: 99, birthPlace: "Westminster",
birthDate: DateComponents(calendar: .current, year: 1985, month: 1, day: 1).date!,
hobbies: ["Tennis", "Piano"])
let keys = ["name", "age", "birthPlace", "birthDate", "hobbies"]
override func viewDidLoad() {
super.viewDidLoad()
outlineView.dataSource = self
outlineView.delegate = self
}
}
extension ViewController: NSOutlineViewDataSource, NSOutlineViewDelegate {
// You must give each row a unique identifier, referred to as `item` by the outline view
// * For top-level rows, we use the values in the `keys` array
// * For the hobbies sub-rows, we label them as ("hobbies", 0), ("hobbies", 1), ...
// The integer is the index in the hobbies array
//
// item == nil means it's the "root" row of the outline view, which is not visible
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
if item == nil {
return keys[index]
} else if let item = item as? String, item == "hobbies" {
return ("hobbies", index)
} else {
return 0
}
}
// Tell how many children each row has:
// * The root row has 5 children: name, age, birthPlace, birthDate, hobbies
// * The hobbies row has how ever many hobbies there are
// * The other rows have no children
func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
if item == nil {
return keys.count
} else if let item = item as? String, item == "hobbies" {
return person.hobbies.count
} else {
return 0
}
}
// Tell whether the row is expandable. The only expandable row is the Hobbies row
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
if let item = item as? String, item == "hobbies" {
return true
} else {
return false
}
}
// Set the text for each row
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
guard let columnIdentifier = tableColumn?.identifier else {
return nil
}
var text = ""
// Recall that `item` is the row identiffier
switch (columnIdentifier, item) {
case ("keyColumn", let item as String):
switch item {
case "name":
text = "Name"
case "age":
text = "Age"
case "birthPlace":
text = "Birth Place"
case "birthDate":
text = "Birth Date"
case "hobbies":
text = "Hobbies"
default:
break
}
case ("keyColumn", _):
// Remember that we identified the hobby sub-rows differently
if let (key, index) = item as? (String, Int), key == "hobbies" {
text = person.hobbies[index]
}
case ("valueColumn", let item as String):
switch item {
case "name":
text = person.name
case "age":
text = "\(person.age)"
case "birthPlace":
text = person.birthPlace
case "birthDate":
text = "\(person.birthDate)"
default:
break
}
default:
text = ""
}
let cell = outlineView.make(withIdentifier: "outlineViewCell", owner: self) as! NSTableCellView
cell.textField!.stringValue = text
return cell
}
}
結果
可以使用DateFormatter
爲更好的日期輸出,但是這不是必需的對於這個問題。
在我看來,他們的例子很簡單。 –
@ElTomato嘿,謝謝你的評論 - 你是什麼意思?這是我自己的榜樣!?!如果你認爲這很容易,你能幫助我嗎?我很感謝你的幫助。 –
你嘗試了什麼? – Willeke