Giter Club home page Giter Club logo

coredatastack's Issues

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.

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?

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

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.

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?

"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).

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.

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.

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!

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?

(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()
}

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.

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

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.

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?

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.

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.

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

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?

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.

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?

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?

Add support for TVOS

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

Add support for OS X

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

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

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

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.

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.

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?

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.