Giter Club home page Giter Club logo

coredatastack's Introduction

BNR Core Data Stack

Carthage compatible CocoaPods Compatible GitHub license Build Status

Big Nerd Ranch

The BNR Core Data Stack is a small Swift framework that makes it both easier and safer to use Core Data.

A better fetched results controller and delegate

Our FetchedResultsController<ManagedObjectType> sends Swifty delegate messages, rather than a mess of optionals.

Turn this:

func controller(
    _ controller: NSFetchedResultsController<NSFetchRequestResult>,
    didChange anObject: Any,
    at indexPath: IndexPath?,
    for type: NSFetchedResultsChangeType,
    newIndexPath: IndexPath?
) {
    guard let book = anObject as? Book else {
        preconditionFailure("Why is this thing an Any anyway? WTH!")
    }

    switch type {
    case .insert:
        guard let newIndexPath = newIndexPath else {
            preconditionFailure("Insertion to nowheresville? WHY IS THIS OPTIONAL?")
        }

        print("We have a new book! \(book.title)")
        tableView?.insertRows(at: [newIndexPath], with: .automatic)

    case .delete:
        guard let indexPath = indexPath else {
            preconditionFailure("Deletion you say? Where? WHY IS THIS OPTIONAL?")
        }

        tableView?.deleteRows(at: [indexPath], with: .automatic)

    case .move:
        guard let newIndexPath = newIndexPath else {
            preconditionFailure("It moved to NOWHERE! WHY IS THIS OPTIONAL?")
        }
        guard let indexPath = indexPath else {
            preconditionFailure("It moved from NOWHERE?! WHY IS THIS OPTIONAL!")
        }

        tableView?.moveRow(at: indexPath, to: newIndexPath)

    case .update:
        guard let indexPath = indexPath else {
            preconditionFailure("I give up! Remind me, why are we using Swift, again?")
        }

        tableView?.reloadRows(at: [indexPath!], with: .automatic)
    }
}

Into this:

func fetchedResultsController(
    _ controller: FetchedResultsController<Book>,
    didChangeObject change: FetchedResultsObjectChange<Book>
) {
    switch change {
    case let .insert(book, indexPath):
        print("Hey look, it's not an Any! A new book: \(book.title)")
        tableView?.insertRows(at: [indexPath], with: .automatic)

    case let .delete(_ /*book*/, indexPath):
        print("A deletion, and it has a from-where? Finally!")
        tableView?.deleteRows(at: [indexPath], with: .automatic)

    case let .move(_ /*book*/, fromIndexPath, toIndexPath):
        print("Whoah, wait, I actually HAVE index paths? Both of them? Yay!")
        tableView?.moveRow(at: fromIndexPath, to: toIndexPath)

    case let .update(_ /*book*/, indexPath):
        print("It's almost like I'm actually using Swift and not Obj-C!")
        tableView?.reloadRows(at: [indexPath], with: .automatic)
    }
}

It also has properly typed sections and subscripting operators. Because, we are writing Swift, are we not?

As a further bonus, you get our workarounds for some misbehavior of Core Data that contradicts the documentation, like this one:

// Work around a bug in Xcode 7.0 and 7.1 when running on iOS 8 - updated objects
// sometimes result in both an Update *and* an Insert call to didChangeObject,
// … (explanation continues) …

Convenient store change listening

Our EntityMonitor<ManagedObjectType> makes it easy to listen to all changes for a given ManagedObjectType:

/* EXAMPLE: NOTIFYING WHEN A MOC SAVES AUTHOR CHANGES */
let authorMonitor = EntityMonitor<Author>(context: moc, entity: authorEntityDescription, frequency: .onSave)
let authorMonitorDelegate = AuthorMonitorDelegate()
authorMonitor.setDelegate(authorMonitorDelegate)


