jessesquires / jsqcoredatakit Goto Github PK
View Code? Open in Web Editor NEWA swifter Core Data stack
Home Page: https://jessesquires.github.io/JSQCoreDataKit/
License: MIT License
A swifter Core Data stack
Home Page: https://jessesquires.github.io/JSQCoreDataKit/
License: MIT License
Support for emptying all the managed object contexts in the stack and clearing the persistent store.
When using NSInMemoryStoreType
for the model, the storeDirectory
and storeURL
should be nil
to reflect that the store is not on disk.
These properties should be optional to reflect this.
Also, the storeType
should be a property on the model, not the stack. It makes much more sense to describe this on the model in general, but especially because of the dependencies between this property and the storeDirectory
and storeURL
properties.
related: #20
Tasks:
See MagicalRecord for ideas, but make them Swifter.
Hello @jessesquires ๐, a quick question:
Regarding forced unwrapping of NSEntityDescription.entityForName()
in CoreDataExtensions.swift
: why shouldn't the optional be passed on?
Thanks for your time ๐
Following carthage error occurred while installation. Any suggestions?:
dev$ carthage update
*** Fetching JSQDataSourcesKit
*** Fetching JSQCoreDataKit
*** Checking out JSQCoreDataKit at "2.1.0"
*** Checking out JSQDataSourcesKit at "3.0.1"
*** xcodebuild output can be found in /var/folders/sg/vc3ry_wd77x_mv_qbdf0szf80000gr/T/carthage-xcodebuild.iagUVy.log
*** Building scheme "ExampleApp" in ExampleApp.xcodeproj
** BUILD FAILED **
The following build commands failed:
Check dependencies
(1 failure)
A shell task failed with exit code 65:
** BUILD FAILED **
The following build commands failed:
Check dependencies
(1 failure)
The fetch method fails to compile because in Swift 2.0, NSManagedObjectContext.executeFetchRequest throws. I suggest something like the following:
public func fetch <T: NSManagedObject>(request request: FetchRequest<T>,
inContext context: NSManagedObjectContext) -> FetchResult<T> {
var results: [AnyObject]?
var fetchResult = FetchResult<T>(success: false, objects: [], error: nil)
context.performBlockAndWait { () -> Void in
do {
results = try context.executeFetchRequest(request)
fetchResult.success = true
fetchResult.objects = results as! [T]
} catch let error as NSError {
print("*** ERROR: [\(__LINE__)] \(__FUNCTION__) Error while executing fetch request: \(error)")
fetchResult.error = error
}
}
return fetchResult
}
CoreDataModel
init method storeType defaults to a SQLite DB using the Documents Directory URL: storeType: StoreType = .SQLite(DocumentsDirectoryURL())
On tvOS, the Document Directory is not available and it would be a nice enhancement to have the init method default to the Caches Directory.
A proposal would be to refactor DocumentsDirectoryURL()
to DirectoryURL()
and add an availability check when creating the directory URL:
var searchPathDirectory = .DocumentDirectory
#if os(tvOS)
searchPathDirectory = .CachesDirectory
#endif
return try NSFileManager.defaultManager().URLForDirectory(searchPathDirectory, ...)
This feels/reads better.
Update docs and README for changes.
I'm experiencing the following runtime error on XCode 7/iOS 9 (I'm on the release-2.0
branch):
dyld: Library not loaded: /JSQCoreDataKit.framework/JSQCoreDataKit Referenced from: /var/mobile/Containers/Bundle/Application/3803D54B-EB15-4759-8B9E-EE4D09B76855/MyApp.app/MyApp Reason: image not found
when installing JSQCoreDataKit with Carthage.
I've added the .framework to Linked Frameworks and Libraries
.
Creating a Copy Files
step with Destination = "Products Directory" (with Code Sign on Copy) makes it run on the simulator, but still fails on the phone.
Any clues?
I would like a function to reset the stack. Sometimes I remove to store (sqlite-file) and replace it with a backup and would like to reload the stack in an easy way.
After talking with Daniel Eggert, I found that nesting parent/child contexts is non-optimal.
Move from the existing stack architecture, to the following:
mainContext
as a child context of the backgroundContext
backgroundContext
and mainContext
to the coordinatorOriginal design: 28b9e4e (what we want to go back to)
Refactor to parent-child: f0aa87c
Basically need to revert stack changes in f0aa87c to go back to 28b9e4e
Extend CoreDataModel
such that a directory can be specified.
Default value should be ~/Documents/
for backwards compatibility. Also, this is likely the most common use case.
Since Example.xcodeproj and JSQCoreDataKit.xcodeproj are at the same level, Carthage builds ExampleModel.framework which is undesired. Moving /Example into /JSQCoreDataKit seems to me to be the best way to resolve this if you have no objections.
Add more/better tests for 1.1.0 additions.
Refine/double-check documentation
ld: file not found: /Users/glensimmons/Library/Developer/Xcode/DerivedData/JSQCoreDataKit-gtnoirqkhjsldddhczuizwdxwvee/Build/Products/Debug-iphonesimulator/Example.app/Example
clang: error: linker command failed with exit code 1 (use -v to see invocation)
See MagicalRecord for ideas, but make things Swifter.
Copy milestone release notes
Hi,
First thanks for your library (and for your realm talk !)
Everything works fine but I'm struggling with this question :
How I can adapt JSQCoreDataKit with a UISearchController the most swiftnessly possible.
Should I need to modify NSFetchedResultsController with a proper FetchRequest adapter everytime I select the UISearchController in my tableView ? Will it affect the delegate ?
Any thoughts on it would be greatly appreciated !
Anyway thanks again !
I have enabled concurrency detection for multithread violations using
-com.apple.CoreData.ConcurrencyDebug 1
in the Run arguments
Since then every save I raising this flag. Currently it seems this is happening how the saves are being handled.
The violation happens in save context for parent after the NSManagedObjectContextDidSaveNotification
is posted for the child context
Source/
and Tests/
(c571133)Hi, we're using your excellent framework, and I noticed that the saving performed on didReceiveChildContextDidSaveNotification
is using performBlockAndWait
by default (see here).
This may cause deadlocks, for example, if I replace the implementation of didTapAddButton
in the ExampleApp
with:
func didTapAddButton(sender: UIBarButtonItem) {
let childContext = stack.childContext()
childContext.performBlock {
Company.newCompany(childContext)
saveContext(childContext, wait: false)
}
for i in 1...10 {
childContext.performBlockAndWait { }
print(i)
}
}
It deadlocks.. I iterate 10 times just to make sure, but it deadlocks on the 2nd time.
The problem is that there's an implicit waiting when using saveContext(childContext, wait: false)
, i.e. the childContext
thread is waiting for the mainContext
to save..
Why not use a different mechanism for the parent's context saving, so that the waiting behaviour will be preserved?
Thanks in advance, Amitai.
The migration manager will be responsible for performing and managing migrations.
model.needsMigration
to detect if migrations are needed.I think it would be a good improvement to support container url paths, for when sharing CoreData with a an AppGroup to be used in a TodayViewExtension.
codecov appears to have broken with Xcode 7.2
@jessesquires Using Carthage 0.7.5
when I do carthage update --platform iOS
, it will download JSQCoreDataKit
but never build it. I've tried on develop
master
and 1.1.0
. Could you help me out?
The idea here is to present a convenient interface for dispatching Core Data work in the background, and calling back to the main thread upon completion.
My apologies if this question is at the wrong place. I'm new to GitHub. I watched your presentation at realm.io, and liked your clean approach. I tried to implement your solution with a designated Swift initializer in my OS X project which also uses bindings. When NSArrayController tries to make a new object of my NSManagedObject subclass, it crashes, because it tries to use init(entity:insertIntoManagedObjectContext:). That is an easy problem to fix, but when CoreData tries to open an existing archive from disk, it also tries to use the same initializer.
I tried, hackishly, to simply add init(entity:insertIntoManagedObjectContext:) as a convenience initializer, but this is far from ideal, because the ManagedObjectContext argument is optional, yet you need it to get an EntityDescription. The obvious solution was to try to use your CoreDataKit, so I tried to make a simple test project and use the Podfile. Cocoapods says:
[!] The platform of the target Pods
(OS X 10.10) is not compatible with JSQCoreDataKit (1.1.0)
, which does not support osx
.
So I thought perhaps the designated initializer approach only works on iOS? Do you have plans to add support for OS X? I suppose that apart from the example project, very little should be different between the two platforms?
Interesting approaches here:
https://www.bignerdranch.com/blog/introducing-the-big-nerd-ranch-core-data-stack/
Hey Jesse - was looking over the release-2.0 branch and noticed that the persistent store wasn't being added to the psc on a background thread. According to the new (preliminary) docs, they suggest you do so because it can take an unknown amount of time. Just thought I'd throw it out there.
As part of the initialization of Core Data, assign the adding of the persistent store (NSPersistentStore) to the persistent store coordinator (NSPersistentStoreCoordinator) to a background queue. That action can take an unknown amount of time, and performing it on the main queue can block the user interface, possibly causing the application to terminate.
And there sample implementation fwiw.
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
NSError *error = nil;
NSPersistentStoreCoordinator *psc = [[self managedObjectContext] persistentStoreCoordinator];
NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error];
NSAssert(store != nil, @"Error initializing PSC: %@\n%@", [error localizedDescription], [error userInfo]);
});
I'm not sure if I'm missing something but my app crashes on fetch request. Because it can't find
initWithEntity:insertIntoManagedObjectContext:
initialiser. I implemented my managed object same way as in the examples:
final class User: NSManagedObject {
init(context: NSManagedObjectContext, ...) {
let entity = NSEntityDescription.entityForName(self.dynamicType.modelName, inManagedObjectContext: context)!
super.init(entity: entity, insertIntoManagedObjectContext: context)
...
}
}
To fix this issue I changed the implementation:
final class User: NSManagedObject {
override init(entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext?) {
super.init(entity: entity, insertIntoManagedObjectContext: context)
}
convenience init(context: NSManagedObjectContext, ...) {
let entity = NSEntityDescription.entityForName(self.dynamicType.modelName, inManagedObjectContext: context)!
self.init(entity: entity, insertIntoManagedObjectContext: context)
...
}
}
Is there other way to fix this issue? Because overriding initialiser for every managed object looks not very clean
Is saveContext() intended to be called from any thread? The docs say "This function is performed in a block on the context's queue" implying that I can call it from any thread. However, the first line (context.hasChanges) is not thread safe. I discovered this because I have com.apple.CoreData.ConcurrencyDebug enabled.
I know that I can wrap saveContext() inside a performBlock call to avoid this.
I added a quick test to TestCase.swift
:
func test_CoreDataModel_Has_Description() {
let description = model.description
XCTAssertNotNil(description)
}
Which resulted in:
Test Suite 'Selected tests' started at 2015-06-21 23:18:55.817
Test Suite 'ModelTestCase' started at 2015-06-21 23:18:55.818
Test Case '-[JSQCoreDataKitTests.ModelTestCase test_CoreDataModel_Has_Description]' started.
/Users/tonyarnold/Documents/Open Source Projects/JSQCoreDataKit/JSQCoreDataKit/JSQCoreDataKitTests/TestCase.swift:46: error: -[JSQCoreDataKitTests.ModelTestCase test_CoreDataModel_Has_Description] : failed: caught "NSInvalidArgumentException", "Invalid store URL: nil"
(
0 CoreFoundation 0x00000001036f4885 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010316ddf1 objc_exception_throw + 48
2 CoreData 0x000000010d34e4eb CoreData + 1021163
3 JSQCoreDataKit 0x000000010d240839 JSQCoreDataKit + 14393
4 JSQCoreDataKit 0x000000010d241705 JSQCoreDataKit + 18181
5 JSQCoreDataKitTests 0x000000010d207721 JSQCoreDataKitTests + 26401
6 JSQCoreDataKitTests 0x000000010d207922 JSQCoreDataKitTests + 26914
7 CoreFoundation 0x00000001035e16ec __invoking___ + 140
8 CoreFoundation 0x00000001035e153e -[NSInvocation invoke] + 286
9 XCTest 0x0000000102c4eb4e XCTest + 97102
10 XCTest 0x0000000102c4ee46 XCTest + 97862
11 XCTest 0x0000000102c4ccef XCTest + 89327
12 XCTest 0x0000000102c4ccef XCTest + 89327
13 XCTest 0x0000000102c3b547 XCTest + 17735
14 XCTest 0x0000000102c58620 XCTest + 136736
15 XCTest 0x0000000102c3b493 XCTest + 17555
16 XCTest 0x0000000102c3be8e XCTest + 20110
17 XCTest 0x0000000102c7760d XCTest + 263693
18 xctest 0x0000000102bc9571 xctest + 5489
19 libdyld.dylib 0x00000001058e3a05 libdyld.dylib + 10757
20 ??? 0x0000000000000005 0x0 + 5
)
Test Case '-[JSQCoreDataKitTests.ModelTestCase test_CoreDataModel_Has_Description]' failed (7.325 seconds).
Test Suite 'ModelTestCase' failed at 2015-06-21 23:19:03.178.
Executed 1 test, with 1 failure (1 unexpected) in 7.325 (7.361) seconds
Test Suite 'Selected tests' failed at 2015-06-21 23:19:03.179.
Executed 1 test, with 1 failure (1 unexpected) in 7.325 (7.363) seconds
Program ended with exit code: 1
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.