2014-12-11 14 views
7

Desidero distribuire Elenco sorgenti utilizzando NSOutlineView in un progetto Swift.NSOutlineView arresti anomali quando viene utilizzato il metodo delegato isGroupItem con Swift

Il controller di visualizzazione di seguito funziona correttamente quando non viene richiamato il metodo delegato isGroupItem. Tuttavia, molti oggetti __NSMallocBlock__ verranno restituiti quando viene utilizzato il metodo isGroupItem. Quale non ho idea da dove vengono questi elementi. Gli articoli che ho fornito sono solo stringhe.

class ViewController: NSViewController, NSOutlineViewDataSource, NSOutlineViewDelegate { 

let topLevel = ["1", "2"] 
let secLevel = ["1": ["1.1", "1.2"], "2": ["2.1", "2.2"]] 

func outlineView(outlineView: NSOutlineView, numberOfChildrenOfItem item: AnyObject?) -> Int { 
    if let str = item as? String { 
     let arr = secLevel[str]! as [String] 
     return arr.count 
    } else { 
     return topLevel.count 
    } 
} 

func outlineView(outlineView: NSOutlineView, isItemExpandable item: AnyObject) -> Bool { 
    return outlineView.parentForItem(item) == nil 
} 

func outlineView(outlineView: NSOutlineView, child index: Int, ofItem item: AnyObject?) -> AnyObject { 
    var output: String! 
    if let str = item as? String { 
     output = secLevel[str]![index] 
    } else { 
     output = topLevel[index] 
    } 
    return NSString(string: output) 
} 

func outlineView(outlineView: NSOutlineView, objectValueForTableColumn tableColumn: NSTableColumn?, byItem item: AnyObject?) -> AnyObject? { 
    return item 
} 

func outlineView(outlineView: NSOutlineView, isGroupItem item: AnyObject) -> Bool { 
    return (outlineView.parentForItem(item) == nil) 
} 

func outlineView(outlineView: NSOutlineView, viewForTableColumn tableColumn: NSTableColumn?, item: AnyObject) -> NSView? { 
    return outlineView.makeViewWithIdentifier("HeaderCell", owner: self) as NSTextField 
} 
} 

Il progetto di esempio può essere scaricato here

+0

Odora di insetto. Se si restituisce 'true', si blocca. Se si restituisce 'false' mostra la riga genitore come' malloc ... ' –

+0

Questo è probabilmente un bug; dovrebbe "funzionare", ma non lo fa. Per favore vedi la mia risposta (presto disponibile). –

risposta

5

Questa domanda ha ricevuto risposta da Ken Tommaso forum degli sviluppatori di Apple. Qui è stato estratto quello che ha detto:

Gli elementi forniti nella vista struttura devono essere persistenti. Inoltre, devi restituire lo stesso oggetto ogni volta per un dato genitore e indice. Non è possibile restituire oggetti creati ad hoc, come si fa in -outlineView: child: ofItem: dove si chiama il costruttore di convenienza NSString.

Funziona bene dopo persistente gli oggetti origine dati come segue:

let topLevel = [NSString(string: "1"), NSString(string: "2")] 
let secLevel = ["1": [NSString(string: "1.1"), NSString(string: "1.2")], "2": [NSString(string: "2.1"), NSString(string: "2.2")]] 

poi tornare la stored NSString nella outlineView: Metodo di origine dati: bambino: ofItem.

+0

Grazie. Questo ha aiutato. Non avrei mai indovinato. – nspire

+0

Mi sono divertito un po 'di più con questo. Vedi qui: http://stackoverflow.com/questions/24828553/swift-code-to-use-nsoutlineview-as-file-system-directory-browser/27626466#27626466 –

+0

Penso che sia importante capire * perché * questo lavori. Si prega di vedere la mia risposta. –

8

Se si controlla la documentazione di NSOutlineView si vedrà che memorizza solo i puntatori; non conserva gli oggetti restituiti dal figlio: ofItem: metodo delegato. Così, quando si esegue questa linea:

return NSString(string: output) 

si restituisce un nuova istanza NSString che viene rapidamente rilasciato (in quanto la vista struttura non conserva di esso). Dopo quel punto, ogni volta che si fanno domande sugli oggetti si verificherà un arresto anomalo, poiché la NSString è stata liberata.

La soluzione è semplice: archiviare NSStrings in un array e restituire ogni volta le stesse istanze.

Corbin

0

È perché NSOutlineView opere con oggetti ereditati da NSObject, e la stringa Swift è di tipo compatibile.