2017-08-25 78 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