swift - How to program a NSOutlineView? -
i having trouble creating nsoutlineview in xcode 8 (swift 3). have plist file information present in outlineview. plist file looks following (example):
root dictionary *(1 item) harry watson dictionary *(5 items)* name string harry watson age int 99 birthplace string westminster birthdate date 01/01/1000 hobbies array *(2 items)* item 0 string tennis item 1 string piano
the outlineview should pretty similar, follow:
name harry watson age 99 birthplace westminster birthdate 01/01/1000 > hobbies ... (<- should expandable)
i searched nsoutlineview tutorials on google, found raywenderlich.com, read bit in opinion isn't easy. wondering whether me exact example above , give me code examples, regarding function:
func outlineview(_ outlineview: nsoutlineview, viewfor tablecolumn: nstablecolumn?, item: any) -> nsview? {}
. not sure write in there.
if have questions, let me know.
thanks in advance , kind regards
i find ray wenderlitch's tutorials vary wildly in quality. in-jokes, verbosity, step-by-step handholding assumes know nothing swift nauseating me. here's skinny tutorial cover basics of outline view.
the key understand nsoutlineview
must give each row unique identifier, string or object represent row. nsoutlineview
calls item
. based on item
, query data model fill outline view data.
interface builder setup
we use simple nsoutlineview
2 columns: key , value.
select first column , change identifier keycolumn
. select second column , change identifier valuecolumn
:
set identifier cell outlineviewcell
. need once.
code
copy , paste following 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! // assume know how load plist skip // code , use constant 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 { // must give each row unique identifier, referred `item` outline view // * top-level rows, use values in `keys` array // * hobbies sub-rows, label them ("hobbies", 0), ("hobbies", 1), ... // integer index in hobbies array // // item == nil means it's "root" row of outline view, not visible func outlineview(_ outlineview: nsoutlineview, child index: int, ofitem item: 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: // * root row has 5 children: name, age, birthplace, birthdate, hobbies // * hobbies row has how ever many hobbies there // * 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 row expandable. expandable row hobbies row func outlineview(_ outlineview: nsoutlineview, isitemexpandable item: any) -> bool { if let item = item as? string, item == "hobbies" { return true } else { return false } } // set text each row func outlineview(_ outlineview: nsoutlineview, viewfor tablecolumn: nstablecolumn?, item: any) -> nsview? { guard let columnidentifier = tablecolumn?.identifier else { return nil } var text = "" // recall `item` row identiffier switch (columnidentifier, item) { case ("keycolumn", let item 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 identified hobby sub-rows differently if let (key, index) = item as? (string, int), key == "hobbies" { text = person.hobbies[index] } case ("valuecolumn", let item 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 } }
result
you can use dateformatter
nicer date output that's not essential question.
Comments
Post a Comment