diff --git a/Evergreen/AppNotifications.swift b/Evergreen/AppNotifications.swift index a7c17fff5..1274d235e 100644 --- a/Evergreen/AppNotifications.swift +++ b/Evergreen/AppNotifications.swift @@ -40,7 +40,7 @@ final class AppInfo { var article: Article? var articles: Set
? var navigationKey: Int? - var objects: [AnyObject]? + var objects: [AnyHashable]? var feed: Feed? static let appInfoKey = "appInfo" diff --git a/Evergreen/MainWindow/AddFeed/FolderTreeControllerDelegate.swift b/Evergreen/MainWindow/AddFeed/FolderTreeControllerDelegate.swift index e5950ed95..b6a3f6604 100644 --- a/Evergreen/MainWindow/AddFeed/FolderTreeControllerDelegate.swift +++ b/Evergreen/MainWindow/AddFeed/FolderTreeControllerDelegate.swift @@ -41,7 +41,7 @@ private extension FolderTreeControllerDelegate { func createNode(_ folder: Folder, parent: Node) -> Node { - let node = Node(representedObject: folder as AnyObject, parent: parent) + let node = Node(representedObject: folder, parent: parent) node.canHaveChildNodes = false return node } diff --git a/Evergreen/MainWindow/Sidebar/SidebarTreeControllerDelegate.swift b/Evergreen/MainWindow/Sidebar/SidebarTreeControllerDelegate.swift index 8e48b0a82..7539fcc03 100644 --- a/Evergreen/MainWindow/Sidebar/SidebarTreeControllerDelegate.swift +++ b/Evergreen/MainWindow/Sidebar/SidebarTreeControllerDelegate.swift @@ -34,16 +34,16 @@ private extension SidebarTreeControllerDelegate { // This will be expanded later to add synthetic feeds (All Unread, for instance) // and other accounts. - return childNodesForContainerNode(rootNode, AccountManager.shared.localAccount.children) + return childNodesForContainerNode(rootNode, AccountManager.shared.localAccount.children as! [AnyHashable]) } func childNodesForFolderNode(_ folderNode: Node) -> [Node]? { let folder = folderNode.representedObject as! Folder - return childNodesForContainerNode(folderNode, folder.children) + return childNodesForContainerNode(folderNode, folder.children as! [AnyHashable]) } - func childNodesForContainerNode(_ containerNode: Node, _ children: [AnyObject]) -> [Node]? { + func childNodesForContainerNode(_ containerNode: Node, _ children: [AnyHashable]) -> [Node]? { var updatedChildNodes = [Node]() @@ -83,15 +83,15 @@ private extension SidebarTreeControllerDelegate { func createNode(folder: Folder, parent: Node) -> Node { - let node = Node(representedObject: folder as AnyObject, parent: parent) + let node = Node(representedObject: folder, parent: parent) node.canHaveChildNodes = true return node } - func nodeInArrayRepresentingObject(_ nodes: [Node], _ representedObject: AnyObject) -> Node? { + func nodeInArrayRepresentingObject(_ nodes: [Node], _ representedObject: AnyHashable) -> Node? { for oneNode in nodes { - if oneNode.representedObject === representedObject { + if oneNode.representedObject == representedObject { return oneNode } } diff --git a/Evergreen/MainWindow/Sidebar/SidebarViewController.swift b/Evergreen/MainWindow/Sidebar/SidebarViewController.swift index 2500c7ca1..334f2e3e8 100644 --- a/Evergreen/MainWindow/Sidebar/SidebarViewController.swift +++ b/Evergreen/MainWindow/Sidebar/SidebarViewController.swift @@ -38,10 +38,10 @@ import RSCore @objc dynamic func unreadCountDidChange(_ note: Notification) { - guard let representedObject = note.object else { + guard let representedObject = note.object as? AnyHashable else { return } - let _ = configureCellsForRepresentedObject(representedObject as AnyObject) + let _ = configureCellsForRepresentedObject(representedObject) } @objc dynamic func containerChildrenDidChange(_ note: Notification) { @@ -172,7 +172,7 @@ private extension SidebarViewController { } } - func postSidebarSelectionDidChangeNotification(_ selectedObjects: [AnyObject]?) { + func postSidebarSelectionDidChangeNotification(_ selectedObjects: [AnyHashable]?) { let appInfo = AppInfo() if let objects = selectedObjects { @@ -186,7 +186,7 @@ private extension SidebarViewController { NotificationCenter.default.post(name: .SidebarSelectionDidChange, object: self, userInfo: appInfo.userInfo) } - func updateUnreadCounts(for objects: [AnyObject]) { + func updateUnreadCounts(for objects: [AnyHashable]) { // On selection, update unread counts for folders and feeds. // For feeds, actually fetch from database. @@ -300,7 +300,7 @@ private extension SidebarViewController { return cells } - func cellsForRepresentedObject(_ representedObject: AnyObject) -> [SidebarCell] { + func cellsForRepresentedObject(_ representedObject: AnyHashable) -> [SidebarCell] { let availableCells = availableSidebarCells() return availableCells.filter{ (oneSidebarCell) -> Bool in @@ -308,11 +308,11 @@ private extension SidebarViewController { guard let oneNode = oneSidebarCell.objectValue as? Node else { return false } - return oneNode.representedObject === representedObject + return oneNode.representedObject == representedObject } } - func configureCellsForRepresentedObject(_ representedObject: AnyObject) -> Bool { + func configureCellsForRepresentedObject(_ representedObject: AnyHashable) -> Bool { //Return true if any cells were configured. @@ -333,7 +333,7 @@ private extension SidebarViewController { } @discardableResult - func revealAndSelectRepresentedObject(_ representedObject: AnyObject) -> Bool { + func revealAndSelectRepresentedObject(_ representedObject: AnyHashable) -> Bool { return outlineView.revealAndSelectRepresentedObject(representedObject, treeController) } diff --git a/Evergreen/MainWindow/Timeline/TimelineViewController.swift b/Evergreen/MainWindow/Timeline/TimelineViewController.swift index 7d3a17635..5242f99e3 100644 --- a/Evergreen/MainWindow/Timeline/TimelineViewController.swift +++ b/Evergreen/MainWindow/Timeline/TimelineViewController.swift @@ -43,7 +43,7 @@ class TimelineViewController: NSViewController, KeyboardDelegate { } } - private var representedObjects: [AnyObject]? { + private var representedObjects: [AnyHashable]? { didSet { if !representedObjectArraysAreEqual(oldValue, representedObjects) { fetchArticles() @@ -479,7 +479,7 @@ private extension TimelineViewController { } } - func representedObjectArraysAreEqual(_ objects1: [AnyObject]?, _ objects2: [AnyObject]?) -> Bool { + func representedObjectArraysAreEqual(_ objects1: [AnyHashable]?, _ objects2: [AnyHashable]?) -> Bool { if objects1 == nil && objects2 == nil { return true @@ -493,7 +493,7 @@ private extension TimelineViewController { var ix = 0 for oneObject in objects1 { - if oneObject !== objects2[ix] { + if oneObject != objects2[ix] { return false } ix += 1 diff --git a/Frameworks/Account/Folder.swift b/Frameworks/Account/Folder.swift index 1c5d0cb63..b82905f36 100644 --- a/Frameworks/Account/Folder.swift +++ b/Frameworks/Account/Folder.swift @@ -10,12 +10,14 @@ import Foundation import Data import RSCore -public final class Folder: DisplayNameProvider, Container, UnreadCountProvider { +public final class Folder: DisplayNameProvider, Container, UnreadCountProvider, Hashable { + public weak var account: Account? public var children = [AnyObject]() var name: String? static let untitledName = NSLocalizedString("Untitled ƒ", comment: "Folder name") + public let hashValue: Int // MARK: - Fetching Articles @@ -52,7 +54,8 @@ public final class Folder: DisplayNameProvider, Container, UnreadCountProvider { self.account = account self.name = name - + self.hashValue = name?.hashValue ?? Folder.untitledName.hashValue + NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil) } @@ -137,6 +140,12 @@ public final class Folder: DisplayNameProvider, Container, UnreadCountProvider { } } + // MARK: - Equatable + + static public func ==(lhs: Folder, rhs: Folder) -> Bool { + + return lhs === rhs + } } // MARK: - Private diff --git a/Frameworks/RSTree/RSTree/NSOutlineView+RSTree.swift b/Frameworks/RSTree/RSTree/NSOutlineView+RSTree.swift index 0ac4c64b9..73ad58d0a 100644 --- a/Frameworks/RSTree/RSTree/NSOutlineView+RSTree.swift +++ b/Frameworks/RSTree/RSTree/NSOutlineView+RSTree.swift @@ -44,7 +44,7 @@ public extension NSOutlineView { } @discardableResult - public func revealAndSelectRepresentedObject(_ representedObject: AnyObject, _ treeController: TreeController) -> Bool { + public func revealAndSelectRepresentedObject(_ representedObject: AnyHashable, _ treeController: TreeController) -> Bool { guard let nodePath = NodePath(representedObject: representedObject, treeController: treeController) else { return false diff --git a/Frameworks/RSTree/RSTree/Node.swift b/Frameworks/RSTree/RSTree/Node.swift index c97649080..991e980b6 100644 --- a/Frameworks/RSTree/RSTree/Node.swift +++ b/Frameworks/RSTree/RSTree/Node.swift @@ -11,7 +11,7 @@ import Foundation public final class Node: Equatable { public weak var parent: Node? - public let representedObject: AnyObject + public let representedObject: AnyHashable public var canHaveChildNodes = false public var isGroupItem = false public var childNodes: [Node]? @@ -59,7 +59,7 @@ public final class Node: Equatable { } } - public init(representedObject: AnyObject, parent: Node?) { + public init(representedObject: AnyHashable, parent: Node?) { self.representedObject = representedObject self.parent = parent @@ -90,14 +90,14 @@ public final class Node: Equatable { } } - public func childNodeRepresentingObject(_ obj: AnyObject) -> Node? { + public func childNodeRepresentingObject(_ obj: AnyHashable) -> Node? { guard let childNodes = childNodes else { return nil } for oneNode in childNodes { - if oneNode.representedObject === obj { + if oneNode.representedObject == obj { return oneNode } } diff --git a/Frameworks/RSTree/RSTree/NodePath.swift b/Frameworks/RSTree/RSTree/NodePath.swift index 1e9fee5d9..0fd6aaf20 100644 --- a/Frameworks/RSTree/RSTree/NodePath.swift +++ b/Frameworks/RSTree/RSTree/NodePath.swift @@ -30,7 +30,7 @@ public struct NodePath { self.components = tempArray.reversed() } - public init?(representedObject: AnyObject, treeController: TreeController) { + public init?(representedObject: AnyHashable, treeController: TreeController) { if let node = treeController.nodeInTreeRepresentingObject(representedObject) { self.init(node: node) diff --git a/Frameworks/RSTree/RSTree/TopLevelRepresentedObject.swift b/Frameworks/RSTree/RSTree/TopLevelRepresentedObject.swift index 7d18d71cf..1644fd226 100644 --- a/Frameworks/RSTree/RSTree/TopLevelRepresentedObject.swift +++ b/Frameworks/RSTree/RSTree/TopLevelRepresentedObject.swift @@ -10,6 +10,12 @@ import Foundation // Handy to use as the represented object for a root node. Not required to use it, though. -final class TopLevelRepresentedObject { - +final class TopLevelRepresentedObject: Hashable { + + let hashValue: Int = 0 + + static func ==(lhs: TopLevelRepresentedObject, rhs: TopLevelRepresentedObject) -> Bool { + + return true + } } diff --git a/Frameworks/RSTree/RSTree/TreeController.swift b/Frameworks/RSTree/RSTree/TreeController.swift index 435b9087e..85ea82f31 100644 --- a/Frameworks/RSTree/RSTree/TreeController.swift +++ b/Frameworks/RSTree/RSTree/TreeController.swift @@ -45,11 +45,11 @@ public final class TreeController { visitNode(rootNode, visitBlock) } - public func nodeInArrayRepresentingObject(nodes: [Node], representedObject: AnyObject, recurse: Bool = false) -> Node? { + public func nodeInArrayRepresentingObject(nodes: [Node], representedObject: AnyHashable, recurse: Bool = false) -> Node? { for oneNode in nodes { - if oneNode.representedObject === representedObject { + if oneNode.representedObject == representedObject { return oneNode } @@ -63,7 +63,7 @@ public final class TreeController { return nil } - public func nodeInTreeRepresentingObject(_ representedObject: AnyObject) -> Node? { + public func nodeInTreeRepresentingObject(_ representedObject: AnyHashable) -> Node? { return nodeInArrayRepresentingObject(nodes: [rootNode], representedObject: representedObject, recurse: true) }