A sample of the view I wanted to achieve:
This is the base type that I wanted to display in the outline view:
// The Domains Tab
class Domain {
var name: String = "domain-name.extension"
var wwwIncluded: Bool = true
var root: String = "root-folder"
var forewardUrl: String = ""
}
Which I had to replace with:
// The Domains Tab
class Domain {
var name: NSString = "domain-name.extension"
var wwwIncluded: NSNumber = NSNumber(bool: true)
var root: NSString = "root-folder"
var forewardUrl: NSString = ""
}
It was not the Bool that caused the problems, but the String. But before I talk about that, let me first show the implementation of the NSOutlineViewDataSource delegate:
var domains = Array<Domain>(arrayLiteral: Domain(), Domain())
@IBOutlet weak var domainNameColumn: NSTableColumn!
@IBOutlet weak var domainValueColumn: NSTableColumn!
extension ConsoleWindowViewController: NSOutlineViewDataSource {
func outlineView(outlineView: NSOutlineView, numberOfChildrenOfItem item: AnyObject?) -> Int {
if item == nil { return domains.count }
return 3
}
func outlineView(outlineView: NSOutlineView, isItemExpandable item: AnyObject) -> Bool {
return (domains as NSArray).containsObject(item)
}
func outlineView(outlineView: NSOutlineView, child index: Int, ofItem item: AnyObject?) -> AnyObject {
if item == nil { return domains[index] }
for d in domains {
if item === d {
switch index {
case 0: return d.wwwIncluded
case 1: return d.root
case 2: return d.forewardUrl
default:
log.atLevelError(id: 0, source: "ConsoleWindowViewController.outlineView-child-ofItem", message: "Index out of range: \(index)")
}
}
}
return "Error"
}
// Using "Cell Based" content mode
func outlineView(outlineView: NSOutlineView, objectValueForTableColumn tableColumn: NSTableColumn?, byItem item: AnyObject?) -> AnyObject? {
if tableColumn === domainNameColumn {
for d in domains {
if item === d { return d.name }
else if item === d.wwwIncluded { return "Include 'www' prefix" }
else if item === d.root { return "Root directory" }
else if item === d.forewardUrl { return "Foreward to URL" }
}
} else if tableColumn === domainValueColumn {
for d in domains {
if item === d { return nil }
else if item === d.wwwIncluded { return (d.wwwIncluded.boolValue ? "yes" : "no") }
else if item === d.root { return d.root }
else if item === d.forewardUrl { return (d.forewardUrl.length > 0 ? d.forewardUrl : "-") }
}
}
return nil
}
}
item === (d.root as AnyObject)
would crash the App at runtime. Strangely enough defining the wwwIncluded as Bool and comparing it as
item === (d.wwwIncluded as AnyObject)
would work fine.
Only by converting the String to a NSString would the App run correctly.
While I do not know what the cause is for this, I don't mind defining the Domain class with Foundation class types as it makes the code a lot more readable. The number of casts is reduced considerably.
Oh, and one more thing: The NSOutlineView in InterfaceBuilder is preset to be "View Based" instead of "Cell Based". If at runtime the view shows you the annoying "Table View Cell" content, you have probably forgotten to change the Table View - Content Mode from "View Based" to "Cell based":
If you want to use the "View Based" table then do not use
func outlineView(outlineView: NSOutlineView, objectValueForTableColumn tableColumn: NSTableColumn?, byItem item: AnyObject?) -> AnyObject? {
but use the NSOutlineViewDelegate operation:
func outlineView(outlineView: NSOutlineView, viewForTableColumn tableColumn: NSTableColumn?, item: AnyObject) -> NSView? {
instead.
Note: While it does work, it turned out that the above code has some not-so-nice properties. I posted an improved example here: Using NSOutlineView in Swift, an example.
Happy coding...
Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH
We don't get the world we wish for... we get the world we pay for.
No comments:
Post a Comment