JSQCoreDataKit - A swifter Core Data stack

Overview

JSQCoreDataKit CI

A swifter Core Data stack

About

This library aims to do the following:

  • Encode Core Data best practices, so you don't have to think "is this correct?" or "is this the right way to do this?"
  • Provide better interoperability with Swift
  • Harness Swift features and enforce Swift paradigms
  • Bring functional paradigms to Core Data
  • Make Core Data more Swifty
  • Simplify the processes of standing up the Core Data stack
  • Aid in testing your Core Data models
  • Reduce the boilerplate involved with Core Data

Further reading on Core Data:

Requirements

  • Xcode 12.0+
  • Swift 5.3+
  • iOS 11.0+
  • macOS 10.12+
  • tvOS 11.0+
  • watchOS 4.0+
  • SwiftLint

Installation

CocoaPods

pod 'JSQCoreDataKit', '~> 9.0.0'

# develop branch
pod 'JSQCoreDataKit', :git => 'https://github.com/jessesquires/JSQCoreDataKit.git', :branch => 'develop'

Swift Package Manager

Add JSQCoreDataKit to the dependencies value of your Package.swift.

dependencies: [
    .package(url: "https://github.com/jessesquires/JSQCoreDataKit.git", from: "9.0.0")
]

Alternatively, you can add the package directly via Xcode.

Documentation

You can read the documentation here. Generated with jazzy. Hosted by GitHub Pages.

Contributing

Interested in making contributions to this project? Please review the guides below.

Also, consider sponsoring this project or buying my apps! ✌️

Credits

Created and maintained by @jesse_squires.

License

Released under the MIT License. See LICENSE for details.

Copyright © 2015-present Jesse Squires.

