Use AnyHashable instead of AnyObject as representedObject for tree nodes.
This commit is contained in:
parent
1adaebf2bf
commit
c08bbaa970
|
@ -40,7 +40,7 @@ final class AppInfo {
|
|||
var article: Article?
|
||||
var articles: Set<Article>?
|
||||
var navigationKey: Int?
|
||||
var objects: [AnyObject]?
|
||||
var objects: [AnyHashable]?
|
||||
var feed: Feed?
|
||||
|
||||
static let appInfoKey = "appInfo"
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue