2014-12-11 5 views
7

Swift 프로젝트에서 NSOutlineView를 사용하여 소스 목록을 배포하려고합니다.Swift에서 isGroupItem 대리자 메서드를 사용할 때의 NSOutlineView 크래시

아래보기 컨트롤러는 isGroupItem 대리자 메서드가 호출되지 않으면 잘 작동합니다. 그러나 isGroupItem 메서드를 사용하면 많은 __NSMallocBlock__ 항목이 반환됩니다. 나는이 품목들이 어디에서 왔는지 전혀 모른다. 내가 제공 한 항목은 문자열입니다.

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 
} 
} 

이 샘플 프로젝트는이 질문은 애플 개발자 포럼에서 켄 Thomases 응답 된 here

+0

냄새는 버그를 좋아합니다. 'true'를 반환하면 충돌이 발생합니다. 'false'를 반환하면 부모 행이'malloc ... '으로 표시됩니다. –

+0

이것은 틀림없이 버그입니다. 그것은 단지 "일해야"하지만하지 않습니다. 내 답변을 참조하십시오 (곧 제공 될 예정). –

답변

5

을 다운로드 할 수 있습니다. 여기에 그가 말한 내용이 추출되었습니다.

개요보기에 제공하는 항목은 영구적이어야합니다. 또한 주어진 부모 및 색인에 대해 매번 동일한 항목을 반환해야합니다. -outlineView : child : ofItem : NSString 편의 생성자를 호출 할 때처럼 임시로 생성 된 객체를 반환 할 수 없습니다. 그것은 다음과 같이 데이터 소스 오브젝트를 지속 한 후 잘 작동

:

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")]] 

는 다음 outlineView에 저장되어있는 NSString을 반환 : 아이 : ofItem : 데이터 소스 방법.

+0

감사합니다. 이것은 도움이되었습니다. 나는 결코 짐작하지 않았을 것이다. – nspire

+0

나는 이걸 좀 더 들여다 보았다. 여기를 참조하십시오 : http://stackoverflow.com/questions/24828553/swift-code-to-use-nsoutlineview-as-file-system-directory-browser/27626466#27626466 –

+0

나는 이것을 이해하는 것이 중요하다고 생각합니다. 공장. 제 응답을 참조하십시오. –

8

NSOutlineView 문서를 살펴보면 포인터 만 저장된다는 것을 알 수 있습니다. child : ofItem : delegate 메서드에서 반환 된 객체는 유지되지 않습니다. 그래서, 당신은이 선 수행 할 때 당신은 신속하게 출시되는 새로운있는 NSString 인스턴스 (개요보기가 유지되지 않기 때문에) 반환하는

return NSString(string: output) 

합니다. 그 시점 이후에 언제든지 NSString이 해제 되었기 때문에 아이템에 대한 질문을하면 크래시가 발생합니다.

솔루션은 간단합니다. NSString을 배열에 저장하고 매번 동일한 인스턴스를 반환합니다.

코빈

0

개체 NSOutlineView 작품 NSObject로부터 상속 때문입니다, 그리고 스위프트 문자열이 호환되지 않는 유형입니다.