Added a "userInfo" property to relevant types to allow external code to store custom data

This commit is contained in:
John Estropia
2017-04-20 16:40:27 +09:00
parent fd14a18248
commit a543a4c94a
6 changed files with 160 additions and 114 deletions

View File

@@ -434,6 +434,10 @@
B5A991ED1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */; };
B5A991EE1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */; };
B5A991EF1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */; };
B5A9921F1EA898710091A2E3 /* UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A9921E1EA898710091A2E3 /* UserInfo.swift */; };
B5A992201EA898720091A2E3 /* UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A9921E1EA898710091A2E3 /* UserInfo.swift */; };
B5A992211EA898720091A2E3 /* UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A9921E1EA898710091A2E3 /* UserInfo.swift */; };
B5A992221EA898720091A2E3 /* UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A9921E1EA898710091A2E3 /* UserInfo.swift */; };
B5AEFAB51C9962AE00AD137F /* CoreStoreBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */; };
B5AEFAB61C9962AE00AD137F /* CoreStoreBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */; };
B5AEFAB71C9962AE00AD137F /* CoreStoreBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */; };
@@ -757,6 +761,7 @@
B5A261201B64BFDB006EB6D3 /* MigrationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationType.swift; sourceTree = "<group>"; };
B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSelect.swift; sourceTree = "<group>"; };
B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionLock.swift; sourceTree = "<group>"; };
B5A9921E1EA898710091A2E3 /* UserInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserInfo.swift; sourceTree = "<group>"; };
B5AD60CD1C90141E00F2B2E8 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = SOURCE_ROOT; };
B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreBridge.swift; sourceTree = "<group>"; };
B5BDC91A1C202269008147CD /* Cartfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Cartfile; path = ../Cartfile; sourceTree = "<group>"; };
@@ -1323,6 +1328,7 @@
B512607E1E97A18000402229 /* CoreStoreObject+Convenience.swift */,
B5FAD6A81B50A4B300714891 /* Progress+Convenience.swift */,
B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */,
B5A9921E1EA898710091A2E3 /* UserInfo.swift */,
);
path = Convenience;
sourceTree = "<group>";
@@ -1692,6 +1698,7 @@
B52FD3AA1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74411E9B8724005F3DAC /* LegacyXcodeDataModel.swift in Sources */,
B51FE5AB1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
B5A9921F1EA898710091A2E3 /* UserInfo.swift in Sources */,
B54A6A551BA15F2A007870FD /* FetchedResultsControllerDelegate.swift in Sources */,
B5D339E21E948C3600C880DE /* Value.swift in Sources */,
B5A261211B64BFDB006EB6D3 /* MigrationType.swift in Sources */,
@@ -1864,6 +1871,7 @@
B52FD3AB1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74421E9B8724005F3DAC /* LegacyXcodeDataModel.swift in Sources */,
B51FE5AD1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
B5A992201EA898720091A2E3 /* UserInfo.swift in Sources */,
B5FE4DAD1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */,
B5D339E31E948C3600C880DE /* Value.swift in Sources */,
82BA18C51C4BBD5300A0916E /* ListObserver.swift in Sources */,
@@ -2036,6 +2044,7 @@
B52FD3AD1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74441E9B8724005F3DAC /* LegacyXcodeDataModel.swift in Sources */,
B5ECDC2D1CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */,
B5A992221EA898720091A2E3 /* UserInfo.swift in Sources */,
B5D7A5BA1CA3BF8F005C752B /* CSInto.swift in Sources */,
B5D339E51E948C3600C880DE /* Value.swift in Sources */,
B5A5F26A1CAEC50F004AB9AF /* CSSelect.swift in Sources */,
@@ -2208,6 +2217,7 @@
B52FD3AC1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */,
B52F74431E9B8724005F3DAC /* LegacyXcodeDataModel.swift in Sources */,
B51FE5AE1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */,
B5A992211EA898720091A2E3 /* UserInfo.swift in Sources */,
B563218C1BD65216006C9394 /* DataStack+Transaction.swift in Sources */,
B5D339E41E948C3600C880DE /* Value.swift in Sources */,
B53FBA0E1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift in Sources */,

