diff --git a/Vienna/Sources/Application/DispatchTimer.swift b/Vienna/Sources/Application/DispatchTimer.swift index a16bce8570..602a7925de 100644 --- a/Vienna/Sources/Application/DispatchTimer.swift +++ b/Vienna/Sources/Application/DispatchTimer.swift @@ -24,7 +24,7 @@ import os.log @objc(VNADispatchTimer) class DispatchTimer: NSObject { - private var dispatchSource: DispatchSourceTimer + private var dispatchSource: any DispatchSourceTimer private(set) var interval: TimeInterval diff --git a/Vienna/Sources/Criteria/Criteria+NSPredicate.swift b/Vienna/Sources/Criteria/Criteria+NSPredicate.swift index d2ccf0565e..96298d5b15 100644 --- a/Vienna/Sources/Criteria/Criteria+NSPredicate.swift +++ b/Vienna/Sources/Criteria/Criteria+NSPredicate.swift @@ -58,7 +58,7 @@ extension CriteriaTree: PredicateConvertible { } for subPredicate in subPredicates { - let criteriaElement: CriteriaElement? + let criteriaElement: (any CriteriaElement)? if let subCompound = subPredicate as? NSCompoundPredicate { // Look ahead to detect "not contains" predicate diff --git a/Vienna/Sources/Criteria/Criteria+XML.swift b/Vienna/Sources/Criteria/Criteria+XML.swift index 5daf839137..571879c218 100644 --- a/Vienna/Sources/Criteria/Criteria+XML.swift +++ b/Vienna/Sources/Criteria/Criteria+XML.swift @@ -22,14 +22,14 @@ import Foundation class CriteriaXmlConverter { @objc - static func toXml(_ criteriaElement: CriteriaElement) -> XMLElement { - guard let criteriaElement = criteriaElement as? Traversable else { + static func toXml(_ criteriaElement: any CriteriaElement) -> XMLElement { + guard let criteriaElement = criteriaElement as? any Traversable else { fatalError("All CriteriaElement subtypes must be Traversable!") } return toXml(criteriaElement) } - static func toXml(_ criteriaElement: Traversable) -> XMLElement { + static func toXml(_ criteriaElement: any Traversable) -> XMLElement { return criteriaElement.traverse { element, subresult in let criteriaTreeXml = XMLElement(name: CriteriaTree.groupTag) criteriaTreeXml.setAttributesWith([CriteriaTree.conditionAttribute: "\(element.condition)"]) @@ -52,14 +52,14 @@ class CriteriaXmlConverter { } @objc - static func from(xml: XMLElement?) -> CriteriaElement? { + static func from(xml: XMLElement?) -> (any CriteriaElement)? { guard let (subtree, condition) = subtreeAndConditionFrom(xml: xml) else { return nil } return CriteriaTree(subtree: subtree, condition: condition) } - static func subtreeAndConditionFrom(xml: XMLElement?) -> (subtree: [Traversable], condition: CriteriaCondition)? { + static func subtreeAndConditionFrom(xml: XMLElement?) -> (subtree: [any Traversable], condition: CriteriaCondition)? { guard let xml = xml else { NSLog("CriteriaTree cannot be initialized from nil xml") return nil @@ -69,14 +69,14 @@ class CriteriaXmlConverter { // assumes that we're matching ALL conditions. let conditionString = xml.attribute(forName: CriteriaTree.conditionAttribute)?.stringValue ?? "" - var subtree: [Traversable] = [] + var subtree: [any Traversable] = [] for child in xml.children ?? [] { guard let child = child as? XMLElement, child.name == CriteriaTree.groupTag || child.name == CriteriaTree.criteriaTag else { NSLog("Invalid node \(child) in criteria xml discovered.") return nil } - let subCriteriaElement: CriteriaElement + let subCriteriaElement: any CriteriaElement if child.name == CriteriaTree.groupTag { guard let subCriteriaTree = CriteriaTree(xml: child) else { NSLog("CriteriaTree cannot be initialized from \(child)") @@ -90,7 +90,7 @@ class CriteriaXmlConverter { } subCriteriaElement = subCriterion } - guard let subtreeElement = subCriteriaElement as? Traversable else { + guard let subtreeElement = subCriteriaElement as? (any Traversable) else { fatalError("All CriteriaElement subtypes must be Traversable!") } subtree.append(subtreeElement) @@ -127,7 +127,7 @@ extension CriteriaTree { @objc convenience init?(string: String) { - var xmlError: Error? + var xmlError: (any Error)? var criteriaTreeXml: XMLDocument? do { criteriaTreeXml = try XMLDocument(xmlString: string) diff --git a/Vienna/Sources/Criteria/Criteria.swift b/Vienna/Sources/Criteria/Criteria.swift index 26553b7c61..f965fe76b5 100644 --- a/Vienna/Sources/Criteria/Criteria.swift +++ b/Vienna/Sources/Criteria/Criteria.swift @@ -98,24 +98,24 @@ protocol Traversable: CriteriaElement { @objc class CriteriaTree: NSObject, Traversable { // Workaround while this variable is needed for objc (Traversable cannot be exposed) - @objc var criteriaTree: [CriteriaElement] { + @objc var criteriaTree: [any CriteriaElement] { get { traversableTree } set { - self.traversableTree = newValue as? [Traversable] ?? [] + self.traversableTree = newValue as? [any Traversable] ?? [] } } var condition: CriteriaCondition - var traversableTree: [Traversable] + var traversableTree: [any Traversable] override convenience init() { self.init(subtree: [], condition: .all) } - init(subtree: [Traversable], condition: CriteriaCondition) { + init(subtree: [any Traversable], condition: CriteriaCondition) { traversableTree = subtree self.condition = condition } diff --git a/Vienna/Sources/Main window/ArticleContentView.swift b/Vienna/Sources/Main window/ArticleContentView.swift index 817460840b..241feb3f6d 100644 --- a/Vienna/Sources/Main window/ArticleContentView.swift +++ b/Vienna/Sources/Main window/ArticleContentView.swift @@ -10,7 +10,7 @@ import Cocoa @objc protocol ArticleContentView { - var listView: ArticleViewDelegate? { get set } + var listView: (any ArticleViewDelegate)? { get set } var articles: [Article] { get set } @objc(keyDown:) diff --git a/Vienna/Sources/Main window/Browser.swift b/Vienna/Sources/Main window/Browser.swift index 4b4d03e0aa..77292d9dbe 100644 --- a/Vienna/Sources/Main window/Browser.swift +++ b/Vienna/Sources/Main window/Browser.swift @@ -36,7 +36,7 @@ protocol Browser { /// A tabbed browser always has one tab that is selected. It is called the active tab. /// In case the primary tab is selected, the return value is nil /// (because it does not necessarily implement the Tab protocol) - var activeTab: Tab? { get } + var activeTab: (any Tab)? { get } /// Add a new tab to the open tabs of the browser /// @@ -46,7 +46,7 @@ protocol Browser { /// - load: whether the page to which the URL points is supposed to be loaded immediately /// (otherwise it is opened when opening the tab) /// - Returns: the new tab - func createNewTab(_ url: URL?, inBackground: Bool, load: Bool) -> Tab + func createNewTab(_ url: URL?, inBackground: Bool, load: Bool) -> any Tab /// Saves all tabs persistently. /// Next time when instanciating the browser, these tabs will be re-instanciated as well. diff --git a/Vienna/Sources/Main window/BrowserTab+RSSSource.swift b/Vienna/Sources/Main window/BrowserTab+RSSSource.swift index 5dad93b7c1..2645614475 100644 --- a/Vienna/Sources/Main window/BrowserTab+RSSSource.swift +++ b/Vienna/Sources/Main window/BrowserTab+RSSSource.swift @@ -36,7 +36,7 @@ extension BrowserTab: RSSSource { } } - var rssSubscriber: RSSSubscriber? { + var rssSubscriber: (any RSSSubscriber)? { get { self.rssDelegate } diff --git a/Vienna/Sources/Main window/BrowserTab.swift b/Vienna/Sources/Main window/BrowserTab.swift index 2b3253a4e5..12bdc8a89c 100644 --- a/Vienna/Sources/Main window/BrowserTab.swift +++ b/Vienna/Sources/Main window/BrowserTab.swift @@ -62,7 +62,7 @@ class BrowserTab: NSViewController { var navigationEndHandler: [(_ success: Bool) -> Void] = [] /// backing storage only, access via rssSubscriber property - weak var rssDelegate: RSSSubscriber? + weak var rssDelegate: (any RSSSubscriber)? /// backing storage only, access via rssUrl property var rssFeedUrls: [URL] = [] @@ -353,12 +353,12 @@ extension BrowserTab: WKNavigationDelegate { handleNavigationStart() } - func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation?, withError error: Error) { + func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation?, withError error: any Error) { // TODO: provisional navigation fail seems to translate to error in resolving URL or similar. Treat different from normal navigation fail handleNavigationEnd(success: false) } - func webView(_ webView: WKWebView, didFail navigation: WKNavigation?, withError error: Error) { + func webView(_ webView: WKWebView, didFail navigation: WKNavigation?, withError error: any Error) { // TODO: show failure to load as page or symbol handleNavigationEnd(success: false) } diff --git a/Vienna/Sources/Main window/ButtonToolbarItem.swift b/Vienna/Sources/Main window/ButtonToolbarItem.swift index 9a9e46211f..eb12b8d99e 100644 --- a/Vienna/Sources/Main window/ButtonToolbarItem.swift +++ b/Vienna/Sources/Main window/ButtonToolbarItem.swift @@ -79,7 +79,7 @@ class ButtonToolbarItem: NSToolbarItem { } switch NSApp.target(forAction: action, to: target, from: self) { - case let validator as NSToolbarItemValidation: + case let validator as any NSToolbarItemValidation: isEnabled = validator.validateToolbarItem(self) default: isEnabled = false diff --git a/Vienna/Sources/Main window/CustomWKWebView.swift b/Vienna/Sources/Main window/CustomWKWebView.swift index 562f6eaa28..9a02e02e59 100644 --- a/Vienna/Sources/Main window/CustomWKWebView.swift +++ b/Vienna/Sources/Main window/CustomWKWebView.swift @@ -18,13 +18,13 @@ class CustomWKWebView: WKWebView { // store weakly here because contentController retains listener weak var contextMenuListener: CustomWKWebViewContextMenuListener? - weak var contextMenuProvider: CustomWKUIDelegate? { + weak var contextMenuProvider: (any CustomWKUIDelegate)? { didSet { self.uiDelegate = contextMenuProvider } } - @objc weak var hoverUiDelegate: CustomWKHoverUIDelegate? { + @objc weak var hoverUiDelegate: (any CustomWKHoverUIDelegate)? { didSet { resetHoverUiListener() } @@ -393,9 +393,9 @@ extension CustomWKWebView { class CustomWKWebViewHoverListener: NSObject, WKScriptMessageHandler { - weak var hoverDelegate: CustomWKHoverUIDelegate? + weak var hoverDelegate: (any CustomWKHoverUIDelegate)? - init(hoverDelegate: CustomWKHoverUIDelegate) { + init(hoverDelegate: any CustomWKHoverUIDelegate) { self.hoverDelegate = hoverDelegate } diff --git a/Vienna/Sources/Main window/MainWindowController.swift b/Vienna/Sources/Main window/MainWindowController.swift index 5ee56abeb2..3aeab3dbad 100644 --- a/Vienna/Sources/Main window/MainWindowController.swift +++ b/Vienna/Sources/Main window/MainWindowController.swift @@ -35,8 +35,8 @@ final class MainWindowController: NSWindowController { @objc private(set) var toolbarSearchField: NSSearchField? @IBOutlet private(set) weak var placeholderDetailView: NSView! - @objc private(set) lazy var browser: (Browser & NSViewController) = { - var controller = TabbedBrowserViewController() as (Browser & NSViewController) + @objc private(set) lazy var browser: (any Browser & NSViewController) = { + var controller = TabbedBrowserViewController() as (any Browser & NSViewController) return controller }() @@ -48,7 +48,7 @@ final class MainWindowController: NSWindowController { // cf. https://stackoverflow.com/q/16587058 splitView.autosaveName = "VNASplitView" - (self.browser as? RSSSource)?.rssSubscriber = self + (self.browser as? any RSSSource)?.rssSubscriber = self statusBarState(disclosed: Preferences.standard.showStatusBar, animate: false) @@ -177,7 +177,7 @@ final class MainWindowController: NSWindowController { var shareableItemsSubject = String() - private var shareableItems: [NSPasteboardWriting] { + private var shareableItems: [any NSPasteboardWriting] { var items = [URL]() if let activeTab = browser.activeTab, let url = activeTab.tabUrl { items.append(url) @@ -518,7 +518,7 @@ extension MainWindowController: NSSharingServicePickerDelegate { func sharingServicePicker( _ sharingServicePicker: NSSharingServicePicker, delegateFor sharingService: NSSharingService - ) -> NSSharingServiceDelegate? { + ) -> (any NSSharingServiceDelegate)? { return self } diff --git a/Vienna/Sources/Main window/RSSSubscriber.swift b/Vienna/Sources/Main window/RSSSubscriber.swift index 999640ae66..e3c5e04d34 100644 --- a/Vienna/Sources/Main window/RSSSubscriber.swift +++ b/Vienna/Sources/Main window/RSSSubscriber.swift @@ -49,5 +49,5 @@ extension RSSSubscriber { } protocol RSSSource: AnyObject { - var rssSubscriber: RSSSubscriber? { get set } + var rssSubscriber: (any RSSSubscriber)? { get set } } diff --git a/Vienna/Sources/Main window/TabbedBrowserViewController.swift b/Vienna/Sources/Main window/TabbedBrowserViewController.swift index 016a88e7f8..180165ef8f 100644 --- a/Vienna/Sources/Main window/TabbedBrowserViewController.swift +++ b/Vienna/Sources/Main window/TabbedBrowserViewController.swift @@ -63,18 +63,18 @@ class TabbedBrowserViewController: NSViewController, RSSSource { var restoredTabs = false - var activeTab: Tab? { - tabView?.selectedTabViewItem?.viewController as? Tab + var activeTab: (any Tab)? { + tabView?.selectedTabViewItem?.viewController as? any Tab } var browserTabCount: Int { tabView?.numberOfTabViewItems ?? 0 } - weak var rssSubscriber: RSSSubscriber? { + weak var rssSubscriber: (any RSSSubscriber)? { didSet { for source in tabView?.tabViewItems ?? [] { - (source as? RSSSource)?.rssSubscriber = self.rssSubscriber + (source as? any RSSSource)?.rssSubscriber = self.rssSubscriber } } } @@ -152,21 +152,21 @@ class TabbedBrowserViewController: NSViewController, RSSSource { } extension TabbedBrowserViewController: Browser { - func createNewTab(_ url: URL?, inBackground: Bool, load: Bool) -> Tab { + func createNewTab(_ url: URL?, inBackground: Bool, load: Bool) -> any Tab { createNewTab(url, inBackground: inBackground, load: load, insertAt: nil) } - func createNewTab(_ request: URLRequest, config: WKWebViewConfiguration, inBackground: Bool, insertAt index: Int? = nil) -> Tab { + func createNewTab(_ request: URLRequest, config: WKWebViewConfiguration, inBackground: Bool, insertAt index: Int? = nil) -> any Tab { let newTab = BrowserTab(request, config: config) return initNewTab(newTab, request.url, false, inBackground, insertAt: index) } - func createNewTab(_ url: URL? = nil, inBackground: Bool = false, load: Bool = false, insertAt index: Int? = nil) -> Tab { + func createNewTab(_ url: URL? = nil, inBackground: Bool = false, load: Bool = false, insertAt index: Int? = nil) -> any Tab { let newTab = BrowserTab() return initNewTab(newTab, url, load, inBackground, insertAt: index) } - private func initNewTab(_ newTab: BrowserTab, _ url: URL?, _ load: Bool, _ inBackground: Bool, insertAt index: Int? = nil) -> Tab { + private func initNewTab(_ newTab: BrowserTab, _ url: URL?, _ load: Bool, _ inBackground: Bool, insertAt index: Int? = nil) -> any Tab { newTab.rssSubscriber = self.rssSubscriber let newTabViewItem = TitleChangingTabViewItem(viewController: newTab) @@ -258,7 +258,7 @@ extension TabbedBrowserViewController: MMTabBarViewDelegate { } func tabView(_ aTabView: NSTabView, willClose tabViewItem: NSTabViewItem) { - guard let tab = tabViewItem.viewController as? Tab else { + guard let tab = tabViewItem.viewController as? any Tab else { return } tab.closeTab() @@ -288,7 +288,7 @@ extension TabbedBrowserViewController: MMTabBarViewDelegate { tabViewItem != primaryTab } - func tabView(_ aTabView: NSTabView, validateDrop sender: NSDraggingInfo, proposedItem tabViewItem: NSTabViewItem, proposedIndex: UInt, in tabBarView: MMTabBarView) -> NSDragOperation { + func tabView(_ aTabView: NSTabView, validateDrop sender: any NSDraggingInfo, proposedItem tabViewItem: NSTabViewItem, proposedIndex: UInt, in tabBarView: MMTabBarView) -> NSDragOperation { proposedIndex != 0 ? [.every] : [] } @@ -321,7 +321,7 @@ extension TabbedBrowserViewController: MMTabBarViewDelegate { extension TabbedBrowserViewController: CustomWKUIDelegate { // TODO: implement functionality for alerts and maybe peek actions - private static var contextMenuCustomizer: BrowserContextMenuDelegate = WebKitContextMenuCustomizer() + private static var contextMenuCustomizer: any BrowserContextMenuDelegate = WebKitContextMenuCustomizer() func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? { let newTab = self.createNewTab(navigationAction.request, config: configuration, inBackground: false, insertAt: getIndexAfterSelected()) diff --git a/Vienna/Sources/Main window/WebKitArticleTab.swift b/Vienna/Sources/Main window/WebKitArticleTab.swift index 0638e02882..7fd4e2d9d4 100644 --- a/Vienna/Sources/Main window/WebKitArticleTab.swift +++ b/Vienna/Sources/Main window/WebKitArticleTab.swift @@ -35,7 +35,7 @@ class WebKitArticleTab: BrowserTab, ArticleContentView { } } - var listView: ArticleViewDelegate? + var listView: (any ArticleViewDelegate)? var articles: [Article] { get { @@ -119,7 +119,7 @@ class WebKitArticleTab: BrowserTab, ArticleContentView { NotificationCenter.default.post(name: .articleViewEnded, object: self) } - override func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { + override func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: any Error) { super.webView(webView, didFailProvisionalNavigation: navigation, withError: error) NotificationCenter.default.post(name: .articleViewEnded, object: self) } diff --git a/Vienna/Sources/Main window/WebKitArticleView.swift b/Vienna/Sources/Main window/WebKitArticleView.swift index 543c6f7a54..7c1e328f6b 100644 --- a/Vienna/Sources/Main window/WebKitArticleView.swift +++ b/Vienna/Sources/Main window/WebKitArticleView.swift @@ -22,7 +22,7 @@ import WebKit class WebKitArticleView: CustomWKWebView, ArticleContentView, WKNavigationDelegate, CustomWKUIDelegate { - var listView: ArticleViewDelegate? + var listView: (any ArticleViewDelegate)? var articles: [Article] = [] { didSet { @@ -43,7 +43,7 @@ class WebKitArticleView: CustomWKWebView, ArticleContentView, WKNavigationDelega let converter = WebKitArticleConverter() - let contextMenuCustomizer: BrowserContextMenuDelegate = WebKitContextMenuCustomizer() + let contextMenuCustomizer: any BrowserContextMenuDelegate = WebKitContextMenuCustomizer() @objc init(frame: NSRect) { diff --git a/Vienna/Sources/Parsing/JSONFeed.swift b/Vienna/Sources/Parsing/JSONFeed.swift index 19133099a3..fb5c880347 100644 --- a/Vienna/Sources/Parsing/JSONFeed.swift +++ b/Vienna/Sources/Parsing/JSONFeed.swift @@ -35,7 +35,7 @@ class JSONFeed: NSObject, Feed, Decodable { var modifiedDate: Date? // The `items` key is required (but the array may be empty). - var items: [FeedItem] + var items: [any FeedItem] // MARK: Decodable @@ -52,7 +52,7 @@ class JSONFeed: NSObject, Feed, Decodable { case author } - required init(from decoder: Decoder) throws { + required init(from decoder: any Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) title = try container.decode(String.self, forKey: .title) diff --git a/Vienna/Sources/Parsing/JSONFeedItem.swift b/Vienna/Sources/Parsing/JSONFeedItem.swift index 2f846b2ca0..2a9e22bfe5 100644 --- a/Vienna/Sources/Parsing/JSONFeedItem.swift +++ b/Vienna/Sources/Parsing/JSONFeedItem.swift @@ -65,7 +65,7 @@ class JSONFeedItem: NSObject, FeedItem, Decodable { case attachments } - required init(from decoder: Decoder) throws { + required init(from decoder: any Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) guid = try container.decode(String.self, forKey: .id)