/* EXAMPLE: AUTHOR MONITOR DELEGATE */
class AuthorMonitorDelegate: EntityMonitorDelegate {
    func entityMonitorObservedInserts(
        _ monitor: EntityMonitor<Author>,
        entities: Set<Author>
    ) {
        print("inserted authors:", entities)
    }

    func entityMonitorObservedModifications(
        _ monitor: EntityMonitor<Author>,
        entities: Set<Author>
    ) {
        print("modified authors:", entities)
    }

    func entityMonitorObservedDeletions(
        _ monitor: EntityMonitor<Author>,
        entities: Set<Author>
    ) {
        print("deleted authors:", entities)
    }
}

A friendlier managed object context

Extension methods on ManagedObjectContext ensure saves happen on the right queue and make your life easier:

// Gotta catch 'em all
let allBooks = try Book.allInContext(moc)

// Or at least one of 'em
let anyBook = try Book.findFirstInContext(moc)

// Ah, forget it. Rocks fall, everyone dies.
try Book.removeAllInContext(moc)


// Blocking save, including up through parent contexts,
// on the appropriate queue.
try moc.saveContextToStoreAndWait()

Interested?

Check out the documentation!

For more details on the design methodology, read "Introducing the Big Nerd Ranch Core Data Stack."

Why "Stack"? Previously, the Core Data Stack provided a full, ready-made Core Data stack. Apple now provide that themselves in NSPersistentContainer, so we're free to focus on the other benefits listed above, and we have [deprecated][#sec:deprecations] our own stack in favor of Apple's.

Swift-Only: Note that the Core Data Stack is intended to be used from Swift. Any use you can make of it from Objective-C is by luck, not design.

Support

Big Nerd Ranch can help you develop your app, or train you or your team in Swift, iOS, and more. We share what we learn here on GitHub and in bookstores near you.

For questions specific to the Core Data Stack, please open an issue.

Minimum Requirements

Running

Apps using BNR Core Data Stack can be used on devices running these versions or later:

  • macOS 10.10
  • tvOS 9.0
  • iOS 8.0

Building

To build an app using BNR Core Data Stack, you'll need:

  • Xcode 8.0
  • Swift 3.0

Usage

Type Safe Monitors

Fetched Results Controller

FetchedResultsController<T> is a type safe wrapper around NSFetchedResultsController using Swift generics.

Example

See BooksTableViewController.swift for an example.

Entity Monitor

EntityMonitor<T> is a class for monitoring inserts, deletes, and updates of a specific NSManagedObject subclass within an NSManagedObjectContext.

Example

See EntityMonitorTests.swift for an example.

NSManagedObject Extensions