Comments
  • Framework does not include symbols from NSManagedObjectContext

    Framework does not include symbols from NSManagedObjectContext

    When attempting to call 'delete' I am receiving a -[NSManagedObjectContext delete:]: unrecognized selector sent to instance 0x79e53be0.

    Placing breakpoints in the extension, I can quickly see that the JSQCoreDataKit NSManagedObjectContext extension is NOT called, which makes it understandable why the above error as 'delete' is being called

    Other included frameworks with extensions have worked ok... and I see that the example project works fine. No idea why these symbols are being lost, though a SO post sheds some light on the issue being known for 'generics'

    General information

    • Library version(s): 4.0.1
    • OS version(s): iOS 9.3
    • Devices/Simulators affected: iPhone 5 simulator
    • Reproducible in the demo project (Yes/No): No
    • Related issues: [http://stackoverflow.com/questions/24175596/swift-framework-does-not-include-symbols-from-extensions-to-generic-structs]

    Expected behavior

    Object is deleted

    Actual behavior

    -[NSManagedObjectContext delete:]: unrecognized selector sent to instance 0x79e53be0

    Steps to reproduce

    1. Include framework within the project.
    2. Add framework to the appropriate Build Phases.
    3. Call self.stack?.mainContext.delete(obj)
    question 
    opened by MobileVet 12
  • Add extensions to replace free functions

    Add extensions to replace free functions

    Prefer methods and properties to free functions.

    Swift API Design Guidelines

    ~~Let's keep the free functions in place, but add extensions to types (which should call the free functions).~~

    Update:*

    • [x] extension on NSManagedObjectContext for delete
    • [x] extension on NSManagedObjectContext for fetch
    • [x] move resetStack to CoreDataStack
    enhancement 
    opened by jessesquires 11
  • Provide the ability for the CoreDataStackFactory user to supply their…

    Provide the ability for the CoreDataStackFactory user to supply their…

    Pull request checklist

    • [ √ ] All tests pass. Demo project builds and runs.
    • [ √ ] I have resolved any merge conflicts.
    • [ √ ] I have followed the coding style, and reviewed the contributing guidelines.

    What's in this pull request?

    For a current project, I needed to supply a custom NSPersistentStoreCoordinator subclass so I could support an encrypted backing store. This pull request adds the ability to supply an optional factory method to the CoreDataStackFactory that allows the user of the factory to do just that. I included test coverage and all tests pass.

    opened by troya2 10
  • Add persistent store to coordinator on background queue

    Add persistent store to coordinator on background queue

    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.

    https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Conceptual/CoreData/IntegratingCoreData.html#//apple_ref/doc/uid/TP40001075-CH9-SW1

    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]);
    });
    

    https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Conceptual/CoreData/InitializingtheCoreDataStack.html#//apple_ref/doc/uid/TP40001075-CH4-SW1

    enhancement documentation 
    opened by bartcone 9
  • Concurrency thread limitations in CoreDataStackFactory not necessary

    Concurrency thread limitations in CoreDataStackFactory not necessary

    The current implementations in the createStackInBackground and createStack methods of the CoreDataStackFactory have some technically unnecessary limitations regarding the calling thread (precondition statements).

    Creating queue based contexts with the NSPrivateQueueConcurrencyType and NSMainQueueConcurrencyType on any thread (including the main thread) is absolutely legit and valid.

    As described in the NSManagedObjectContext Class Reference only contexts using the deprecated confinement pattern must be created and used from a single thread. I.e. those contexts are no longer valid if the thread to which the context was bound during the init phase ends. Queue based contexts on the other hand must not be used with anything else but the performBlock and performBlockAndWait which automatically ensures that the operations are run in a correct context (thread).

    That being said:

    • the precondition in createStack of CoreDataStackFactory is unnecessary. Calling this method asynchronously would be totally fine, both backgroundContext and the mainContext would work as expected.
    • the precondition in createStackInBackground of CoreDataStackFactory is also unnecessary.
    • CoreDataFunctions and the resetStack have the same limitation.

    It does however make sense for some of the mentioned methods to be called asynchronously (or to be called on the main queue) even though there's no technical requirement to do so. If the mentioned limitations are intended because it helps the UI to stay responsive then this should be at least documented. Otherwise it would be a good thing to give developers the freedom to use those methods on any queue they want for whatever reason there may be.

    bug enhancement 
    opened by wiedem 8
  • Added Framework Search Paths to ExampleModel project (#100)

    Added Framework Search Paths to ExampleModel project (#100)

    Pull request checklist

    This fixes issue #100

    What's in this pull request?

    Added Search Framework Path to the ExampleModel project to locate the JSQCoreDataKit.framework built during carthage build

    bug 
    opened by darkhonor 7
  • Update FetchRequest

    Update FetchRequest

    Pull request checklist

    This fixes issue #___.

    What's in this pull request?

    Uses a cleaner FetchRequest.

    opened by MaxHasADHD 7
  • Default saving uses performBlockAndWait and leads to deadlock?

    Default saving uses performBlockAndWait and leads to deadlock?

    General information

    • Library version(s): 2.2.0

    Description

    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.

    question 
    opened by david-hoze 7
  • Carthage builds ExampleModel.framework

    Carthage builds ExampleModel.framework

    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.

    question 
    opened by alexcurylo 7
  • Podspec needs to specify Swift version 3.0

    Podspec needs to specify Swift version 3.0

    New issue checklist

    General information

    • Library version(s): 6.0.0
    • OS version(s): MacOS 10.12
    • Devices/Simulators affected: No
    • Reproducible in the demo project (Yes/No): No
    • Related issues: None

    Expected behavior

    • No "Convert to Current Swift Syntax" dialog should appear after installing cocoapod
    • Project should build

    Actual behavior

    • "Convert to Current Swift Syntax" dialog appears after installing cocoapod
    • Project does not build. Error that JSQCoreDataKit is using legacy Swift.

    Steps to reproduce

    Create a project using Swift 3. Install latest cocoapod 6.0.0 Open project workspace Dialog opens to ask to "Convert to Current Swift Syntax"

    Crash log? Screenshots? Videos? Sample project?

    screen shot 2016-10-13 at 11 18 58

    This can be fixed by adding...

    "pod_target_xcconfig": { "SWIFT_VERSION": "3.0" }
    

    to the podspec but I don't know the syntax of the podspec file that you are using. I am used to the old syntax so not sure how it works with your podspec.

    Once this is added to the podspec it should quiet the dialog.

    question 
    opened by oliverfoggin 6
  • Top level function for migrations

    Top level function for migrations

    Pull request checklist

    • [x] All tests pass. Demo project builds and runs.
    • [x] I have resolved any merge conflicts.
    • [x] I have rebased on develop squashed my commits into 1 commit.
    • [x] I have followed the coding style, and reviewed the contributing guidelines.

    This fixes issue #46 .

    What's in this pull request?

    Added a top level function that performs progressive migrations. The function is a bit large, it could be broken down but not sure what's your preference @jessesquires .

    enhancement 
    opened by marius-serban 6
  • Include some test helpers?

    Include some test helpers?

    Can wrap this to be reusable:

    https://useyourloaf.com/blog/async-core-data-testing/

    (See also: "verifySaveSucceeded/Failed" helpers from my existing projects)

    feature request 
    opened by jessesquires 0
  • Remove plist files, autogenerate instead

    Remove plist files, autogenerate instead

    As of Xcode 13, plists can be generated automatically.

    We can delete them from the framework targets and test targets.

    Also update Package.swift

    https://useyourloaf.com/blog/xcode-13-missing-info.plist/

    enhancement 
    opened by jessesquires 0
  • macOS unit tests hang on GH actions

    macOS unit tests hang on GH actions

    Not sure why this is happening yet, but need to fix.

    Hypothesis: some tests write to disk. maybe a disk access permissions issues?

    Possible solution: disable those tests for macOS

    bug 
    opened by jessesquires 0
Releases(9.0.3)
  • 9.0.3(Sep 25, 2020)

  • 9.0.2(May 9, 2020)

  • 9.0.1(Sep 24, 2019)

  • 9.0.0(Sep 22, 2019)

    This release closes the 9.0.0 milestone.

    Breaking

    • Removed NSManagedObjectContext extension func save(wait:, completion:). Replaced with two new extension methods, func saveAsync(completion:) and func saveSync(completion:).

    • Removed SaveResult type in favor of Swift's new generic Result type.

    • Removed StackResult type in favor of Swift's new generic Result type.

    • Renamed CoreDataStackFactory to CoreDataStackProvider

    New

    • Added typealias SaveResult = Result<NSManagedObjectContext, Error> (Replaces the former SaveResult type.)

    • Added typealias StackResult = Result<CoreDataStack, Error> (Replaces the former StackResult type.)

    Changed

    • Upgraded to Swift 5.1
    • Update to Xcode 11
    • Update SwiftLint to 0.35.0, add new rules
    Source code(tar.gz)
    Source code(zip)
  • 8.0.0(Nov 7, 2018)

    This release closes the 8.0.0 milestone.

    • iOS 11.0 minimum now required
    • tvOS 11.0 minimum now required
    • macOS 10.12 minimum now required
    • watchOS 4.0 minimum now required

    New

    • Upgraded to Swift 4.2 (#125)
    • Update to Xcode 10.1
    • Update SwiftLint to 0.27.0

    Breaking

    • PersistentStoreOptions typealias is now [AnyHashable: Any] (#119)

    • Make APIs more "swifty" (#120)

      • Nest top-level function defaultDirectoryURL() under CoreDataModel
      • Nest ChildContext typealias under NSManagedObjectContext extension
      • Move saveContext() top-level function to extension method on NSManagedObjectContext

    Changed

    • Use Equatable auto-synthesis where possible
    Source code(tar.gz)
    Source code(zip)
  • 7.0.0(Sep 27, 2017)

    • Converted to Swift 4.0
    • iOS 9.0 minimum now required
    • tvOS 10.0 minimum now required
    • watchOS 3.0 minimum now required
    • macOS 10.11 minimum now required
    Source code(tar.gz)
    Source code(zip)
  • 6.0.3(Apr 4, 2017)

  • 6.0.2(Jan 3, 2017)

  • 6.0.1(Oct 27, 2016)

  • 6.0.0(Sep 30, 2016)

    This release closes the 6.0.0 milestone.

    Swift 3.0 now required.

    Breaking

    • Migrated to Swift 3.0
    • Removed entity(name: String, context: NSManagedObjectContext) -> NSEntityDescription
    • Removed FetchRequest<T: NSManagedObject> (new Swift overlays now provide generic NSFetchRequest)
    • Remove the delete() and fetch() extensions on NSManagedObjectContext (new Swift overlays now provide these)

    New

    • There's a new protocol, CoreDataEntityProtocol, which provides a better API for creating entity descriptions and inserting managed objects (#87). It also provides some helpful extensions. Conform to the new CoreDataEntityProtocol to take advantage of this. This replaces the (removed) top-level function entity(name:, context:) -> NSEntityDescription
    Source code(tar.gz)
    Source code(zip)
  • 5.0.0(Sep 15, 2016)

  • 4.0.2(Jun 6, 2016)

  • 4.0.1(Jun 2, 2016)

  • 4.0.0(May 8, 2016)

    This release closes the 4.0.0 milestone.

    This release includes a significant change to CoreDataStack, which no longer uses child contexts. The mainContext and backgroundContext are now both connected to the persistent store coordinator. See #60 for the background and rationale behind this change. In short, child contexts are considered bad practice for this kind of stack setup and should really only be used for "throw away" work.

    While this is technically a breaking change, it likely will not affect most clients. The behavior should remain largely unchanged — data is still kept in-sync between the 2 contexts. So unless you were specifically relying on this parent-child nesting behavior, you should be fine. 👍

    Thanks

    Huge thanks to @Liquidsoul for closing most of the issues for this release and to @wiedem for contributing significantly as well! 🎉

    Breaking changes ⚠️

    Stack
    • The mainContext and backgroundContext are now both connected to the persistent store coordinator (#60)
    • When creating a child context, the concurrencyType determines which context is the parent (#73)
    • CoreDataStackFactory has been simplified. There is now a single createStack() method. (#77)
    Free functions

    In alignment with the latest Swift API guidelines, the library now prefers methods/extensions over free functions.

    • The resetStack() top-level function is now a method on CoreDataStack (#75)
    • The deleteObjects() top-level function is now an extension method on NSManagedObjectContext (#76)
    • The fetch() top-level function is now an extension method on NSManagedObjectContext (#78)
    • The migrate() top-level function is now an extension method CoreDataModel (#82)

    Documentation

    All docs have been updated. As usual, check these out for more details on the changes described above.

    Refinements

    There have been other general refinements and additional unit tests have been added. Test coverage is 94% 😎

    Source code(tar.gz)
    Source code(zip)
  • 3.0.0(Apr 4, 2016)

    This release closes the 3.0.0 milestone.

    The goals of this release are primarily to adopt Swift 2.2 and refine the API to make it more Swifty, as the definition of Swifty has evolved.

    Breaking changes :warning:

    There are many breaking changes in this release, however — with the exception of Swift 2.2 — they are all merely name changes that aim to reduce verbosity.

    • Migrated to Swift 2.2. (#67) Swift 2.2 and above is now required.
    • Renamed DefaultStoreOptions to defaultStoreOptions
    • Renamed CoreDataSaveResult to SaveResult
    • Renamed CoreDataStackResult to StackResult
    • Renamed CoreDataModel.removeExistingModelStore() to CoreDataModel.removeExistingStore()
    • Renamed all enum cases to be lowercase, in line with latest Swift API guidelines
    • The StackResultClosure typealias has been removed

    New features

    • Support for Swift Package Manager (#55) :tada:
    • Core Data model migration support! (#46, #66) Thanks @marius-serban ! :tada: See the README and docs for details!
    Source code(tar.gz)
    Source code(zip)
  • 2.2.1(Apr 2, 2016)

    This release closes the 2.2.1 milestone.

    Fixes

    • Fixed multithreading violation while saving context (#63, #59, #65). Thanks @saurabytes and @markkrenek!
    • On tvOS, the default SQLite directory now defaults to .CacheDirectory instead of .DocumentDirectory (#61, #62). Thanks @cgoldsby !
    Source code(tar.gz)
    Source code(zip)
  • 2.2.0(Dec 28, 2015)

    This release closes the 2.2.0 milestone.

    New

    Added a resetStack() top-level function. See the updated docs for details. Thanks @marius-serban! :tada:

    Changes

    :warning: CoreDataStackFactory.CompletionHandler was moved from the factory's scope to the module's scope and renamed to StackResultClosure. This is technically a breaking change, but it is highly unlikely that anyone was referring to this closure directly. If so, simply rename to the correct type.

    Source code(tar.gz)
    Source code(zip)
  • 2.1.0(Dec 3, 2015)

  • 2.0.0(Oct 17, 2015)

    :tada: JSQCoreDataKit 2.0 is here! :tada:

    img

    Breaking changes

    • Swift 2.0
    • You must now initialize CoreDataStack via a CoreDataStackFactory. This will init the stack on a background queue and return to your completion handler on the main queue when finished. This is necessary since adding a persistent store can take an unknown amount of time.
    • Rethinking and rewriting of CoreDataStack. It now has a mainContext and a backgroundContext. :sunglasses:
    • Saving a context now returns a CoreDataSaveResult to the completion handler, instead of NSError?

    New

    • New CoreDataStackFactory for async stack initialization, as mentioned above. It also support synchronous init if you need it, but this is only recommended for testing. Returns a CoreDataStackResult.
    • All types now conform to CustomStringConvertible and Equatable. :facepunch:

    Issues closed

    Find the complete list of closed issues here. :bug:

    Documentation

    All documentation has been updated. :scroll:

    Example app

    The example app is actually an example app now, check it out! It's a pretty substantial demo.

    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Apr 26, 2015)

  • 1.0.0(Mar 22, 2015)

Owner
Jesse Squires
unpaid labor for everyone. indie. he/him.
Jesse Squires
100% Swift Simple Boilerplate Free Core Data Stack. NSPersistentContainer

DATAStack helps you to alleviate the Core Data boilerplate. Now you can go to your AppDelegate remove all the Core Data related code and replace it wi

Nes 216 Jan 3, 2023
JSON to Core Data and back. Swift Core Data Sync.

Notice: Sync was supported from it's creation back in 2014 until March 2021 Moving forward I won't be able to support this project since I'm no longer

Nes 2.5k Dec 31, 2022
Core Data Generator (CDG for short) is a framework for generation (using Sourcery) of Core Data entities from plain structs/classes/enums.

Core Data Generator Introduction Features Supported platforms Installation CDG Setup RepositoryType ModelType DataStoreVersion MigrationPolicy Basic U

Lotusflare 18 Sep 19, 2022
DataKernel is a minimalistic wrapper around CoreData stack to ease persistence operations.

DataKernel What is DataKernel? DataKernel is a minimalistic wrapper around CoreData stack to ease persistence operations. It is heavily inspired by Su

Denis 16 Jun 2, 2022
Super awesome Swift minion for Core Data (iOS, macOS, tvOS)

⚠️ Since this repository is going to be archived soon, I suggest migrating to NSPersistentContainer instead (available since iOS 10). For other conven

Marko Tadić 306 Sep 23, 2022
A powerful and elegant Core Data framework for Swift.

A powerful and elegant Core Data framework for Swift. Usage Beta version. New docs soon... Simple do that: let query = persistentContainer.viewContext

null 782 Nov 6, 2022
CloudCore is a framework that manages syncing between iCloud (CloudKit) and Core Data written on native Swift.

CloudCore CloudCore is a framework that manages syncing between iCloud (CloudKit) and Core Data written on native Swift. Features Leveraging NSPersist

deeje cooley 123 Dec 31, 2022
Unleashing the real power of Core Data with the elegance and safety of Swift

Unleashing the real power of Core Data with the elegance and safety of Swift Dependency managers Contact Swift 5.4: iOS 11+ / macOS 10.13+ / watchOS 4

John Estropia 3.7k Jan 9, 2023
JustPersist is the easiest and safest way to do persistence on iOS with Core Data support out of the box.

JustPersist JustPersist is the easiest and safest way to do persistence on iOS with Core Data support out of the box. It also allows you to migrate to

Just Eat 167 Mar 13, 2022
QueryKit, a simple type-safe Core Data query language.

QueryKit QueryKit, a simple type-safe Core Data query language. Usage QuerySet<Person>(context, "Person")

QueryKit 1.5k Dec 20, 2022
A minimalistic, thread safe, non-boilerplate and super easy to use version of Active Record on Core Data.

Skopelos A minimalistic, thread-safe, non-boilerplate and super easy to use version of Active Record on Core Data. Simply all you need for doing Core

Alberto De Bortoli 235 Sep 9, 2022
HitList is a Swift App shows the implementation of Core Data.

HitList HitList is a Swift App shows the implementation of Core Data. It is the demo app of Ray Wenderlich's tech blog. For details please reference G

Kushal Shingote 2 Dec 9, 2022
A synchronization framework for Core Data.

Core Data Ensembles Author: Drew McCormack Created: 29th September, 2013 Last Updated: 15th February, 2017 Ensembles 2 is now available for purchase a

Drew McCormack 1.6k Dec 6, 2022
Core Data code generation

mogenerator Visit the project's pretty homepage. Here's mogenerator's elevator pitch: mogenerator is a command-line tool that, given an .xcdatamodel f

Wolf Rentzsch 3k Dec 30, 2022
Super Awesome Easy Fetching for Core Data!

MagicalRecord In software engineering, the active record pattern is a design pattern found in software that stores its data in relational databases. I

Magical Panda Software 10.9k Dec 29, 2022
A type-safe, fluent Swift library for working with Core Data

Core Data Query Interface (CDQI) is a type-safe, fluent, intuitive library for working with Core Data in Swift. CDQI tremendously reduces the amount o

null 31 Oct 26, 2022
A feature-light wrapper around Core Data that simplifies common database operations.

Introduction Core Data Dandy is a feature-light wrapper around Core Data that simplifies common database operations. Feature summary Initializes and m

Fuzz Productions 33 May 11, 2022
Example repo of working with Core Data in a SwiftUI application

CoreData in SwiftUI This repository serves many purpose. But mostly so I can experiment with Core Data in SwiftUI, and also so I can use it show my ap

Donny Wals 4 Jan 30, 2022
This project server as a demo for anyone who wishes to learn Core Data in Swift.

CoreDataDemo This project server as a demo for anyone who wishes to learn Core Data in Swift. The purpose of this project is to help someone new to Co

null 1 May 3, 2022