diff --git a/Mac/MainWindow/MainWindowController.swift b/Mac/MainWindow/MainWindowController.swift index d9523f961..c5159dc8b 100644 --- a/Mac/MainWindow/MainWindowController.swift +++ b/Mac/MainWindow/MainWindowController.swift @@ -426,15 +426,12 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations { extension MainWindowController: NSWindowDelegate { func window(_ window: NSWindow, willEncodeRestorableState coder: NSCoder) { - saveSplitViewState(to: coder) - sidebarViewController?.saveState(to: coder) - timelineContainerViewController?.saveState(to: coder) + coder.encode(savableState(), forKey: UserInfoKey.windowState) } func window(_ window: NSWindow, didDecodeRestorableState coder: NSCoder) { - restoreSplitViewState(from: coder) - sidebarViewController?.restoreState(from: coder) - timelineContainerViewController?.restoreState(from: coder) + guard let state = try? coder.decodeTopLevelObject(forKey: UserInfoKey.windowState) as? [AnyHashable : Any] else { return } + restoreState(from: state) } func windowWillClose(_ notification: Notification) { @@ -704,6 +701,22 @@ private extension MainWindowController { return oneSelectedArticle?.preferredLink } + // MARK: - State Restoration + + func savableState() -> [AnyHashable : Any] { + var state = [AnyHashable : Any]() + saveSplitViewState(to: &state) + sidebarViewController?.saveState(to: &state) + timelineContainerViewController?.saveState(to: &state) + return state + } + + func restoreState(from state: [AnyHashable : Any]) { + restoreSplitViewState(from: state) + sidebarViewController?.restoreState(from: state) + timelineContainerViewController?.restoreState(from: state) + } + // MARK: - Command Validation func canGoToNextUnread() -> Bool { @@ -912,18 +925,18 @@ private extension MainWindowController { } } - func saveSplitViewState(to coder: NSCoder) { + func saveSplitViewState(to state: inout [AnyHashable : Any]) { guard let splitView = splitViewController?.splitView else { return } let widths = splitView.arrangedSubviews.map{ Int(floor($0.frame.width)) } - coder.encode(widths, forKey: MainWindowController.mainWindowWidthsStateKey) + state[MainWindowController.mainWindowWidthsStateKey] = widths } - func restoreSplitViewState(from coder: NSCoder) { + func restoreSplitViewState(from state: [AnyHashable : Any]) { guard let splitView = splitViewController?.splitView, - let widths = try? coder.decodeTopLevelObject(forKey: MainWindowController.mainWindowWidthsStateKey) as? [Int], + let widths = state[MainWindowController.mainWindowWidthsStateKey] as? [Int], widths.count == 3, let window = window else { return diff --git a/Mac/MainWindow/Sidebar/SidebarViewController.swift b/Mac/MainWindow/Sidebar/SidebarViewController.swift index 5f42cd10c..cb5b688e5 100644 --- a/Mac/MainWindow/Sidebar/SidebarViewController.swift +++ b/Mac/MainWindow/Sidebar/SidebarViewController.swift @@ -90,20 +90,20 @@ protocol SidebarDelegate: class { // MARK: State Restoration - func saveState(to coder: NSCoder) { - coder.encode(isReadFiltered, forKey: UserInfoKey.readFeedsFilterState) - coder.encode(expandedTable.map( { $0.userInfo }), forKey: UserInfoKey.containerExpandedWindowState) - coder.encode(selectedFeeds.compactMap({ $0.feedID?.userInfo }), forKey: UserInfoKey.selectedFeedsState) + func saveState(to state: inout [AnyHashable : Any]) { + state[UserInfoKey.readFeedsFilterState] = isReadFiltered + state[UserInfoKey.containerExpandedWindowState] = expandedTable.map { $0.userInfo } + state[UserInfoKey.selectedFeedsState] = selectedFeeds.compactMap { $0.feedID?.userInfo } } - func restoreState(from coder: NSCoder) { + func restoreState(from state: [AnyHashable : Any]) { - if let containerExpandedWindowState = try? coder.decodeTopLevelObject(forKey: UserInfoKey.containerExpandedWindowState) as? [[AnyHashable: AnyHashable]] { + if let containerExpandedWindowState = state[UserInfoKey.containerExpandedWindowState] as? [[AnyHashable: AnyHashable]] { let containerIdentifers = containerExpandedWindowState.compactMap( { ContainerIdentifier(userInfo: $0) }) expandedTable = Set(containerIdentifers) } - guard let selectedFeedsState = try? coder.decodeTopLevelObject(forKey: UserInfoKey.selectedFeedsState) as? [[AnyHashable: AnyHashable]] else { + guard let selectedFeedsState = state[UserInfoKey.selectedFeedsState] as? [[AnyHashable: AnyHashable]] else { return } @@ -126,7 +126,9 @@ protocol SidebarDelegate: class { outlineView.selectRowIndexes(selectIndexes, byExtendingSelection: false) focus() - isReadFiltered = coder.decodeBool(forKey: UserInfoKey.readFeedsFilterState) + if let readFeedsFilterState = state[UserInfoKey.readFeedsFilterState] as? Bool { + isReadFiltered = readFeedsFilterState + } } // MARK: - Notifications diff --git a/Mac/MainWindow/Timeline/TimelineContainerViewController.swift b/Mac/MainWindow/Timeline/TimelineContainerViewController.swift index 9dcefff47..159278ade 100644 --- a/Mac/MainWindow/Timeline/TimelineContainerViewController.swift +++ b/Mac/MainWindow/Timeline/TimelineContainerViewController.swift @@ -95,12 +95,12 @@ final class TimelineContainerViewController: NSViewController { // MARK: State Restoration - func saveState(to coder: NSCoder) { - regularTimelineViewController.saveState(to: coder) + func saveState(to state: inout [AnyHashable : Any]) { + regularTimelineViewController.saveState(to: &state) } - func restoreState(from coder: NSCoder) { - regularTimelineViewController.restoreState(from: coder) + func restoreState(from state: [AnyHashable : Any]) { + regularTimelineViewController.restoreState(from: state) } } diff --git a/Mac/MainWindow/Timeline/TimelineViewController.swift b/Mac/MainWindow/Timeline/TimelineViewController.swift index 6e1de56b5..d88c5721b 100644 --- a/Mac/MainWindow/Timeline/TimelineViewController.swift +++ b/Mac/MainWindow/Timeline/TimelineViewController.swift @@ -247,20 +247,20 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr // MARK: State Restoration - func saveState(to coder: NSCoder) { + func saveState(to state: inout [AnyHashable : Any]) { var readArticlesFilterState = [[AnyHashable: AnyHashable]: Bool]() for key in readFilterEnabledTable.keys { readArticlesFilterState[key.userInfo] = readFilterEnabledTable[key] } - coder.encode(readArticlesFilterState, forKey: UserInfoKey.readArticlesFilterState) + state[UserInfoKey.readArticlesFilterState] = readArticlesFilterState if selectedArticles.count == 1 { - coder.encode(selectedArticles.first!.pathUserInfo, forKey: UserInfoKey.articlePath) + state[UserInfoKey.articlePath] = selectedArticles.first!.pathUserInfo } } - func restoreState(from coder: NSCoder) { - if let readArticlesFilterState = try? coder.decodeTopLevelObject(forKey: UserInfoKey.readArticlesFilterState) as? [[AnyHashable: AnyHashable]: Bool] { + func restoreState(from state: [AnyHashable : Any]) { + if let readArticlesFilterState = state[UserInfoKey.readArticlesFilterState] as? [[AnyHashable: AnyHashable]: Bool] { for key in readArticlesFilterState.keys { if let feedIdentifier = FeedIdentifier(userInfo: key) { readFilterEnabledTable[feedIdentifier] = readArticlesFilterState[key] @@ -268,7 +268,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr } } - guard let articlePathUserInfo = try? coder.decodeTopLevelObject(forKey: UserInfoKey.articlePath) as? [AnyHashable : Any], + guard let articlePathUserInfo = state[UserInfoKey.articlePath] as? [AnyHashable : Any], let accountID = articlePathUserInfo[ArticlePathKey.accountID] as? String, let account = AccountManager.shared.existingAccount(with: accountID), let articleID = articlePathUserInfo[ArticlePathKey.articleID] as? String else {