diff --git a/Account/Sources/Account/Account.swift b/Account/Sources/Account/Account.swift index 6c423541d..2ec027dbe 100644 --- a/Account/Sources/Account/Account.swift +++ b/Account/Sources/Account/Account.swift @@ -612,6 +612,7 @@ public enum FetchType { try await delegate.addFeed(for: self, with: feed, to: container) } + @discardableResult public func createFeed(url: String, name: String?, container: Container, validateFeed: Bool) async throws -> Feed { try await delegate.createFeed(for: self, url: url, name: name, container: container, validateFeed: validateFeed) diff --git a/Account/Sources/Account/LocalAccount/LocalAccountRefresher.swift b/Account/Sources/Account/LocalAccount/LocalAccountRefresher.swift index 09a16387c..31851db22 100644 --- a/Account/Sources/Account/LocalAccount/LocalAccountRefresher.swift +++ b/Account/Sources/Account/LocalAccount/LocalAccountRefresher.swift @@ -14,11 +14,11 @@ import ArticlesDatabase import FoundationExtras protocol LocalAccountRefresherDelegate { - func localAccountRefresher(_ refresher: LocalAccountRefresher, requestCompletedFor: Feed) - func localAccountRefresher(_ refresher: LocalAccountRefresher, articleChanges: ArticleChanges, completion: @escaping () -> Void) + @MainActor func localAccountRefresher(_ refresher: LocalAccountRefresher, requestCompletedFor: Feed) + @MainActor func localAccountRefresher(_ refresher: LocalAccountRefresher, articleChanges: ArticleChanges, completion: @escaping () -> Void) } -final class LocalAccountRefresher { +@MainActor final class LocalAccountRefresher { private var completion: (() -> Void)? = nil private var isSuspended = false diff --git a/Mac/MainWindow/Sidebar/PasteboardFeed.swift b/Mac/MainWindow/Sidebar/PasteboardFeed.swift index 6119734d0..e0745578b 100644 --- a/Mac/MainWindow/Sidebar/PasteboardFeed.swift +++ b/Mac/MainWindow/Sidebar/PasteboardFeed.swift @@ -13,7 +13,7 @@ import AppKitExtras typealias PasteboardFeedDictionary = [String: String] -struct PasteboardFeed: Hashable { +@MainActor struct PasteboardFeed: Hashable { private struct Key { static let url = "URL" diff --git a/Mac/MainWindow/Timeline/ArticlePasteboardWriter.swift b/Mac/MainWindow/Timeline/ArticlePasteboardWriter.swift index 3645ea179..42cbf0a5e 100644 --- a/Mac/MainWindow/Timeline/ArticlePasteboardWriter.swift +++ b/Mac/MainWindow/Timeline/ArticlePasteboardWriter.swift @@ -36,36 +36,42 @@ extension Article: PasteboardWriterOwner { // MARK: - NSPasteboardWriting - func writableTypes(for pasteboard: NSPasteboard) -> [NSPasteboard.PasteboardType] { - var types = [ArticlePasteboardWriter.articleUTIType] + nonisolated func writableTypes(for pasteboard: NSPasteboard) -> [NSPasteboard.PasteboardType] { - if let _ = article.preferredURL { - types += [.URL] + MainActor.assumeIsolated { + var types = [ArticlePasteboardWriter.articleUTIType] + + if let _ = article.preferredURL { + types += [.URL] + } + types += [.string, .html, ArticlePasteboardWriter.articleUTIInternalType] + + return types } - types += [.string, .html, ArticlePasteboardWriter.articleUTIInternalType] - - return types } - func pasteboardPropertyList(forType type: NSPasteboard.PasteboardType) -> Any? { - let plist: Any? + nonisolated func pasteboardPropertyList(forType type: NSPasteboard.PasteboardType) -> Any? { - switch type { - case .html: - return renderedHTML - case .string: - plist = plainText() - case .URL: - return article.preferredLink ?? "" - case ArticlePasteboardWriter.articleUTIType: - plist = exportDictionary() - case ArticlePasteboardWriter.articleUTIInternalType: - plist = internalDictionary() - default: - plist = nil + MainActor.assumeIsolated { + let plist: Any? + + switch type { + case .html: + return renderedHTML + case .string: + plist = plainText() + case .URL: + return article.preferredLink ?? "" + case ArticlePasteboardWriter.articleUTIType: + plist = exportDictionary() + case ArticlePasteboardWriter.articleUTIInternalType: + plist = internalDictionary() + default: + plist = nil + } + + return plist } - - return plist } } diff --git a/Shared/Extensions/SmallIconProvider.swift b/Shared/Extensions/SmallIconProvider.swift index bd935cd72..81a7ce7a7 100644 --- a/Shared/Extensions/SmallIconProvider.swift +++ b/Shared/Extensions/SmallIconProvider.swift @@ -12,7 +12,7 @@ import Account protocol SmallIconProvider { - var smallIcon: IconImage? { get } + @MainActor var smallIcon: IconImage? { get } } extension Account: SmallIconProvider { diff --git a/Shared/ShareExtension/ExtensionContainersFile.swift b/Shared/ShareExtension/ExtensionContainersFile.swift index 8196686f2..3d3f2a515 100644 --- a/Shared/ShareExtension/ExtensionContainersFile.swift +++ b/Shared/ShareExtension/ExtensionContainersFile.swift @@ -12,7 +12,7 @@ import Parser import Account import Core -final class ExtensionContainersFile { +@MainActor final class ExtensionContainersFile { private static let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "extensionContainersFile") diff --git a/Shared/SidebarItem/SidebarItemIdentifier.swift b/Shared/SidebarItem/SidebarItemIdentifier.swift index 7041d2c76..586c39113 100644 --- a/Shared/SidebarItem/SidebarItemIdentifier.swift +++ b/Shared/SidebarItem/SidebarItemIdentifier.swift @@ -10,7 +10,7 @@ import Foundation import Account protocol SidebarItemIdentifiable { - var sidebarItemID: SidebarItemIdentifier? { get } + @MainActor var sidebarItemID: SidebarItemIdentifier? { get } } enum SidebarItemIdentifier: CustomStringConvertible, Hashable, Equatable { diff --git a/Shared/SmartFeeds/SearchFeedDelegate.swift b/Shared/SmartFeeds/SearchFeedDelegate.swift index 923200d35..5c0406722 100644 --- a/Shared/SmartFeeds/SearchFeedDelegate.swift +++ b/Shared/SmartFeeds/SearchFeedDelegate.swift @@ -11,7 +11,7 @@ import Account import Articles import ArticlesDatabase -struct SearchFeedDelegate: SmartFeedDelegate { +@MainActor struct SearchFeedDelegate: SmartFeedDelegate { var sidebarItemID: SidebarItemIdentifier? { return SidebarItemIdentifier.smartFeed(String(describing: SearchFeedDelegate.self)) diff --git a/Shared/SmartFeeds/SearchTimelineFeedDelegate.swift b/Shared/SmartFeeds/SearchTimelineFeedDelegate.swift index e420001f0..a82cb3383 100644 --- a/Shared/SmartFeeds/SearchTimelineFeedDelegate.swift +++ b/Shared/SmartFeeds/SearchTimelineFeedDelegate.swift @@ -11,7 +11,7 @@ import Account import Articles import ArticlesDatabase -struct SearchTimelineFeedDelegate: SmartFeedDelegate { +@MainActor struct SearchTimelineFeedDelegate: SmartFeedDelegate { var sidebarItemID: SidebarItemIdentifier? { return SidebarItemIdentifier.smartFeed(String(describing: SearchTimelineFeedDelegate.self)) diff --git a/Web/Sources/Web/DownloadSession.swift b/Web/Sources/Web/DownloadSession.swift index c15edfb9e..a22c39aab 100755 --- a/Web/Sources/Web/DownloadSession.swift +++ b/Web/Sources/Web/DownloadSession.swift @@ -13,17 +13,17 @@ import Foundation public protocol DownloadSessionDelegate { - func downloadSession(_ downloadSession: DownloadSession, requestForRepresentedObject: AnyObject) -> URLRequest? - func downloadSession(_ downloadSession: DownloadSession, downloadDidCompleteForRepresentedObject: AnyObject, response: URLResponse?, data: Data, error: NSError?, completion: @escaping () -> Void) - func downloadSession(_ downloadSession: DownloadSession, shouldContinueAfterReceivingData: Data, representedObject: AnyObject) -> Bool - func downloadSession(_ downloadSession: DownloadSession, didReceiveUnexpectedResponse: URLResponse, representedObject: AnyObject) - func downloadSession(_ downloadSession: DownloadSession, didReceiveNotModifiedResponse: URLResponse, representedObject: AnyObject) - func downloadSession(_ downloadSession: DownloadSession, didDiscardDuplicateRepresentedObject: AnyObject) - func downloadSessionDidCompleteDownloadObjects(_ downloadSession: DownloadSession) - + @MainActor func downloadSession(_ downloadSession: DownloadSession, requestForRepresentedObject: AnyObject) -> URLRequest? + @MainActor func downloadSession(_ downloadSession: DownloadSession, downloadDidCompleteForRepresentedObject: AnyObject, response: URLResponse?, data: Data, error: NSError?, completion: @escaping () -> Void) + @MainActor func downloadSession(_ downloadSession: DownloadSession, shouldContinueAfterReceivingData: Data, representedObject: AnyObject) -> Bool + @MainActor func downloadSession(_ downloadSession: DownloadSession, didReceiveUnexpectedResponse: URLResponse, representedObject: AnyObject) + @MainActor func downloadSession(_ downloadSession: DownloadSession, didReceiveNotModifiedResponse: URLResponse, representedObject: AnyObject) + @MainActor func downloadSession(_ downloadSession: DownloadSession, didDiscardDuplicateRepresentedObject: AnyObject) + @MainActor func downloadSessionDidCompleteDownloadObjects(_ downloadSession: DownloadSession) + } -@objc public final class DownloadSession: NSObject { +@MainActor @objc public final class DownloadSession: NSObject { private var urlSession: URLSession! private var tasksInProgress = Set() @@ -70,7 +70,7 @@ public protocol DownloadSessionDelegate { } } - public func downloadObjects(_ objects: NSSet) { + @MainActor public func downloadObjects(_ objects: NSSet) { for oneObject in objects { if !representedObjects.contains(oneObject) { representedObjects.add(oneObject) @@ -175,7 +175,7 @@ extension DownloadSession: URLSessionDataDelegate { private extension DownloadSession { - func addDataTask(_ representedObject: AnyObject) { + @MainActor func addDataTask(_ representedObject: AnyObject) { guard tasksPending.count < 500 else { queue.insert(representedObject, at: 0) return @@ -213,7 +213,7 @@ private extension DownloadSession { return taskIdentifierToInfoDictionary[task.taskIdentifier] } - func removeTask(_ task: URLSessionTask) { + @MainActor func removeTask(_ task: URLSessionTask) { tasksInProgress.remove(task) tasksPending.remove(task) taskIdentifierToInfoDictionary[task.taskIdentifier] = nil