mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-11-13 12:23:32 +01:00
cleanup
This commit is contained in:
1 parent
838637f29f
commit
10ac228867
8 files changed
+84
-40
No files matched your search
@@ -33,7 +33,42 @@ import CoreStore
|
|||||||
// MARK: - ConvenienceTests
|
// MARK: - ConvenienceTests
|
||||||
|
|
||||||
class ConvenienceTests: BaseTestCase {
|
class ConvenienceTests: BaseTestCase {
|
||||||
|
|
||||||
|
@objc
|
||||||
|
dynamic func test_ThatUserInfoLazyInitializer_CanReadAnotherKey() {
|
||||||
|
|
||||||
|
let keys = UnsafeMutableRawPointer.allocate(byteCount: 2, alignment: 1)
|
||||||
|
defer { keys.deallocate() }
|
||||||
|
|
||||||
|
let userInfo = UserInfo()
|
||||||
|
let value = userInfo[UnsafeRawPointer(keys), lazyInit: {
|
||||||
|
|
||||||
|
let nested = userInfo[
|
||||||
|
UnsafeRawPointer(keys.advanced(by: 1)),
|
||||||
|
lazyInit: { "nested" }
|
||||||
|
] as! String
|
||||||
|
return "outer \(nested)"
|
||||||
|
}]
|
||||||
|
XCTAssertEqual(value as? String, "outer nested")
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_ThatUndoManagerIsReadyWhenUnsafeTransactionStartsOffMain() async {
|
||||||
|
|
||||||
|
let hasUndoManager = await Task.detached {
|
||||||
|
|
||||||
|
let parent = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
|
||||||
|
let transaction = UnsafeDataTransaction(
|
||||||
|
mainContext: parent,
|
||||||
|
queue: DispatchQueue(label: "com.corestore.tests.unsafeTransactionQueue"),
|
||||||
|
supportsUndo: true,
|
||||||
|
sourceIdentifier: nil
|
||||||
|
)
|
||||||
|
let context = transaction.context
|
||||||
|
return context.performAndWait { context.undoManager != nil }
|
||||||
|
}.value
|
||||||
|
XCTAssertTrue(hasUndoManager)
|
||||||
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
@MainActor
|
@MainActor
|
||||||
dynamic func test_ThatDataStacks_CanCreateFetchedResultsControllers() {
|
dynamic func test_ThatDataStacks_CanCreateFetchedResultsControllers() {
|
||||||
|
|||||||
@@ -52,21 +52,22 @@ extension Classic.ColorsDemo {
|
|||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItemGroup(placement: .topBarLeading) {
|
ToolbarItemGroup(placement: .topBarLeading) {
|
||||||
EditButton()
|
EditButton()
|
||||||
Button("Clear") {
|
.labelStyle(.iconOnly)
|
||||||
|
Button("Clear", systemImage: "trash") {
|
||||||
|
|
||||||
self.clearColors()
|
self.clearColors()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ToolbarItemGroup(placement: .topBarTrailing) {
|
ToolbarItemGroup(placement: .topBarTrailing) {
|
||||||
Button(self.filter.rawValue) {
|
Button(self.filter.rawValue, systemImage: "line.3.horizontal.decrease.circle") {
|
||||||
|
|
||||||
self.changeFilter()
|
self.changeFilter()
|
||||||
}
|
}
|
||||||
Button("Shuffle") {
|
Button("Shuffle", systemImage: "shuffle") {
|
||||||
|
|
||||||
self.shuffleColors()
|
self.shuffleColors()
|
||||||
}
|
}
|
||||||
Button("Add") {
|
Button("Add", systemImage: "plus") {
|
||||||
|
|
||||||
self.addColor()
|
self.addColor()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ extension Modern.ColorsDemo {
|
|||||||
|
|
||||||
ToolbarItemGroup(placement: .topBarLeading) {
|
ToolbarItemGroup(placement: .topBarLeading) {
|
||||||
EditButton()
|
EditButton()
|
||||||
Button("Clear") {
|
.labelStyle(.iconOnly)
|
||||||
|
Button("Clear", systemImage: "trash") {
|
||||||
|
|
||||||
self.clearColors()
|
self.clearColors()
|
||||||
}
|
}
|
||||||
@@ -63,15 +64,15 @@ extension Modern.ColorsDemo {
|
|||||||
|
|
||||||
ToolbarItemGroup(placement: .topBarTrailing) {
|
ToolbarItemGroup(placement: .topBarTrailing) {
|
||||||
|
|
||||||
Button(self.filter.rawValue) {
|
Button(self.filter.rawValue, systemImage: "line.3.horizontal.decrease.circle") {
|
||||||
|
|
||||||
self.changeFilter()
|
self.changeFilter()
|
||||||
}
|
}
|
||||||
Button("Shuffle") {
|
Button("Shuffle", systemImage: "shuffle") {
|
||||||
|
|
||||||
self.shuffleColors()
|
self.shuffleColors()
|
||||||
}
|
}
|
||||||
Button("Add") {
|
Button("Add", systemImage: "plus") {
|
||||||
|
|
||||||
self.addColor()
|
self.addColor()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,7 +109,12 @@ extension Modern.PlacemarksDemo {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
let geocoded = await self.geocoder.geocode(place: place)
|
let geocoded = await self.geocoder.geocode(place: place)
|
||||||
guard self.place?.persistentID() == place.persistentID() else {
|
guard
|
||||||
|
!Task.isCancelled,
|
||||||
|
self.place?.persistentID() == place.persistentID(),
|
||||||
|
self.place?.$latitude == place.$latitude,
|
||||||
|
self.place?.$longitude == place.$longitude
|
||||||
|
else {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -126,7 +131,7 @@ extension Modern.PlacemarksDemo {
|
|||||||
.navigationTitle("Placemarks")
|
.navigationTitle("Placemarks")
|
||||||
.toolbar {
|
.toolbar {
|
||||||
|
|
||||||
Button("Random") {
|
Button("Random", systemImage: "dice") {
|
||||||
|
|
||||||
self.demoSynchronousTransaction()
|
self.demoSynchronousTransaction()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ extension Modern.PokedexDemo {
|
|||||||
if let species = details.$species?.snapshot {
|
if let species = details.$species?.snapshot {
|
||||||
|
|
||||||
self.fetchFormsIfNeeded(
|
self.fetchFormsIfNeeded(
|
||||||
key: String(species.$id),
|
key: pokedexEntry.$id,
|
||||||
detailsPersistentID: details.persistentID(),
|
detailsPersistentID: details.persistentID(),
|
||||||
species: species
|
species: species
|
||||||
)
|
)
|
||||||
@@ -219,7 +219,6 @@ extension Modern.PokedexDemo {
|
|||||||
self.detailTasks.removeValue(forKey: key)
|
self.detailTasks.removeValue(forKey: key)
|
||||||
}
|
}
|
||||||
await self.fetchSpecies(
|
await self.fetchSpecies(
|
||||||
key: key,
|
|
||||||
detailsPersistentID: detailsPersistentID,
|
detailsPersistentID: detailsPersistentID,
|
||||||
speciesURL: speciesURL
|
speciesURL: speciesURL
|
||||||
)
|
)
|
||||||
@@ -288,7 +287,6 @@ extension Modern.PokedexDemo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func fetchSpecies(
|
private func fetchSpecies(
|
||||||
key: String,
|
|
||||||
detailsPersistentID: PersistentID<Modern.PokedexDemo.Details>,
|
detailsPersistentID: PersistentID<Modern.PokedexDemo.Details>,
|
||||||
speciesURL: URL
|
speciesURL: URL
|
||||||
) async {
|
) async {
|
||||||
|
|||||||
@@ -554,11 +554,18 @@ public /*abstract*/ class BaseDataTransaction {
|
|||||||
context.undoManager = nil
|
context.undoManager = nil
|
||||||
}
|
}
|
||||||
else if context.undoManager == nil {
|
else if context.undoManager == nil {
|
||||||
|
let undoManager: UndoManager
|
||||||
Internals.mainActorImmediate {
|
if Thread.isMainThread {
|
||||||
|
|
||||||
context.undoManager = UndoManager()
|
undoManager = MainActor.assumeIsolated { UndoManager() }
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
undoManager = DispatchQueue.main.sync {
|
||||||
|
MainActor.assumeIsolated { UndoManager() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.undoManager = undoManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ extension ListSnapshot {
|
|||||||
|
|
||||||
public let sectionID: SectionID
|
public let sectionID: SectionID
|
||||||
|
|
||||||
public let itemIDs: [NSManagedObjectID]
|
public let itemIDs: [ItemID]
|
||||||
|
|
||||||
|
|
||||||
// MARK: RandomAccessCollection
|
// MARK: RandomAccessCollection
|
||||||
@@ -79,7 +79,7 @@ extension ListSnapshot {
|
|||||||
public subscript(position: Int) -> ObjectPublisher<O> {
|
public subscript(position: Int) -> ObjectPublisher<O> {
|
||||||
|
|
||||||
let itemID = self.itemIDs[position]
|
let itemID = self.itemIDs[position]
|
||||||
return self.context.objectPublisher(managedObjectID: itemID)
|
return self.context.objectPublisher(managedObjectID: itemID.managedObjectID)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func index(_ i: Index, offsetBy distance: Int) -> Index {
|
public func index(_ i: Index, offsetBy distance: Int) -> Index {
|
||||||
@@ -100,7 +100,7 @@ extension ListSnapshot {
|
|||||||
public subscript(bounds: Range<Index>) -> ArraySlice<Element> {
|
public subscript(bounds: Range<Index>) -> ArraySlice<Element> {
|
||||||
|
|
||||||
let itemIDs = self.itemIDs[bounds]
|
let itemIDs = self.itemIDs[bounds]
|
||||||
return ArraySlice(itemIDs.map(self.context.objectPublisher(managedObjectID:)))
|
return ArraySlice(itemIDs.map({ self.context.objectPublisher(managedObjectID: $0.managedObjectID) }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -126,7 +126,6 @@ extension ListSnapshot {
|
|||||||
}
|
}
|
||||||
self.sectionID = sectionID
|
self.sectionID = sectionID
|
||||||
self.itemIDs = listSnapshot.itemIDs(inSectionWithID: sectionID)
|
self.itemIDs = listSnapshot.itemIDs(inSectionWithID: sectionID)
|
||||||
.map({ $0.managedObjectID })
|
|
||||||
self.context = context
|
self.context = context
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-18
@@ -38,7 +38,7 @@ import Foundation
|
|||||||
```
|
```
|
||||||
- Important: Do not use this class to store thread-sensitive data.
|
- Important: Do not use this class to store thread-sensitive data.
|
||||||
*/
|
*/
|
||||||
public final class UserInfo: Sendable {
|
public final class UserInfo: @unchecked Sendable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Allows external libraries to store custom data. App code should rarely have a need for this.
|
Allows external libraries to store custom data. App code should rarely have a need for this.
|
||||||
@@ -55,17 +55,15 @@ public final class UserInfo: Sendable {
|
|||||||
|
|
||||||
get {
|
get {
|
||||||
|
|
||||||
return self.data.withLock { (info: inout _) in
|
self.lock.lock()
|
||||||
|
defer { self.lock.unlock() }
|
||||||
return info[key]
|
return self.data[key]
|
||||||
}
|
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
|
|
||||||
return self.data.withLock { (info: inout _) in
|
self.lock.lock()
|
||||||
|
defer { self.lock.unlock() }
|
||||||
info[key] = newValue
|
self.data[key] = newValue
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,16 +82,15 @@ public final class UserInfo: Sendable {
|
|||||||
*/
|
*/
|
||||||
public subscript(key: UnsafeRawPointer, lazyInit closure: () -> any Sendable) -> any Sendable {
|
public subscript(key: UnsafeRawPointer, lazyInit closure: () -> any Sendable) -> any Sendable {
|
||||||
|
|
||||||
return self.data.withLock { (info: inout _) in
|
self.lock.lock()
|
||||||
|
defer { self.lock.unlock() }
|
||||||
if let value = info[key] {
|
if let value = self.data[key] {
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
let value = closure()
|
|
||||||
info[key] = value
|
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
let value = closure()
|
||||||
|
self.data[key] = value
|
||||||
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -104,5 +101,6 @@ public final class UserInfo: Sendable {
|
|||||||
|
|
||||||
// MARK: Private
|
// MARK: Private
|
||||||
|
|
||||||
private let data: Internals.Mutex<[UnsafeRawPointer: any Sendable]> = .init([:])
|
private var data: [UnsafeRawPointer: any Sendable] = [:]
|
||||||
|
private let lock = NSRecursiveLock()
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user