Adds convenience methods on NSManagedObject` subclasses. These methods make fetching, inserting, deleting, and change management easier.

Example

let allBooks = try Book.allInContext(moc)
let anyBook = try Book.findFirstInContext(moc)
try Book.removeAllInContext(moc)

Installation

Installing with Carthage

Add the following to your Cartfile:

github "BigNerdRanch/CoreDataStack"

Then run carthage update.

In your code, import the framework as CoreDataStack.

Follow the current instructions in Carthage's README for up to date installation instructions.

Installing with CocoaPods

Add the following to your Podfile:

pod 'BNRCoreDataStack'

You will also need to make sure you're opting into using frameworks:

use_frameworks!

Then run pod install.

In your code, import the framework as BNRCoreDataStack.

Contributing

Please see our guide to contributing to the CoreDataStack.

Debugging Tips

To validate that you are honoring all of the threading rules it's common to add the following to a project scheme under Run > Arguments > Arguments Passed On Launch.

-com.apple.CoreData.ConcurrencyDebug 1

This will throw an exception if you happen to break a threading rule. For more on setting up Launch Arguments check out this article by NSHipster.

Excluding sensitive data from iCloud and iTunes backups

The default store location will be backed up. If you're storing sensitive information such as health records, and perhaps if you're storing any personally identifiable information, you should exclude the store from backup by flagging the URL on disk:

/* EXAMPLE: EXCLUDING A FILE FROM BACKUP */
var excludeFromBackup = URLResourceValues()
excludeFromBackup.isExcludedFromBackup = true

let someParentDirectoryURL: URL = 
var storeFileURL = URL(
    string: "MyModel.sqlite",
    relativeTo: someParentDirectoryURL)!
try! storeFileURL.setResourceValues(excludeFromBackup)

You then need to point your persistent container at that location:

/* EXAMPLE: AIMING YOUR CONTAINER AT A SPECIFIC URL */
// Ensure parent directory exists
try! FileManager.default.createDirectory(
    at: storeFileURL.deletingLastPathComponent(),
    withIntermediateDirectories: true)

// Configure the persistent container to use the specific URL
container.persistentStoreDescriptions = [
    NSPersistentStoreDescription(url: storeFileURL),
    ]

Prior to NSPersistentContainer, this would be done with Core Data Stack by:

/* EXAMPLE: DEPRECATED CORE DATA STACK WITH STORE URL */
CoreDataStack.constructSQLiteStack(
    withModelName: "MyModel",
    withStoreURL: storeFileURL) { result in
        switch result {
        case .success(let stack):
            // Use your new stack

        case .failure(let error):
            //handle error ...
        }
    }

Deprecations

iOS 10.0 / macOS 10.12

  • Deprecated: The CoreDataStack class itself.
    • Replacement: Use Apple's NSPersistentContainer instead. The [Container Example](./Container Example/README.md) demonstrates how to use NSPersistentContainer with the BNR Core Data Stack.
  • Deprecated: The CoreDataModelable protocol.
    • Replacement: Use the type method NSManagedObject.entity(). Many of the convenience methods formerly available on CoreDataModelable are now offered by BNR Core Data Stack as extension methods on NSManagedObject as FetchHelpers.

coredatastack's People

Contributors

alessandroorru avatar aranoledur avatar darrarski avatar davidahouse avatar hitsvilleusa avatar hschultjan avatar hydhknn avatar jeremy-w avatar qmoya avatar randomstep avatar rcedwards avatar readmecritic avatar zwaldowski avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

coredatastack's Issues

Add support for creating child NSManagedObjectContext in the main queue

Feature Request

I would like to have the option to create child contexts in the main queue.

Additional Context

It would be great if you could create a new child context in the main queue that can be used for example when the user needs to update and NSManagedObject. That way if the user decides not to save the changes, you can just get rid of the context and everything will be as before the changes.

CoreData test utilities?

Are there any blobs of code we frequently rewrite as part of testing something that relies on Core Data? If so, could we make those available for use in tests alongside the useful methods available for getting Core Data set up in the main app?

Crash saving background context

Any idea on where's the issue in this crash?

Thread : Crashed: NSManagedObjectContext 0x15462eaa0: Background Worker Context
0  libswiftCore.dylib             4317556504 usesNativeSwiftReferenceCounting_unowned(void const*) + 156
1  libswiftCore.dylib             4317557536 swift_unknownWeakRelease + 36
2  BNRCoreDataStack               4305106224 _TFFE16BNRCoreDataStackCSo22NSManagedObjectContext11saveContextFS0_FTGSqFOS_13SuccessResultT___T_U_FGSqFS1_T__T_ + 268
3  CoreData                       6501320960 developerSubmittedBlockToNSManagedObjectContextPerform + 196
4  libdispatch.dylib              6860510888 _dispatch_client_callout + 16
5  libdispatch.dylib              6860560108 _dispatch_queue_drain + 864
6  libdispatch.dylib              6860525996 _dispatch_queue_invoke + 464
7  libdispatch.dylib              6860510888 _dispatch_client_callout + 16
8  libdispatch.dylib              6860569408 _dispatch_root_queue_drain + 2140
9  libdispatch.dylib              6860567260 _dispatch_worker_thread3 + 112

I can't find what called save context. It's a fabric remote crash report.

Add BNRCoreDataStackConvenienceSaves to Add Ons wiki page

Please, consider adding my Add On to list on wiki page. It adds convenience extension to NSManagedObjectContext that that makes saving contexts easier and more efficient.

Description Repository
NSManagedObjectContext convenience extension for saving or rolling back context and performing grouped saves. darrarski/BNRCoreDataStackConvenienceSaves

Brief description is included in the README.md on Add On's repository. There are also tests that demonstrates example usage. Add On integration is handled by Cocoapods.

When using Mogenerator, making a ManagedObject implement CoreDataModelable gives error

Feature Request

What would you like to see that is not available?

I have created my Model Objects with MoGenerator.
When I make one of those generated classes implement CoreDataModelable, I get an error:
/Model/Custom/Region.swift:7:20: Getter for 'entityName' with Objective-C selector 'entityName' conflicts with method 'entityName()' from superclass '_Region' with the same Objective-C selector

Question

Would it be a better idea to put all those very usefull functions in a straightforward:
extension NSManagedObject {
}

Expected behavior

Either way, I would like to be able to use the useful functions you implemented in CoreDataModelable.

Actual behavior

Compile error:
Getter for 'entityName' with Objective-C selector 'entityName' conflicts with method 'entityName()' from superclass '_Region' with the same Objective-C selector

Additional Context

Xcode 7.3.1, Mogenerator 1.29, BNRCoreDataStack 1.2.5, Swift 2.2.

Thanks for contributing to the CoreDataStack!

NSPersistentStoreCoordinator options.

Hi again! Want to say that I really like this framework and want to continue to use it without copying source files. But right now I need a way to add some options to persistent store. I need to encrypt my core data using FileProtection: Complete. Or even better: init CoreDataStack with custom NSPersistentStoreCoordinator. I can do it and create Pull request. But do you need this feature in this framework (will you accept PR)? Or maybe this feature has already been implemented and I couldn't find a way to use it?

"Require Only App-Extension-Safe API" build setting is set to NO

"Require Only App-Extension-Safe API" build setting is set to NO on all targets, which causes Xcode to show a warning - "Linking against a dylib which is not safe for use in application extensions", when CoreDataStack is used as a framework (via Carthage, for example).

CoreDataStack interface should be a protocol for easier mocking

We should look into how we can separate construction of the CoreDataStack from using an instance.

A single concrete class with factory-ish methods is difficult to mock in tests. Ideally the instance methods could be in a protocol.

I don't know that it will make the contract easy to satisfy with valid objects (NSManagedObjectContext in particular requires the stack in some form), but it is probably the right design choice.

Publish Pod version 2.0.0

Feature Request

The 2.0.0 podspec needs to be published.

Issue

The pod lint is failing around the @available with regards to the use of entity()

 -> BNRCoreDataStack (2.0.0)
    - ERROR | [tvOS] xcodebuild: Returned an unsuccessful exit code. You can use `--verbose` for more information.
    - ERROR | [tvOS] xcodebuild:  BNRCoreDataStack/Sources/NSManagedObject+FetchHelpers.swift:29:31: error: 'entity()' is only available on tvOS 10.0 or newer
    - NOTE  | [tvOS] xcodebuild:  BNRCoreDataStack/Sources/NSManagedObject+FetchHelpers.swift:29:31: note: add 'if #available' version check
    - NOTE  | [tvOS] xcodebuild:  BNRCoreDataStack/Sources/NSManagedObject+FetchHelpers.swift:29:31: note: add @available attribute to enclosing static method
    - NOTE  | [tvOS] xcodebuild:  BNRCoreDataStack/Sources/NSManagedObject+FetchHelpers.swift:29:31: note: add @available attribute to enclosing extension

An earlier pre-release version of CocoaPods had this fixed, as I was able to validate the pod spec before merging into master, however now its unable to pass and cannot be published.

Solution

We'll wait and see when this is resolved on CocoaPods side so we can publish the spec. In the meantime you should be able to specify the tag or master if you need to use the Swift 3.0 version right away.

Investigate moving CI to Circle CI

Feature Request

Achieve process parity of Travis CI with Circle CI.

Expected behavior

We should continue to be able to publish docs, verify carthage/cocoa pod install, run unit tests etc.

Actual behavior

n/a

Additional Context

Experiencing extremely long build times and as of the last couple days unable to get a completed build in general from Travis CI.

CoreDataModelable entityInContext should be public or private?

If I embed the CoreDataStack source files directly in my project, I can use CoreDataModelable entityInContext (since it will be defined as internal). But if I embed CoreDataModelable as a framework, entityInContext is not available, since only public functions are available in a framework.

(Swift 3) Make `performAndWaitOrThrow` `rethrows` and `@noescape`

Swift 3 allows forced conversion between @escaping functions and not. You can then use what DispatchQueue.sync(execute:) does to allow sync to return and/or rethrow values:

extension NSManagedObjectContext {
    func performAndWaitOrThrow<Return>(_ body: () throws -> Return) rethrows -> Return {
        func impl(execute work: () throws -> Return, recover: (Error) throws -> Void) rethrows -> Return {
            var result: Return!
            var error: Error?

            // performAndWait is marked @escaping as of iOS 10.0.
            typealias Fn = (() -> Void) -> Void
            let performAndWaitNoescape = unsafeBitCast(self.performAndWait, to: Fn.self)
            performAndWaitNoescape {
                do {
                    result = try work()
                } catch let e {
                    error = e
                }
            }

            if let error = error {
                try recover(error)
            }

            return result
        }

        return try impl(execute: body, recover: { throw $0 })
    }
}

Used like:

let value: Int = try context.performAndWaitOrThrow {
    throw SomeError()
}

Consider options for more specific ErrorTypes from saveContextAndWait()

The Swift 2 compiler seems to have trouble identifying the types of errors that can be thrown from saveContextAndWait(), so when I call it, I must have a catch-all clause at the end of my error handling, like this:

do {
    moc.saveContextAndWait()
} catch let error as NSError {
    // do stuff with expected NSError
} catch {
    // do nothing?
}

Should we have a more specific ErrorType enum that encapsulates the system errors?

Why not return to the main thread after constructing a stack ?

It is pretty common inside a TableViewController's init or viewDidLoad method to have initialisation code like the following:

override func viewDidLoad() {
  super.viewDidLoad()
  CoreDataStack.constructSQLiteStack(withModelName: "SomeName") { outcome in
    print(NSThread.isMainThread())     // false
    switch outcome {
      case .Failure(let error)        : print(error)
      case .Success(let coreDataStack):
        self.coreDataStack = coreDataStack
        self.tableView.reloadData()    // crash
    }
  }  
}

This code will crash however because the callback is executed on a background thread (created by setupSQLiteBackedCoordinator.

Unless I missed something, it seems to me it would be less confusing if the callback was executed on the main thread. After all, once the stack has been set up why remain in the background thread?

A pretty simple fix would be to just wrap the callback calls inside constructSQLiteStack:

    dispatch_async(dispatch_get_main_queue(), { 
      callback(.Success(stack))  // or callback(.Failure(error))
    })

Question for BatchUpdateRequest.

Question

Hi, I really enjoy using this framework, but I have something unclear about batch update.

The test project goes here.
CoreDataTest.zip

I have created CoreDataStack in ViewController.swift and seed initial data like this.

private func seedInitData(stack:CoreDataStack){
        let moc = stack.newChildContext()
        do {
            try moc.performAndWaitOrThrow {
                let books = ["Book 1", "Book 2", "Book3"]
                for bookTitle in books {
                    let book = Book(managedObjectContext: moc)
                    book.title = bookTitle
                    book.isRent = false
                }
                try moc.saveContextAndWait()
            }
        } catch {
            print("Error creating initial data: \(error)")
        }
    }

After that did some testing on testStack() function in NewViewController.swift file.

func testStack(){
        let context = stack.newChildContext(concurrencyType: .PrivateQueueConcurrencyType, name: "batchWorker")
        let batchRequest = NSBatchUpdateRequest(entityName: "Book")
        batchRequest.propertiesToUpdate = ["isRent" : true]
        batchRequest.resultType = .UpdatedObjectIDsResultType
        do{

            // First, try to fetch all book object from core data.
            let objs = try context.executeFetchRequest(NSFetchRequest(entityName: "Book"))
            print("--------------Book objects before performing batch updates-----------")
            objs.forEach{
                let book = $0 as! Book
                // It should show false
                print("title : \(book.title), Rent = \(book.isRent)")
            }
            let batchResult = try context.executeRequest(batchRequest) as! NSBatchUpdateResult
            let objectIDS = batchResult.result as! [NSManagedObjectID]

            print("\n\n--------------After performing batch request & refreshObject-----------")
            objectIDS.forEach{
                let object = context.objectWithID($0) as! Book
                context.refreshObject(object, mergeChanges: false)

                // I think this should show true, but showing false now (So not changed)
                print("title : \(object.title), isRent : \(object.isRent)")
            }
        }catch{}
    }

Output Log

--------------Book objects before performing batch updates-----------
title : Optional("Book 2"), Rent = Optional(0)
title : Optional("Book 1"), Rent = Optional(0)
title : Optional("Book3"), Rent = Optional(0)


--------------After performing batch request & refreshObject-----------
title : Optional("Book 2"), isRent : Optional(0)
title : Optional("Book 1"), isRent : Optional(0)
title : Optional("Book3"), isRent : Optional(0)

I think after batch request is performed, it should show true. But it's showing false.
Is this right behaviour or did I understand wrong?

It will be appreciated if anyone can help me.

FetchedResultsController not receiving updates fromNSBatchDeleteRequest

Sorry to bother you guys again. I am having an issue using the NSBatchDeleteRequest object with the CoreDataStack and the FetchedResultsController.

The issue seems to be that the FetchedResultsController doesn't receive the delegate callbacks after the delete occurs? So none of the UI gets updated removing the items on the screen. I am initializing CoreDataStack with CoreDataStack.constructSQLiteStack so I can see that the database changes are occurring in the table and also you can see in the code below I am printing out how many items are affected.

Below is an example of what I am testing against on the BooksTableViewController. Is there a way to use the NSBatchDeleteRequest to deal with Bulk Deletes or do you have to fetch the items and then delete them 1 at a time with Context.deleteObject(object)?

let deleteItems = [
"American Pastoral",
"An American Tragedy",
"Animal Farm"
]

        let request = NSFetchRequest(entityName: Book.entityName)
        request.predicate = NSPredicate(format: "title IN %@", deleteItems)

        let del = NSBatchDeleteRequest(fetchRequest:request)
        del.resultType = .ResultTypeCount

        do{
            if let moc = coreDataStack.newBackgroundWorkerMOC(), let batchResult = try moc.executeRequest(del) as? NSBatchDeleteResult{
            if let count = batchResult.result as? Int where count > 0 {
                print("delete result:\(count)")
                try moc.saveContextAndWait()
            }
        }
        }catch{
            print(error)
        }

Build issues with Xcode 8 beta 3

Feature Request

I am trying to build with Xcode 8 beta 3, while keep using Swift 2.3, and I get a few build errors. Can you fix them, so that I can get the fixes through 'pod install'?

There are issues in CoreDataStack.swift and in CoreDataModelable.swift.

Actual behavior

Build errors in CoreDataStack.swift:

    let _ = try? fm.removeItemAtURL(storeURL.URLByAppendingPathComponent("-shm"))
                     (!)Value of optional type 'NSURL?' not unwrapped; did you mean to use '!' or '?'?
    let _ = try? fm.removeItemAtURL(storeURL.URLByAppendingPathComponent("-wal"))
                     (!)Value of optional type 'NSURL?' not unwrapped; did you mean to use '!' or '?'?

URLByAppendingPathComponent returns an optional which should be unwrapped or handled correctly. Quick (but possibly unsafe) fix:

    let _ = try? fm.removeItemAtURL(storeURL.URLByAppendingPathComponent("-shm")!)
    let _ = try? fm.removeItemAtURL(storeURL.URLByAppendingPathComponent("-wal")!)

Build error in CoreDataModelable.swift:

    var error: NSError? = nil
    let count = context.countForFetchRequest(fetchReqeust, error: &error)
                     (!)Extra argument 'error' in call
    if let error = error { throw error }
    guard count != NSNotFound else { return 0 }
    return count

That should probably look something like this:

    var count: Int = NSNotFound
    do {
        count = try context.countForFetchRequest(fetchReqeust)
    }
    catch let error {
        throw error
    }
    guard count != NSNotFound else { return 0 }
    return count

Thank you and cheers!
Peter

Add support for OS X

Documents directory is coupled into CoreDataStack and would need to be more flexible to support OS X.

Create stack synchronously

Is it possible to create the stack synchronously? I create it in app delegate and need to use it before any controller is created. Is it possible?

Add support for TVOS

Maybe this will work with TVOS as it is, but the cocoa pods spec currently just says os x

Complete README

  • Add notes on the considerations of different stack types:
    • performance
    • parent MOC gotchas from #7
    • propagating changes
  • How to use the stack
  • License
  • Carthage notes
  • Sample Project Notes
  • When to use newBatchOperationContext

Can't run app in simulator with BNRCoreDataStack in Objective-C project, LaunchServicesError

Question

Creating a cocoapods library, that uses the pod BNRCoreDataStack. The project that I'm working on is an Objective-C project, the CoreDataStack library imports successfully and builds, but fails to install onto the Simulator (archiving and installing through iTunes works fine).

Note:
It only builds after making CoreDataStack inherit from NSObject and adding @objc(CoreDataStack) before the class, also commenting out privateQueueContext.persistentStoreCoordinator = persistentStoreCoordinator line in private init(modelName: String, bundle: NSBundle, persistentStoreCoordinator: NSPersistentStoreCoordinator, storeType: StoreType) because Use of 'self' in property access 'privateQueueContext' before super.init initializes self. Commented it out because I just wanted it to build first, ask questions later. Don't know Swift that well to fix this properly, maybe suggestions?

Expected behavior

The build should install onto the simulator and run fine

Actual behavior

I get the error The operation couldn't be completed. (LaunchServicesError error0.), console shows:
14/07/16 11:00:46,497 com.apple.CoreSimulator.CoreSimulatorService[336]: Error Domain=LaunchServicesError Code=0 "(null)" UserInfo={Error=PackageInspectionFailed, ErrorDescription=Failed to load Info.plist from bundle at path /Users/<redacted>/Library/Developer/CoreSimulator/Devices/906E713E-095D-458D-914A-2A3873723F0A/data/Library/Caches/com.apple.mobile.installd.staging/temp.UiQK9u/extracted/Payload/<redacted>.app/Frameworks/BNRCoreDataStack.framework}

Have tried to reboot, delete derived data, clean build. Inspected the BNRCoreDataStack.framework in the .ipa after archiving, the Info.plist file seems to exist there.

If someone could shine some light on me why this is happening, that would be really great.

Consolidate CoreDataStack to a single class

After profiling the performance trade offs of a nested managed object context stack and a shared persistent store stack (see #7 (comment)) I do not see the value of maintaining two separate stacks.

Instead the NestedContextStack will be the only stack maintained and part of this repo.

For long running batch imports there will be an API added to the nested context stack that will vend the user an NSManagedObjectContext with its very own persistent store coordinator that only shares the store file with the NestedContextStack. This is the recommend method from Apple for this type of import operation.

Fetched result controller in background does not inform delegate.

If I create a new FetchedResultsController with context a newBackgroundWorkerMOC then only fetchedResultsControllerDidPerformFetch is called from the delegate but the fetchedResultsControllerWillChangeContent, fetchedResultsControllerDidChangeContent, didChangeObject, etc are not called.

The newBackgroundWorkerMOC is stored in a member variable and the saves and updates of managed objects are taking place in this managed object context. Still, the fetched results controller delegate is not called.

Reset sql stack

I'm using resetSQLiteStore method but when I run any context save after that it crashes saying that there's no persistent coordinator present. Calling resetSQLiteStore and then creating a new stack fixes the problem.

Any ideas?

Merge changes from newBatchOperationContext

I'm using a batchOperationContext to import a big data set. It works but I don't know why objects from one entity are saved on disk but not on memory. I'm trying to re-fetch from disk but can't make it work.

Right now the only thing that works is creating a new batchOperationContext and fetching the entity there but this seems to be overkill.

Any ideas? How are changes from batchOperationContext merged into main context? Any way to reset main context and re-fetch from disk?

Unique Constraint

For some reason I can't get the iOS 9 Core Data update for Unique Constraints to work in CoreDataStack? Is there a trick to this? I have seen articles saying to do this you need to change the policy to MergeByPropertyObjectTrumpMergePolicyType is this something that needs to be updated in the class?

How many of the parent context gotchas from this article still apply?

Article: http://benedictcohen.co.uk/blog/archives/308

Mentioned:

  • Weirdness about temporary vs permanent object IDs
  • -awakeFromInsert breaking doc contract and being called multiple times as changes propagate upwards
  • Caching up the parent context tree that can cause child contexts to fetch outdated values
  • Merge policy ignored during upward propagation

I'm specifically curious about contrasting the recommendation to have main queue -> PSC with private queue worker contexts hooked up to main queue context only as needed, vs the main -> private -> PSC stack recommended in this repo. What are the dis/advantages and tradeoffs between the two?

Issue compiling project with BNRCoreDataStack using Xcode 8 - Swift 2.3

Question

When I attempt to compile a project with the BNRCoreDataStack pod from the Swift 2.3 branch (Xcode 8), I receive an "undefined symbols for architecture [arm64]" linker error regarding the CoreDataModelable class initiation method. Any clues as to why this might be occurring?

Output

Undefined symbols for architecture arm64: "(extension in BNRCoreDataStack):BNRCoreDataStack.CoreDataModelable<A where A: __ObjC.NSManagedObject, A: BNRCoreDataStack.CoreDataModelable>.init (managedObjectContext : __ObjC.NSManagedObjectContext) -> A", referenced from: Smartech.Battery.init (information : SmartechBluetooth.BatteryInformation, name : Swift.String, insertIntoManagedObjectContext : __ObjC.NSManagedObjectContext) -> Smartech.Battery in Battery.o ld: symbol(s) not found for architecture arm64

Use Private and Main instead of Confinement for thread confinement stack

Idea here is that the context type here: https://github.com/bignerdranch/sms-ios-mac-data-storage/blob/master/projects/CoreDataSMS/CoreDataSMS/CoreDataStack.swift#L135 can be NSMainQueueConcurrencyType

and the context type here https://github.com/bignerdranch/sms-ios-mac-data-storage/blob/master/projects/CoreDataSMS/CoreDataSMS/CoreDataStack.swift#L152 can be NSPrivateQueueConcurrencyType

This class will still follow the older pattern of not having parent/child context relationships but with this change there is no need to return a tuple of MOC/dispatch_queues and the contexts can take advantage of performBlock and performBlockAndWait calls.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.