2017-08-25 72 views
1

我與SWIFT 4 MacOS的工作,我有一個NSOutlineView:迅速大綱視圖

enter image description here

我從核心數據的數據。

結構:

  • 實體人(關係到實體書)
  • 實體書

我對這個結果代碼:

@IBOutlet weak var myOutlineView: NSOutlineView! 

    let context = (NSApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext 
    var people = [Person]() 

    override func viewWillAppear() { 
     requestPeople() 
    } 

    func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? { 
     let view = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "Cell"), owner: self) as? CustomCell 
     if let person = item as? Person { 
      // Show Person 
     } else if let book = item as? Book { 
      // Show Books 
     } 
     return view 
    } 


    func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int { 
     if let person = item as? Person { 
      return person.books.count 
     } 
     return people.count 
    } 


    func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any { 
     if let person = item as? Person { 
      return person.books[index] 
     } 
     return people[index] 
    } 


    func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool { 
     if let person = item as? Person { 
      return person.books.count > 0 
     } 
     return false 
    } 



    func requestPeople() { 
     let request = NSFetchRequest<Person>(entityName: "Person") 
     do { 
      people = try context.fetch(request) 
      myOutlineView.reloadData() 
     } catch { print(error) } 
    } 

現在我的問題: 我想創建另一個大綱視圖。

的My Book實體看起來像這樣(屬性):

  • creationDate

我的新outlineview應該得到這樣的結構:

+ Year 
++ Month 
+++ Bookname 

但我不知道我怎麼能實現這個結構。 它與我的第一個大綱視圖不同。

有人可以幫我嗎?

=======

我想我有沒有重複創建年份和月份陣列。 爲了這個,我嘗試了這個函數來獲取數據:

var year = [String]() 
var month = [String]() 
var books = [Book]() 

    func requestBooks() { 
     let request = NSFetchRequest<Book>(entityName: "Book") 
     do { 
      books = try context.fetch(request) 

      for x in 0 ...< books.count { 

       if !year.contains("\(Calendar.current.component(.year, from: books[x].creationDate))") { 
        year.append("\(Calendar.current.component(.year, from: books[x].creationDate))") 
       } 

       if !month.contains("\(Calendar.current.component(.month, from: books[x].creationDate))") { 
        month.append("\(Calendar.current.component(.month, from: books[x].creationDate))") 
       } 

      } 

      myOutlineView.reloadData() 
     } catch { print(error) } 
    } 

回答

0

一個多層次的大綱更容易管理當你的基礎數據結構是分層(即樹形結構)。

這裏是你如何創造你的書是「樹」節點類的一個示例:

class BookNode 
{ 
    // levels and relationships, from parent to children 
    enum Level { case Top, Year, Month, Book }  
    let subLevels:[Level:Level] = [ .Top:.Year, .Year:.Month, .Month:.Book ]  

    var label = ""    // description and unique "key" 
    var level = Level.Top   
    var children : [BookNode] = []  
    var book  : Book! = nil  // .Book level will store the actual Book 

    // add book to hierarchy, auto-create intermediate levels   
    func add(_ book:Book) 
    { 
     var subLabel = "" 
     switch level 
     { 
     case .Top : subLabel = String(Calendar.current.component(.year, from:book.creationDate)) 
     case .Year : subLabel = String(Calendar.current.component(.month, from:book.creationDate)) 
     case .Month : subLabel = book.name 
     case .Book : self.book = book // last level stores the book 
         return    // and has no children 
     }      
     // Add branch (.Year, .Month) or leaf (.Book) node as needed 
     var subNode:BookNode! = children.first{$0.label == subLabel} 
     if subNode == nil 
     { 
     subNode  = BookNode() 
     subNode.level = subLevels[level]! 
     subNode.label = subLabel 
     children.append(subNode) 
     } 
     // keep adding recursively down to .Book level   
     subNode.add(book) 
    } 
} 

您的數據將存儲在BookNodes的層次,你可以從加載讀取請求 (你可以預先排序,像我一樣,或者留給達BookNode類)

var topNode = BookNode() 

func requestBooks() 
{ 
    let request = NSFetchRequest<Book>(entityName: "Book") 
    do { 
     let books = try context.fetch(request) 

     topNode = BookNode() 
     for book in books.sorted(by:{$0.creationDate < $1.creationDate}) 
     { 
      topNode.add(book) 
     } 
    } 
} 

據此,將很容易使用BookNodes爲綱項目大綱協議作出迴應:

func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? 
{ 
    let view = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "Cell"), owner: self) as? CustomCell 

    let node = (item as? BookNode) ?? topNode 
    switch node.level 
    { 
    case .Year : // show year  : node.label 
    case .Month : // show month  : node.label 
    case .Book : // show book name : node.label and/or node.book 
    default  : break 
    } 

    return view 
} 

func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int 
{   
    let node = (item as? BookNode) ?? topNode 
    return node.children.count   
} 


func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any 
{ 
    let node = (item as? BookNode) ?? topNode 
    return node.children[index]   
} 


func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool 
{ 
    let node = (item as? BookNode) ?? topNode 
    return node.children.count > 0   
} 

如果您的程序需要允許添加/更改/刪除個別書籍,則可以使用BookNode類來反映個別更改的內容(例如,刪除書籍孩子或添加一個新的)。那麼你只需要在大綱上調用reloadData(),而不必從數據庫中取回所有的東西。

+0

非常感謝你:) – Ghost108