View File

@@ -0,0 +1,115 @@
//
// UserInfo.swift
// CoreStore
//
// Copyright © 2017 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import Foundation
// MARK: UserInfo
/**
The `UserInfo` class is provided by several CoreStore types such as `DataStack`, `ListMonitor`, `ObjectMonitor` and transactions to allow external libraries or user apps to store their own custom data.
```
enum Static {
static var myDataKey: Void?
}
CoreStore.defaultStack.userInfo[&Static.myDataKey] = myObject
```
- Important: Do not use this class to store thread-sensitive data.
*/
public final class UserInfo {
/**
Allows external libraries to store custom data. App code should rarely have a need for this.
```
enum Static {
static var myDataKey: Void?
}
CoreStore.defaultStack.userInfo[&Static.myDataKey] = myObject
```
- Important: Do not use this method to store thread-sensitive data.
- parameter key: the key for custom data. Make sure this is a static pointer that will never be changed.
*/
public subscript(key: UnsafeRawPointer) -> Any? {
get {
self.lock.lock()
defer {
self.lock.unlock()
}
return self.data[key]
}
set {
self.lock.lock()
defer {
self.lock.unlock()
}
self.data[key] = newValue
}
}
/**
Allows external libraries to store custom data in the `DataStack`. App code should rarely have a need for this.
```
enum Static {
static var myDataKey: Void?
}
CoreStore.defaultStack.userInfo[&Static.myDataKey, lazyInit: { MyObject() }] = myObject
```
- Important: Do not use this method to store thread-sensitive data.
- parameter key: the key for custom data. Make sure this is a static pointer that will never be changed.
- parameter lazyInit: a closure to use to lazily-initialize the data
- returns: A custom data identified by `key`
*/
public subscript(key: UnsafeRawPointer, lazyInit closure: () -> Any) -> Any {
self.lock.lock()
defer {
self.lock.unlock()
}
if let value = self.data[key] {
return value
}
let value = closure()
self.data[key] = value
return value
}
// MARK: Internal
internal init() {}
// MARK: Private
private var data: [UnsafeRawPointer: Any] = [:]
private let lock = NSRecursiveLock()
}

View File

