mirror of
https://github.com/Ranchero-Software/NetNewsWire.git
synced 2025-01-11 09:14:06 +01:00
Fix some concurrency warnings.
This commit is contained in:
parent
12ddbd578d
commit
bdd9075b99
@ -121,7 +121,7 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func retryIfPossible(after: Double, block: @escaping () -> ()) {
|
func retryIfPossible(after: Double, block: @escaping @Sendable () -> ()) {
|
||||||
let delayTime = DispatchTime.now() + after
|
let delayTime = DispatchTime.now() + after
|
||||||
DispatchQueue.main.asyncAfter(deadline: delayTime, execute: {
|
DispatchQueue.main.asyncAfter(deadline: delayTime, execute: {
|
||||||
block()
|
block()
|
||||||
@ -139,7 +139,7 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainActor func receiveRemoteNotification(userInfo: [AnyHashable : Any], completion: @escaping () -> Void) {
|
@MainActor func receiveRemoteNotification(userInfo: [AnyHashable : Any], completion: @escaping @Sendable () -> Void) {
|
||||||
let note = CKRecordZoneNotification(fromRemoteNotificationDictionary: userInfo)
|
let note = CKRecordZoneNotification(fromRemoteNotificationDictionary: userInfo)
|
||||||
guard note?.recordZoneID?.zoneName == zoneID.zoneName else {
|
guard note?.recordZoneID?.zoneName == zoneID.zoneName else {
|
||||||
completion()
|
completion()
|
||||||
@ -170,7 +170,7 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the zone record for this zone only. If the record isn't found it will be created.
|
/// Retrieves the zone record for this zone only. If the record isn't found it will be created.
|
||||||
func fetchZoneRecord(completion: @escaping (Result<CKRecordZone?, Error>) -> Void) {
|
func fetchZoneRecord(completion: @escaping @Sendable (Result<CKRecordZone?, Error>) -> Void) {
|
||||||
|
|
||||||
let op = CKFetchRecordZonesOperation(recordZoneIDs: [zoneID])
|
let op = CKFetchRecordZonesOperation(recordZoneIDs: [zoneID])
|
||||||
op.qualityOfService = Self.qualityOfService
|
op.qualityOfService = Self.qualityOfService
|
||||||
@ -247,7 +247,7 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates the zone record
|
/// Creates the zone record
|
||||||
func createZoneRecord(completion: @escaping (Result<Void, Error>) -> Void) {
|
func createZoneRecord(completion: @escaping @Sendable (Result<Void, Error>) -> Void) {
|
||||||
guard let database = database else {
|
guard let database = database else {
|
||||||
completion(.failure(CloudKitZoneError.unknown))
|
completion(.failure(CloudKitZoneError.unknown))
|
||||||
return
|
return
|
||||||
@ -285,19 +285,21 @@ public extension CloudKitZone {
|
|||||||
func query(_ ckQuery: CKQuery, desiredKeys: [String]? = nil) async throws -> [CKRecord] {
|
func query(_ ckQuery: CKQuery, desiredKeys: [String]? = nil) async throws -> [CKRecord] {
|
||||||
|
|
||||||
try await withCheckedThrowingContinuation { continuation in
|
try await withCheckedThrowingContinuation { continuation in
|
||||||
self.query(ckQuery, desiredKeys: desiredKeys) { result in
|
Task { @MainActor in
|
||||||
switch result {
|
self.query(ckQuery, desiredKeys: desiredKeys) { result in
|
||||||
case .success(let records):
|
switch result {
|
||||||
continuation.resume(returning: records)
|
case .success(let records):
|
||||||
case .failure(let error):
|
continuation.resume(returning: records)
|
||||||
continuation.resume(throwing: error)
|
case .failure(let error):
|
||||||
|
continuation.resume(throwing: error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Issue a CKQuery and return the resulting CKRecords.
|
/// Issue a CKQuery and return the resulting CKRecords.
|
||||||
func query(_ ckQuery: CKQuery, desiredKeys: [String]? = nil, completion: @escaping (Result<[CKRecord], Error>) -> Void) {
|
@MainActor func query(_ ckQuery: CKQuery, desiredKeys: [String]? = nil, completion: @escaping @Sendable (Result<[CKRecord], Error>) -> Void) {
|
||||||
var records = [CKRecord]()
|
var records = [CKRecord]()
|
||||||
|
|
||||||
let op = CKQueryOperation(query: ckQuery)
|
let op = CKQueryOperation(query: ckQuery)
|
||||||
@ -327,7 +329,9 @@ public extension CloudKitZone {
|
|||||||
|
|
||||||
case .success(let cursor):
|
case .success(let cursor):
|
||||||
if let cursor {
|
if let cursor {
|
||||||
self.query(cursor: cursor, desiredKeys: desiredKeys, carriedRecords: records, completion: completion)
|
Task { @MainActor in
|
||||||
|
self.query(cursor: cursor, desiredKeys: desiredKeys, carriedRecords: records, completion: completion)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
completion(.success(records))
|
completion(.success(records))
|
||||||
}
|
}
|
||||||
@ -340,7 +344,9 @@ public extension CloudKitZone {
|
|||||||
self.createZoneRecord() { result in
|
self.createZoneRecord() { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
self.query(ckQuery, desiredKeys: desiredKeys, completion: completion)
|
Task { @MainActor in
|
||||||
|
self.query(ckQuery, desiredKeys: desiredKeys, completion: completion)
|
||||||
|
}
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
@ -351,7 +357,9 @@ public extension CloudKitZone {
|
|||||||
case .retry(let timeToWait):
|
case .retry(let timeToWait):
|
||||||
os_log(.error, log: self.log, "%@ zone query retry in %f seconds.", self.zoneID.zoneName, timeToWait)
|
os_log(.error, log: self.log, "%@ zone query retry in %f seconds.", self.zoneID.zoneName, timeToWait)
|
||||||
self.retryIfPossible(after: timeToWait) {
|
self.retryIfPossible(after: timeToWait) {
|
||||||
self.query(ckQuery, desiredKeys: desiredKeys, completion: completion)
|
Task { @MainActor in
|
||||||
|
self.query(ckQuery, desiredKeys: desiredKeys, completion: completion)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case .userDeletedZone:
|
case .userDeletedZone:
|
||||||
@ -374,19 +382,21 @@ public extension CloudKitZone {
|
|||||||
func query(cursor: CKQueryOperation.Cursor, desiredKeys: [String]? = nil, carriedRecords: [CKRecord]) async throws -> [CKRecord] {
|
func query(cursor: CKQueryOperation.Cursor, desiredKeys: [String]? = nil, carriedRecords: [CKRecord]) async throws -> [CKRecord] {
|
||||||
|
|
||||||
try await withCheckedThrowingContinuation { continuation in
|
try await withCheckedThrowingContinuation { continuation in
|
||||||
self.query(cursor: cursor, desiredKeys: desiredKeys, carriedRecords: carriedRecords) { result in
|
Task { @MainActor in
|
||||||
switch result {
|
self.query(cursor: cursor, desiredKeys: desiredKeys, carriedRecords: carriedRecords) { result in
|
||||||
case .success(let records):
|
switch result {
|
||||||
continuation.resume(returning: records)
|
case .success(let records):
|
||||||
case .failure(let error):
|
continuation.resume(returning: records)
|
||||||
continuation.resume(throwing: error)
|
case .failure(let error):
|
||||||
|
continuation.resume(throwing: error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Query CKRecords using a CKQuery Cursor
|
/// Query CKRecords using a CKQuery Cursor
|
||||||
func query(cursor: CKQueryOperation.Cursor, desiredKeys: [String]? = nil, carriedRecords: [CKRecord], completion: @escaping (Result<[CKRecord], Error>) -> Void) {
|
@MainActor func query(cursor: CKQueryOperation.Cursor, desiredKeys: [String]? = nil, carriedRecords: [CKRecord], completion: @escaping @Sendable (Result<[CKRecord], Error>) -> Void) {
|
||||||
var records = carriedRecords
|
var records = carriedRecords
|
||||||
|
|
||||||
let op = CKQueryOperation(cursor: cursor)
|
let op = CKQueryOperation(cursor: cursor)
|
||||||
@ -415,7 +425,7 @@ public extension CloudKitZone {
|
|||||||
switch result {
|
switch result {
|
||||||
|
|
||||||
case .success(let newCursor):
|
case .success(let newCursor):
|
||||||
DispatchQueue.main.async {
|
Task { @MainActor in
|
||||||
if let newCursor = newCursor {
|
if let newCursor = newCursor {
|
||||||
self.query(cursor: newCursor, desiredKeys: desiredKeys, carriedRecords: records, completion: completion)
|
self.query(cursor: newCursor, desiredKeys: desiredKeys, carriedRecords: records, completion: completion)
|
||||||
} else {
|
} else {
|
||||||
@ -430,7 +440,9 @@ public extension CloudKitZone {
|
|||||||
self.createZoneRecord() { result in
|
self.createZoneRecord() { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
self.query(cursor: cursor, desiredKeys: desiredKeys, carriedRecords: records, completion: completion)
|
Task { @MainActor in
|
||||||
|
self.query(cursor: cursor, desiredKeys: desiredKeys, carriedRecords: records, completion: completion)
|
||||||
|
}
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
@ -440,7 +452,9 @@ public extension CloudKitZone {
|
|||||||
case .retry(let timeToWait):
|
case .retry(let timeToWait):
|
||||||
os_log(.error, log: self.log, "%@ zone query retry in %f seconds.", self.zoneID.zoneName, timeToWait)
|
os_log(.error, log: self.log, "%@ zone query retry in %f seconds.", self.zoneID.zoneName, timeToWait)
|
||||||
self.retryIfPossible(after: timeToWait) {
|
self.retryIfPossible(after: timeToWait) {
|
||||||
self.query(cursor: cursor, desiredKeys: desiredKeys, carriedRecords: records, completion: completion)
|
Task { @MainActor in
|
||||||
|
self.query(cursor: cursor, desiredKeys: desiredKeys, carriedRecords: records, completion: completion)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case .userDeletedZone:
|
case .userDeletedZone:
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
@ -473,7 +487,7 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch a CKRecord by using its externalID
|
/// Fetch a CKRecord by using its externalID
|
||||||
func fetch(externalID: String?, completion: @escaping (Result<CKRecord, Error>) -> Void) {
|
func fetch(externalID: String?, completion: @escaping @Sendable (Result<CKRecord, Error>) -> Void) {
|
||||||
guard let externalID = externalID else {
|
guard let externalID = externalID else {
|
||||||
completion(.failure(CloudKitZoneError.corruptAccount))
|
completion(.failure(CloudKitZoneError.corruptAccount))
|
||||||
return
|
return
|
||||||
@ -540,7 +554,7 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Save the CKRecord
|
/// Save the CKRecord
|
||||||
func save(_ record: CKRecord, completion: @escaping (Result<Void, Error>) -> Void) {
|
func save(_ record: CKRecord, completion: @escaping @Sendable (Result<Void, Error>) -> Void) {
|
||||||
modify(recordsToSave: [record], recordIDsToDelete: [], completion: completion)
|
modify(recordsToSave: [record], recordIDsToDelete: [], completion: completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,7 +574,7 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Save the CKRecords
|
/// Save the CKRecords
|
||||||
func save(_ records: [CKRecord], completion: @escaping (Result<Void, Error>) -> Void) {
|
func save(_ records: [CKRecord], completion: @escaping @Sendable (Result<Void, Error>) -> Void) {
|
||||||
modify(recordsToSave: records, recordIDsToDelete: [], completion: completion)
|
modify(recordsToSave: records, recordIDsToDelete: [], completion: completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,8 +594,8 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Saves or modifies the records as long as they are unchanged relative to the local version
|
/// Saves or modifies the records as long as they are unchanged relative to the local version
|
||||||
func saveIfNew(_ records: [CKRecord], completion: @escaping (Result<Void, Error>) -> Void) {
|
func saveIfNew(_ records: [CKRecord], completion: @escaping @Sendable (Result<Void, Error>) -> Void) {
|
||||||
|
|
||||||
let op = CKModifyRecordsOperation(recordsToSave: records, recordIDsToDelete: [CKRecord.ID]())
|
let op = CKModifyRecordsOperation(recordsToSave: records, recordIDsToDelete: [CKRecord.ID]())
|
||||||
op.savePolicy = .ifServerRecordUnchanged
|
op.savePolicy = .ifServerRecordUnchanged
|
||||||
op.isAtomic = false
|
op.isAtomic = false
|
||||||
@ -678,7 +692,7 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Save the CKSubscription
|
/// Save the CKSubscription
|
||||||
func save(_ subscription: CKSubscription, completion: @escaping (Result<CKSubscription, Error>) -> Void) {
|
func save(_ subscription: CKSubscription, completion: @escaping @Sendable (Result<CKSubscription, Error>) -> Void) {
|
||||||
database?.save(subscription) { [weak self] savedSubscription, error in
|
database?.save(subscription) { [weak self] savedSubscription, error in
|
||||||
|
|
||||||
guard let self else {
|
guard let self else {
|
||||||
@ -731,8 +745,8 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Delete CKRecords using a CKQuery
|
/// Delete CKRecords using a CKQuery
|
||||||
func delete(ckQuery: CKQuery, completion: @escaping (Result<Void, Error>) -> Void) {
|
func delete(ckQuery: CKQuery, completion: @escaping @Sendable (Result<Void, Error>) -> Void) {
|
||||||
|
|
||||||
var records = [CKRecord]()
|
var records = [CKRecord]()
|
||||||
|
|
||||||
let op = CKQueryOperation(query: ckQuery)
|
let op = CKQueryOperation(query: ckQuery)
|
||||||
@ -795,8 +809,8 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Delete CKRecords using a CKQuery
|
/// Delete CKRecords using a CKQuery
|
||||||
func delete(cursor: CKQueryOperation.Cursor, carriedRecords: [CKRecord], completion: @escaping (Result<Void, Error>) -> Void) {
|
func delete(cursor: CKQueryOperation.Cursor, carriedRecords: [CKRecord], completion: @escaping @Sendable (Result<Void, Error>) -> Void) {
|
||||||
|
|
||||||
var records = [CKRecord]()
|
var records = [CKRecord]()
|
||||||
|
|
||||||
let op = CKQueryOperation(cursor: cursor)
|
let op = CKQueryOperation(cursor: cursor)
|
||||||
@ -855,7 +869,7 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Delete a CKRecord using its recordID
|
/// Delete a CKRecord using its recordID
|
||||||
func delete(recordID: CKRecord.ID, completion: @escaping (Result<Void, Error>) -> Void) {
|
func delete(recordID: CKRecord.ID, completion: @escaping @Sendable (Result<Void, Error>) -> Void) {
|
||||||
modify(recordsToSave: [], recordIDsToDelete: [recordID], completion: completion)
|
modify(recordsToSave: [], recordIDsToDelete: [recordID], completion: completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -875,7 +889,7 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Delete CKRecords
|
/// Delete CKRecords
|
||||||
func delete(recordIDs: [CKRecord.ID], completion: @escaping (Result<Void, Error>) -> Void) {
|
func delete(recordIDs: [CKRecord.ID], completion: @escaping @Sendable (Result<Void, Error>) -> Void) {
|
||||||
modify(recordsToSave: [], recordIDsToDelete: recordIDs, completion: completion)
|
modify(recordsToSave: [], recordIDsToDelete: recordIDs, completion: completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -895,7 +909,7 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Delete a CKRecord using its externalID
|
/// Delete a CKRecord using its externalID
|
||||||
func delete(externalID: String?, completion: @escaping (Result<Void, Error>) -> Void) {
|
func delete(externalID: String?, completion: @escaping @Sendable (Result<Void, Error>) -> Void) {
|
||||||
guard let externalID = externalID else {
|
guard let externalID = externalID else {
|
||||||
completion(.failure(CloudKitZoneError.corruptAccount))
|
completion(.failure(CloudKitZoneError.corruptAccount))
|
||||||
return
|
return
|
||||||
@ -921,7 +935,7 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Delete a CKSubscription
|
/// Delete a CKSubscription
|
||||||
func delete(subscriptionID: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
func delete(subscriptionID: String, completion: @escaping @Sendable (Result<Void, Error>) -> Void) {
|
||||||
database?.delete(withSubscriptionID: subscriptionID) { [weak self] _, error in
|
database?.delete(withSubscriptionID: subscriptionID) { [weak self] _, error in
|
||||||
guard let self = self else {
|
guard let self = self else {
|
||||||
completion(.failure(CloudKitZoneError.unknown))
|
completion(.failure(CloudKitZoneError.unknown))
|
||||||
@ -962,7 +976,7 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Modify and delete the supplied CKRecords and CKRecord.IDs
|
/// Modify and delete the supplied CKRecords and CKRecord.IDs
|
||||||
func modify(recordsToSave: [CKRecord], recordIDsToDelete: [CKRecord.ID], completion: @escaping (Result<Void, Error>) -> Void) {
|
func modify(recordsToSave: [CKRecord], recordIDsToDelete: [CKRecord.ID], completion: @escaping @Sendable (Result<Void, Error>) -> Void) {
|
||||||
|
|
||||||
guard !(recordsToSave.isEmpty && recordIDsToDelete.isEmpty) else {
|
guard !(recordsToSave.isEmpty && recordIDsToDelete.isEmpty) else {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
@ -1097,7 +1111,7 @@ public extension CloudKitZone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch all the changes in the CKZone since the last time we checked
|
/// Fetch all the changes in the CKZone since the last time we checked
|
||||||
@MainActor func fetchChangesInZone(completion: @escaping (Result<Void, Error>) -> Void) {
|
@MainActor func fetchChangesInZone(completion: @escaping @Sendable (Result<Void, Error>) -> Void) {
|
||||||
|
|
||||||
var savedChangeToken = changeToken
|
var savedChangeToken = changeToken
|
||||||
|
|
||||||
@ -1159,7 +1173,9 @@ public extension CloudKitZone {
|
|||||||
self.createZoneRecord() { result in
|
self.createZoneRecord() { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
self.fetchChangesInZone(completion: completion)
|
Task { @MainActor in
|
||||||
|
self.fetchChangesInZone(completion: completion)
|
||||||
|
}
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
@ -1173,7 +1189,9 @@ public extension CloudKitZone {
|
|||||||
case .retry(let timeToWait):
|
case .retry(let timeToWait):
|
||||||
os_log(.error, log: self.log, "%@ zone fetch changes retry in %f seconds.", self.zoneID.zoneName, timeToWait)
|
os_log(.error, log: self.log, "%@ zone fetch changes retry in %f seconds.", self.zoneID.zoneName, timeToWait)
|
||||||
self.retryIfPossible(after: timeToWait) {
|
self.retryIfPossible(after: timeToWait) {
|
||||||
self.fetchChangesInZone(completion: completion)
|
Task { @MainActor in
|
||||||
|
self.fetchChangesInZone(completion: completion)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case .changeTokenExpired:
|
case .changeTokenExpired:
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
Loading…
Reference in New Issue
Block a user