diff --git a/RealmSwift/Combine.swift b/RealmSwift/Combine.swift index 5d54f284b7..a07e79e38e 100644 --- a/RealmSwift/Combine.swift +++ b/RealmSwift/Combine.swift @@ -197,7 +197,7 @@ extension Publisher { /// - returns: A publisher that publishes frozen copies of the changesets /// which the upstream publisher publishes. public func freeze() - -> Publishers.Map> where Output == RealmSectionedResultsChange { + -> Publishers.Map> where Output == SectionedResultsChange { return map { switch $0 { case .initial(let collection): @@ -446,7 +446,7 @@ extension Publisher { /// /// - returns: A publisher that supports `receive(on:)` for thread-confined objects. public func threadSafeReference() - -> RealmPublishers.MakeThreadSafeSectionedResultsChangeset where Output == RealmSectionedResultsChange { + -> RealmPublishers.MakeThreadSafeSectionedResultsChangeset where Output == SectionedResultsChange { RealmPublishers.MakeThreadSafeSectionedResultsChangeset(self) } } @@ -1824,7 +1824,7 @@ public enum RealmPublishers { } } - /// A publisher which emits RealmSectionedResultsChange each time the observed object is modified + /// A publisher which emits SectionedResultsChange each time the observed object is modified /// /// `receive(on:)` and `subscribe(on:)` can be called directly on this /// publisher, and calling `.threadSafeReference()` is only required if @@ -1833,8 +1833,8 @@ public enum RealmPublishers { /// /// Create this publisher using the `changesetPublisher` property on RealmSectionedResult. @frozen public struct SectionedResultsChangeset: Publisher { - public typealias Output = RealmSectionedResultsChange - /// This publisher reports error via the `.error` case of RealmSectionedResultsChange. + public typealias Output = SectionedResultsChange + /// This publisher reports error via the `.error` case of SectionedResultsChange. public typealias Failure = Never private let collection: Collection @@ -1907,7 +1907,7 @@ public enum RealmPublishers { } } - /// A publisher which emits RealmSectionedResultsChange each time the observed object is modified + /// A publisher which emits SectionedResultsChange each time the observed object is modified /// /// `receive(on:)` and `subscribe(on:)` can be called directly on this /// publisher, and calling `.threadSafeReference()` is only required if @@ -1916,8 +1916,8 @@ public enum RealmPublishers { /// /// Create this publisher using the `changesetPublisher` property on RealmSectionedResult. @frozen public struct SectionChangeset: Publisher { - public typealias Output = RealmSectionedResultsChange - /// This publisher reports error via the `.error` case of RealmSectionedResultsChange. + public typealias Output = SectionedResultsChange + /// This publisher reports error via the `.error` case of SectionedResultsChange. public typealias Failure = Never private let collection: Collection @@ -2070,7 +2070,7 @@ public enum RealmPublishers { } } - /// A publisher which emits RealmSectionedResultsChange each time the observed object is modified + /// A publisher which emits SectionedResultsChange each time the observed object is modified /// /// `receive(on:)` and `subscribe(on:)` can be called directly on this /// publisher, and calling `.threadSafeReference()` is only required if @@ -2079,7 +2079,7 @@ public enum RealmPublishers { /// /// Create this publisher using the `changesetPublisher` property on RealmSectionedResult. public class SectionedResultsChangesetWithToken: Publisher { - public typealias Output = RealmSectionedResultsChange + public typealias Output = SectionedResultsChange /// This publisher reports error via the `.error` case of RealmCollectionChange. public typealias Failure = Never @@ -2149,7 +2149,7 @@ public enum RealmPublishers { } } - /// A publisher which emits RealmSectionedResultsChange each time the observed object is modified + /// A publisher which emits SectionedResultsChange each time the observed object is modified /// /// `receive(on:)` and `subscribe(on:)` can be called directly on this /// publisher, and calling `.threadSafeReference()` is only required if @@ -2158,7 +2158,7 @@ public enum RealmPublishers { /// /// Create this publisher using the `changesetPublisher` property on RealmSectionedResult. public class SectionChangesetWithToken: Publisher { - public typealias Output = RealmSectionedResultsChange + public typealias Output = SectionedResultsChange /// This publisher reports error via the `.error` case of RealmCollectionChange. public typealias Failure = Never @@ -2370,8 +2370,8 @@ public enum RealmPublishers { } /// A helper publisher created by calling `.threadSafeReference()` on a - /// publisher which emits `RealmSectionedResultsChange`. - @frozen public struct MakeThreadSafeSectionedResultsChangeset: Publisher where Upstream.Output == RealmSectionedResultsChange { + /// publisher which emits `SectionedResultsChange`. + @frozen public struct MakeThreadSafeSectionedResultsChangeset: Publisher where Upstream.Output == SectionedResultsChange { /// :nodoc: public typealias Failure = Upstream.Failure /// :nodoc: @@ -2552,7 +2552,7 @@ public enum RealmPublishers { private enum SectionedHandover { // A collection change which does not contain a live object and so // can be delivered directly - case passthrough(_ change: RealmSectionedResultsChange) + case passthrough(_ change: SectionedResultsChange) // The initial and update notifications for live collections need // to wrap the collection in a thread-safe reference and hold onto // a pinned Realm to ensure that the version which the change @@ -2562,7 +2562,7 @@ public enum RealmPublishers { deletions: [IndexPath], insertions: [IndexPath], modifications: [IndexPath], sectionsToInsert: IndexSet, sectionsToDelete: IndexSet) - init(_ change: RealmSectionedResultsChange) { + init(_ change: SectionedResultsChange) { switch change { case .initial(let collection): guard let realm = collection.realm, !realm.isFrozen else { @@ -2585,7 +2585,7 @@ public enum RealmPublishers { } } - func resolve(_ scheduler: S) -> RealmSectionedResultsChange? { + func resolve(_ scheduler: S) -> SectionedResultsChange? { switch self { case .passthrough(let change): return change @@ -2613,7 +2613,7 @@ public enum RealmPublishers { /// /// Create using `.threadSafeReference().receive(on: queue)` on a publisher /// that emits `RealmCollectionChange`. - @frozen public struct DeferredHandoverSectionedResultsChangeset: Publisher where Upstream.Output == RealmSectionedResultsChange { + @frozen public struct DeferredHandoverSectionedResultsChangeset: Publisher where Upstream.Output == SectionedResultsChange { /// :nodoc: public typealias Failure = Upstream.Failure /// :nodoc: @@ -2642,8 +2642,8 @@ public enum RealmPublishers { /// serial dispatch queue. /// /// Create using `.threadSafeReference().receive(on: queue)` on a publisher - /// that emits `RealmSectionedResultsChange`. - @frozen public struct DeferredHandoverSectionChangeset: Publisher where Upstream.Output == RealmSectionedResultsChange { + /// that emits `SectionedResultsChange`. + @frozen public struct DeferredHandoverSectionChangeset: Publisher where Upstream.Output == SectionedResultsChange { /// :nodoc: public typealias Failure = Upstream.Failure /// :nodoc: diff --git a/RealmSwift/Projection.swift b/RealmSwift/Projection.swift index 3cd407f5ff..7924b1d92f 100644 --- a/RealmSwift/Projection.swift +++ b/RealmSwift/Projection.swift @@ -628,8 +628,9 @@ extension NSLocking { // A property wrapper which unsafely disables concurrency checking for a property // This is required when a property is guarded by something which concurrency // checking doesn't understand (i.e. a lock instead of an actor) +@usableFromInline @propertyWrapper -public struct Unchecked: @unchecked Sendable { +internal struct Unchecked: @unchecked Sendable { public var wrappedValue: Wrapped public init(wrappedValue: Wrapped) { self.wrappedValue = wrappedValue diff --git a/RealmSwift/SectionedResults.swift b/RealmSwift/SectionedResults.swift index 53155d9015..b6e4a227b9 100644 --- a/RealmSwift/SectionedResults.swift +++ b/RealmSwift/SectionedResults.swift @@ -24,7 +24,6 @@ import Realm `SectionedResults` and `ResultSection`. */ public protocol RealmSectionedResult: RandomAccessCollection, Equatable, ThreadConfined { - associatedtype Key: _Persistable, Hashable // MARK: Properties /// The Realm which manages the collection, or `nil` if the collection is invalidated. @@ -69,17 +68,17 @@ public protocol RealmSectionedResult: RandomAccessCollection, Equatable, ThreadC /// :nodoc: func observe(keyPaths: [String]?, on queue: DispatchQueue?, - _ block: @escaping (RealmSectionedResultsChange) -> Void) -> NotificationToken + _ block: @escaping (SectionedResultsChange) -> Void) -> NotificationToken /// :nodoc: func observe(on queue: DispatchQueue?, - _ block: @escaping (RealmSectionedResultsChange) -> Void) -> NotificationToken + _ block: @escaping (SectionedResultsChange) -> Void) -> NotificationToken } extension RealmSectionedResult where Element: RLMObjectBase { /// :nodoc: func observe(keyPaths: [PartialKeyPath], on queue: DispatchQueue?, - _ block: @escaping (RealmSectionedResultsChange) -> Void) -> NotificationToken { + _ block: @escaping (SectionedResultsChange) -> Void) -> NotificationToken { fatalError("abstract") } } @@ -138,13 +137,13 @@ extension RealmSectionedResultImpl { /// :nodoc: internal typealias ObjcSectionedResultsChange = (RLMSectionedResult?, RLMSectionedResultsChange?) -> Void /// :nodoc: - internal func wrapObserveBlock(_ block: @escaping (RealmSectionedResultsChange) -> Void) -> ObjcSectionedResultsChange { + internal func wrapObserveBlock(_ block: @escaping (SectionedResultsChange) -> Void) -> ObjcSectionedResultsChange { var col: Self? return { collection, change in if col == nil, let collection = collection { col = self.collection === collection ? self : Self(rlmSectionedResult: collection as! Self.Collection) } - block(RealmSectionedResultsChange.fromObjc(value: col, change: change)) + block(SectionedResultsChange.fromObjc(value: col, change: change)) } } } @@ -195,7 +194,7 @@ public struct SectionedResults) -> Void) -> NotificationToken { + _ block: @escaping (SectionedResultsChange) -> Void) -> NotificationToken { return collection.addNotificationBlock(wrapObserveBlock(block), keyPaths: keyPaths, queue: queue) } @@ -322,7 +321,7 @@ public struct SectionedResults) -> Void) -> NotificationToken { + _ block: @escaping (SectionedResultsChange) -> Void) -> NotificationToken { return collection.addNotificationBlock(wrapObserveBlock(block), keyPaths: nil, queue: queue) } /// :nodoc: - public func makeIterator() -> RLMSectionedResultsIterator { - return RLMSectionedResultsIterator(collection: collection) + public func makeIterator() -> SectionedResultsIterator { + return SectionedResultsIterator(collection: collection) } /// :nodoc: @@ -454,7 +453,7 @@ extension SectionedResults where Element: RLMObjectBase { transaction which changes either any of the objects in the sectioned results collection, or which objects are in the sectioned results collection. The `change` parameter that is passed to the block reports, in the form of indices within the collection, which of - the objects were added, removed, or modified during each write transaction. See the `RealmSectionedResultsChange` + the objects were added, removed, or modified during each write transaction. See the `SectionedResultsChange` documentation for more information on the change information supplied and an example of how to use it to update a `UITableView`. @@ -567,7 +566,7 @@ extension SectionedResults where Element: RLMObjectBase { */ public func observe(keyPaths: [PartialKeyPath], on queue: DispatchQueue? = nil, - _ block: @escaping (RealmSectionedResultsChange) -> Void) -> NotificationToken { + _ block: @escaping (SectionedResultsChange) -> Void) -> NotificationToken { return collection.addNotificationBlock(wrapObserveBlock(block), keyPaths: keyPaths.map(_name(for:)), queue: queue) } } @@ -613,7 +612,7 @@ public struct ResultsSection) -> Void) -> NotificationToken { + _ block: @escaping (SectionedResultsChange) -> Void) -> NotificationToken { return collection.addNotificationBlock(wrapObserveBlock(block), keyPaths: keyPaths, queue: queue) } /** @@ -739,7 +738,7 @@ public struct ResultsSection) -> Void) -> NotificationToken { + _ block: @escaping (SectionedResultsChange) -> Void) -> NotificationToken { return collection.addNotificationBlock(wrapObserveBlock(block), keyPaths: nil, queue: queue) } /// :nodoc: - public func makeIterator() -> RLMSectionIterator { - return RLMSectionIterator(collection: collection) + public func makeIterator() -> SectionIterator { + return SectionIterator(collection: collection) } /// :nodoc: @@ -871,7 +870,7 @@ extension ResultsSection where T: RLMObjectBase { transaction which changes either any of the objects in the sectioned results collection, or which objects are in the sectioned results collection. The `change` parameter that is passed to the block reports, in the form of indices within the collection, which of - the objects were added, removed, or modified during each write transaction. See the `RealmSectionedResultsChange` + the objects were added, removed, or modified during each write transaction. See the `SectionedResultsChange` documentation for more information on the change information supplied and an example of how to use it to update a `UITableView`. @@ -984,7 +983,7 @@ extension ResultsSection where T: RLMObjectBase { */ public func observe(keyPaths: [PartialKeyPath], on queue: DispatchQueue? = nil, - _ block: @escaping (RealmSectionedResultsChange) -> Void) -> NotificationToken { + _ block: @escaping (SectionedResultsChange) -> Void) -> NotificationToken { return collection.addNotificationBlock(wrapObserveBlock(block), keyPaths: keyPaths.map(_name(for:)), queue: queue) } } @@ -992,7 +991,16 @@ extension ResultsSection where T: RLMObjectBase { @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) extension ResultsSection: Identifiable { } -@frozen public enum RealmSectionedResultsChange { +/** + A `SectionedResultsChange` value encapsulates information about changes to + sectioned results that are reported by Realm notifications. + + The first time a notification is delivered it will be `.initial`, and all + subsequent notifications will be `.change()` with information about what has + changed since the last time the callback was invoked. + } + */ +@frozen public enum SectionedResultsChange { /** `.initial` indicates that the initial run of the query has completed (if applicable), and the collection can now be used without performing any @@ -1017,7 +1025,7 @@ extension ResultsSection: Identifiable { } sectionsToInsert: IndexSet, sectionsToDelete: IndexSet) /// :nodoc: - static func fromObjc(value: Collection?, change: RLMSectionedResultsChange?) -> RealmSectionedResultsChange { + static func fromObjc(value: Collection?, change: RLMSectionedResultsChange?) -> SectionedResultsChange { if let change = change { return .update(value!, deletions: change.deletions as [IndexPath], @@ -1030,10 +1038,14 @@ extension ResultsSection: Identifiable { } } } +/// :nodoc: +@available(*, deprecated, renamed: "SectionedResultsChange") +public typealias RealmSectionedResultsChange = SectionedResultsChange + /** An iterator for a `SectionedResults` instance. */ -@frozen public struct RLMSectionedResultsIterator: IteratorProtocol { +@frozen public struct SectionedResultsIterator: IteratorProtocol { private var generatorBase: NSFastEnumerationIterator init(collection: RLMSectionedResults) { @@ -1047,10 +1059,14 @@ extension ResultsSection: Identifiable { } } } +/// :nodoc: +@available(*, deprecated, renamed: "SectionedResultsIterator") +public typealias RLMSectionedResultsIterator = SectionedResultsIterator + /** An iterator for a `Section` instance. */ -@frozen public struct RLMSectionIterator: IteratorProtocol { +@frozen public struct SectionIterator: IteratorProtocol { private var generatorBase: NSFastEnumerationIterator init(collection: RLMSection) { @@ -1063,3 +1079,7 @@ extension ResultsSection: Identifiable { } return next as? Element } } + +/// :nodoc: +@available(*, deprecated, renamed: "SectionIterator") +public typealias RLMSectionIterator = SectionIterator diff --git a/RealmSwift/Tests/CombineTests.swift b/RealmSwift/Tests/CombineTests.swift index fbca68800d..f3da13028c 100644 --- a/RealmSwift/Tests/CombineTests.swift +++ b/RealmSwift/Tests/CombineTests.swift @@ -2340,7 +2340,7 @@ private class CombineSectionedResultsPublisherTests } func checkChangeset( - _ change: RealmSectionedResultsChange, + _ change: SectionedResultsChange, insertions: [IndexPath] = [], deletions: [IndexPath] = [], frozen: Bool = false) { switch change { case .initial(let collection): diff --git a/RealmSwift/Tests/SectionedResultsTests.swift b/RealmSwift/Tests/SectionedResultsTests.swift index a95a97b603..e52fddb76b 100644 --- a/RealmSwift/Tests/SectionedResultsTests.swift +++ b/RealmSwift/Tests/SectionedResultsTests.swift @@ -372,7 +372,7 @@ class SectionedResultsTests: SectionedResultsTestsBase { let results = realm.objects(ModernAllTypesObject.self) let sectionedResults = results.sectioned(by: \.firstLetter, ascending: true) let ex = expectation(description: "initial notification") - let token = sectionedResults.observe { (changes: RealmSectionedResultsChange) in + let token = sectionedResults.observe { (changes: SectionedResultsChange) in switch changes { case .initial(let collection): XCTAssertEqual(collection.count, 3) @@ -486,7 +486,7 @@ class SectionedResultsTests: SectionedResultsTestsBase { let queue = DispatchQueue(label: "background") var firstRun = true let token = sectionedResults.observe(keyPaths: [\.stringCol], - on: queue) { (changes: RealmSectionedResultsChange) in + on: queue) { (changes: SectionedResultsChange) in switch changes { case .initial(let collection): XCTAssertEqual(collection.count, 3) @@ -544,7 +544,7 @@ class SectionedResultsTests: SectionedResultsTestsBase { var firstRun = true // Only get notifications for key 'a'. - let token1 = section1.observe(keyPaths: [\.stringCol]) { (changes: RealmSectionedResultsChange) in + let token1 = section1.observe(keyPaths: [\.stringCol]) { (changes: SectionedResultsChange) in switch changes { case .initial(let collection): XCTAssertEqual(collection.count, 1) @@ -565,7 +565,7 @@ class SectionedResultsTests: SectionedResultsTestsBase { } // Only get notifications for key 'b'. - let token2 = section2.observe(keyPaths: [\.stringCol]) { (changes: RealmSectionedResultsChange) in + let token2 = section2.observe(keyPaths: [\.stringCol]) { (changes: SectionedResultsChange) in switch changes { case .initial(let collection): if firstRun { @@ -626,7 +626,7 @@ class SectionedResultsTests: SectionedResultsTestsBase { var firstRun = true // Only get notifications for key 'a'. let token1 = section1.observe(keyPaths: [\.stringCol], - on: queue) { (changes: RealmSectionedResultsChange) in + on: queue) { (changes: SectionedResultsChange) in switch changes { case .initial(let collection): XCTAssertEqual(collection.count, 1) @@ -650,7 +650,7 @@ class SectionedResultsTests: SectionedResultsTestsBase { sema1.wait() // Only get notifications for key 'b'. let token2 = section2.observe(keyPaths: [\.stringCol], - on: queue) { (changes: RealmSectionedResultsChange) in + on: queue) { (changes: SectionedResultsChange) in switch changes { case .initial(let collection): if firstRun { @@ -850,7 +850,7 @@ class SectionedResultsProjectionTests: SectionedResultsTestsBase { let results = realm.objects(ModernAllTypesProjection.self) let sectionedResults = results.sectioned(by: \.firstLetter, ascending: true) let ex = expectation(description: "initial notification") - let token = sectionedResults.observe { (changes: RealmSectionedResultsChange) in + let token = sectionedResults.observe { (changes: SectionedResultsChange) in switch changes { case .initial(let collection): XCTAssertEqual(collection.count, 3) @@ -889,7 +889,7 @@ class SectionedResultsProjectionTests: SectionedResultsTestsBase { let queue = DispatchQueue(label: "background") var firstRun = true let token = sectionedResults.observe(keyPaths: ["stringCol"], - on: queue) { (changes: RealmSectionedResultsChange) in + on: queue) { (changes: SectionedResultsChange) in switch changes { case .initial(let collection): XCTAssertEqual(collection.count, 3) @@ -947,7 +947,7 @@ class SectionedResultsProjectionTests: SectionedResultsTestsBase { var firstRun = true // Only get notifications for key 'a'. - let token1 = section1.observe(keyPaths: ["stringCol"]) { (changes: RealmSectionedResultsChange) in + let token1 = section1.observe(keyPaths: ["stringCol"]) { (changes: SectionedResultsChange) in switch changes { case .initial(let collection): XCTAssertEqual(collection.count, 1) @@ -968,7 +968,7 @@ class SectionedResultsProjectionTests: SectionedResultsTestsBase { } // Only get notifications for key 'b'. - let token2 = section2.observe(keyPaths: ["stringCol"]) { (changes: RealmSectionedResultsChange) in + let token2 = section2.observe(keyPaths: ["stringCol"]) { (changes: SectionedResultsChange) in switch changes { case .initial(let collection): if firstRun { @@ -1029,7 +1029,7 @@ class SectionedResultsProjectionTests: SectionedResultsTestsBase { var firstRun = true // Only get notifications for key 'a'. let token1 = section1.observe(keyPaths: ["stringCol"], - on: queue) { (changes: RealmSectionedResultsChange) in + on: queue) { (changes: SectionedResultsChange) in switch changes { case .initial(let collection): XCTAssertEqual(collection.count, 1) @@ -1053,7 +1053,7 @@ class SectionedResultsProjectionTests: SectionedResultsTestsBase { sema1.wait() // Only get notifications for key 'b'. let token2 = section2.observe(keyPaths: ["stringCol"], - on: queue) { (changes: RealmSectionedResultsChange) in + on: queue) { (changes: SectionedResultsChange) in switch changes { case .initial(let collection): if firstRun {