@@ -578,6 +578,21 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
}
// MARK: Public (3rd Party Utilities)
/**
Allow external libraries to store custom data in the `ListMonitor`. App code should rarely have a need for this.
```
enum Static {
static var myDataKey: Void?
}
monitor.userInfo[&Static.myDataKey] = myObject
```
- Important: Do not use this method to store thread-sensitive data.
*/
private let userInfo = UserInfo()
// MARK: Equatable
public static func == (lhs: ListMonitor<ObjectType>, rhs: ListMonitor<ObjectType>) -> Bool {

View File

@@ -110,6 +110,21 @@ public final class ObjectMonitor<D: DynamicObject>: Equatable {
}
// MARK: Public (3rd Party Utilities)
/**
Allow external libraries to store custom data in the `ObjectMonitor`. App code should rarely have a need for this.
```
enum Static {
static var myDataKey: Void?
}
monitor.userInfo[&Static.myDataKey] = myObject
```
- Important: Do not use this method to store thread-sensitive data.
*/
private let userInfo = UserInfo()
// MARK: Equatable
public static func == (lhs: ObjectMonitor<ObjectType>, rhs: ObjectMonitor<ObjectType>) -> Bool {

View File

@@ -450,61 +450,11 @@ public final class DataStack: Equatable {
enum Static {
static var myDataKey: Void?
}
CoreStore.defaultStack[userInfoKey: &Static.myDataKey] = myObject
CoreStore.defaultStack.userInfo[&Static.myDataKey] = myObject
```
- Important: Do not use this method to store thread-sensitive data.
- parameter userInfoKey: the key for custom data. Make sure this is a static pointer that will never be changed.
*/
public subscript(userInfoKey key: UnsafeRawPointer) -> Any? {
get {
self.userInfoLock.lock()
defer {
self.userInfoLock.unlock()
}
return self.userInfo[key]
}
set {
self.userInfoLock.lock()
defer {
self.userInfoLock.unlock()
}
self.userInfo[key] = newValue
}
}
/**
Allow external libraries to store custom data in the `DataStack`. App code should rarely have a need for this.
```
enum Static {
static var myDataKey: Void?
}
CoreStore.defaultStack[userInfoKey: &Static.myDataKey, lazyInit: { MyObject() }] = myObject
```
- Important: Do not use this method to store thread-sensitive data.
- parameter userInfoKey: the key for custom data. Make sure this is a static pointer that will never be changed.
- parameter lazyInit: a closure to use to lazily-initialize the data
- returns: A custom data identified by `userInfoKey`
*/
public subscript(userInfoKey key: UnsafeRawPointer, lazyInit closure: () -> Any) -> Any {
self.userInfoLock.lock()
defer {
self.userInfoLock.unlock()
}
if let value = self.userInfo[key] {
return value
}
let value = closure()
self.userInfo[key] = value
return value
}
private let userInfo = UserInfo()
// MARK: Equatable
@@ -636,8 +586,6 @@ public final class DataStack: Equatable {
private var persistentStoresByFinalConfiguration = [String: NSPersistentStore]()
private var finalConfigurationsByEntityIdentifier = [EntityIdentifier: Set<String>]()
private var userInfo: [UnsafeRawPointer: Any] = [:]
private let userInfoLock = NSRecursiveLock()
deinit {

View File

@@ -444,64 +444,13 @@ public /*abstract*/ class BaseDataTransaction {
Allow external libraries to store custom data in the transaction. App code should rarely have a need for this.
```
enum Static {
static var myDataKey: Void?
static var myDataKey: Void?
}
transaction[userInfoKey: &Static.myDataKey] = myObject
transaction.userInfo[&Static.myDataKey] = myObject
```
- Important: Do not use this method to store thread-sensitive data.
- parameter userInfoKey: the key for custom data. Make sure this is a static pointer that will never be changed.
- returns: A custom data identified by `userInfoKey`
*/
public subscript(userInfoKey key: UnsafeRawPointer) -> Any? {
get {
self.userInfoLock.lock()
defer {
self.userInfoLock.unlock()
}
return self.userInfo[key]
}
set {
self.userInfoLock.lock()
defer {
self.userInfoLock.unlock()
}
self.userInfo[key] = newValue
}
}
/**
Allow external libraries to store custom data in the transaction. App code should rarely have a need for this.
```
enum Static {
static var myDataKey: Void?
}
CoreStore.defaultStack[userInfoKey: &Static.myDataKey, lazyInit: { MyObject() }] = myObject
```
- Important: Do not use this method to store thread-sensitive data.
- parameter userInfoKey: the key for custom data. Make sure this is a static pointer that will never be changed.
- parameter lazyInit: a closure to use to lazily-initialize the data
- returns: A custom data identified by `userInfoKey`
*/
public subscript(userInfoKey key: UnsafeRawPointer, lazyInit closure: () -> Any) -> Any {
self.userInfoLock.lock()
defer {
self.userInfoLock.unlock()
}
if let value = self.userInfo[key] {
return value
}
let value = closure()
self.userInfo[key] = value
return value
}
private let userInfo = UserInfo()
// MARK: Internal
@@ -542,10 +491,4 @@ public /*abstract*/ class BaseDataTransaction {
return self.bypassesQueueing || self.transactionQueue.cs_isCurrentExecutionContext()
}
// MARK: Private
private var userInfo: [UnsafeRawPointer: Any] = [:]
private let userInfoLock = NSRecursiveLock()
}