GithubHelp home page GithubHelp logo

nofelmahmood / seam Goto Github PK

View Code? Open in Web Editor NEW
672.0 31.0 65.0 2.95 MB

Seamless CloudKit Sync with CoreData

Home Page: https://medium.com/@Nofel/reason-why-cloudkit-cannot-be-ignored-9c7806d76230

License: MIT License

Swift 98.51% Ruby 0.41% Objective-C 1.08%
swift cloudkit sync carthage coredata-model

seam's People

Contributors

nofelmahmood 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

seam's Issues

Demo App Crashes

When you run the app I receive an error in the CKIncrementalStore.swift for function triggerSync() on below line:

'''
...
if error == nil
{
print("Sync Performed Successfully")
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in

// CRASHES ON THIS LINE EVERY TIME NSNotificationCenter.defaultCenter().postNotificationName(CKSIncrementalStoreDidFinishSyncOperationNotification, object: self)

            })
        }

...
'''

When I comment that line out the app does not crash but syncing stops.

I also needed to add to the TableView a cell otherwise code crashes.

Thank you.

SeamDemo infinite loop

SeamDemo runs in an infinite loop, consumes more and more memory, until it finally crashes.

Steps to reproduce:

  1. Download the current master branch.
  2. Change the Bundle Identifier in the SeamDemo project to something unique.
  3. Add a custom iCloud container and select it as the only one to use.
  4. Run the app either in the simulator or on an device.

I expect the app to normally run, and not to sync anything until I create a first record. I use the latest iOS 9, OS X 10.11 & Xcode 7 betas. Currently I just get the following output until the demo app crashes:

Sync Started
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
…

On inspecting ~/Library/Mobile Documents/ I don’t see the corresponding subfolder created by Apple’s frameworks which is normally present when you use Core Data + iCloud and I don’t see any data in the CloudKit Dashboard.

Repo status and CKContainer question

Is this repo still being updated? I see the branch Improve-Store (and forks) have been updated recently, but these branches are quite different from the latest release. 0.6 had some major errors for me, so I had to use Improve-Store. My issue is that I cannot define a custom CKContainer with an id different from the bundle_id. I've looked through the entire codebase for a while now and can't figure out how to change from the default container. Any help would be appreciated, thanks!

Need to handle iCloud account changes

If the user switches iCloud accounts their local data will no longer match the server's data. In that case you would need initiate a complete two-way sync of all records stored both locally and on the server. In iOS 9 there is a notification you can subscribe to so you know when the account change happens, but in iOS 8 I believe the only option is to record the user's iCloud ID and poll it for changes periodically (like at startup?). Alternatively, providing a button to manually initiate a complete sync might be acceptable.

Push configuration

I am trying to figure out whether app should register for remote notifications or implementing didReceiveRemoteNotification should be sufficient enough.

To be fair I am not much familiar with CloudKit, and looking at both README and demo app I see inconsistencies.

Demo app does not register for remote notifications nor handles remote notifications. Is this somehow intentional?

How does one configure Seam to receive live updates from CloudKit?

Default data

Is it possible to start an application with some default data? I know how to do it with a sql based coredata app but no idea how to do it with a cloudkit based coredata.

Taking CoreData operations off main thread

Hello guys!

According to best practices, it is better to do Coredata related operations in the background, not to cause any possible performance drops, or UI blocks.

I feel like you are doing some database access in the main thread:

Class:StoreRelationshipTests function:testAddingTagToAlreadyAddedTask is calling deleteAll which is doing database operations.

Don't you think it would be better to take these operations off the main thread?

'Cannot retrieve referenceObject from an objectID that was not created by this store’ error

I have an object called Client, which have a NSSet of Projects and the Project object have a Client reference.

I can create a client and edit it as long as it dosen’t have any projects.
But when I create a project and give the project a client. I can’t edit the client anymore.
Is gives me this error: 'Cannot retrieve referenceObject from an objectID that was not created by this store’

                managedContext.refreshObject(client, mergeChanges: false)
                for pro in client.projects {
                    managedContext.refreshObject(pro as! Project, mergeChanges: false)
                }

If I call the refresh method show above I dont get the earlier error but this:

Error Domain=NSCocoaErrorDomain Code=1550 "The operation couldn’t be completed. (Cocoa error 1550.)" UserInfo=0x1740ec100 {NSValidationErrorObject=<TimeTarget.Client: 0x1700bbfc0> (entity: Client; id: 0x170424720 x-coredata://EC349C9D-E6A5-4297-9B96-778618D88B0E-7984-000002915A9F1799/Client/pBA63AEE6-5C27-47A3-86B0-57FD57A8A1EE ; data: {
billable = 0;
color = 0;
defaultHourRate = 0;
name = Huhu4;
projects = (
"0xd000000000040002 x-coredata://8B9AF010-A46F-4A5B-872B-A87B38C291C5/Project/p1"
);
}), NSValidationErrorValue=Relationship 'projects' on managed object (0x1700bbfc0) <TimeTarget.Client: 0x1700bbfc0> (entity: Client; id: 0x170424720 x-coredata://EC349C9D-E6A5-4297-9B96-778618D88B0E-7984-000002915A9F1799/Client/pBA63AEE6-5C27-47A3-86B0-57FD57A8A1EE ; data: {
billable = 0;
color = 0;
defaultHourRate = 0;
name = Huhu4;
projects = (
"0xd000000000040002 x-coredata://8B9AF010-A46F-4A5B-872B-A87B38C291C5/Project/p1"
);
}) with objects {(
<TimeTarget.Project: 0x1700de060> (entity: Project; id: 0xd000000000040002 x-coredata://8B9AF010-A46F-4A5B-872B-A87B38C291C5/Project/p1 ; data: {
billable = nil;
"cks_LocalStore_Attribute_ChangeType" = 0;
"cks_LocalStore_Attribute_EncodedValues" = <62706c69 73743030 d4010203 04050649 4a582476 65727369 6f6e5824 6f626a65 63747359 24617263 68697665 72542474 6f70>;
"cks_LocalStore_Attribute_RecordID" = "5C8A7045-6398-441F-B3D1-46A30523C4D7";
client = "0xd000000000040000 x-coredata://8B9AF010-A46F-4A5B-872B-A87B38C291C5/Client/p1";
color = 0;
defaultHourRate = 0;
name = Nu;
})
)}, NSValidationErrorKey=projects, NSLocalizedDescription=The operation couldn’t be completed. (Cocoa error 1550.)}

Everything works if I dont use CKSIncrementalStore and only core data local on iPhone.

My core data model:
screen shot 2015-07-19 at 00 31 52

Many-to-many relations

Are many-to-many relationships supported as well? Or only one-to-many?

Example:

  • A user can be in many groups
  • A group can hold many users

or

  • An item has many tags and
  • A tag has many items

Would that be a problem?

SeamStoreType undeclared identifier

I have added Seam to my ObjectiveC project using CocoaPods, and successfully declared a property for the store:

@property (nonatomic, readonly) SMStore *seamStore;

I then use the following code to add it to my NSPersistentStoreCoordinator:

_store = [_coordinator addPersistentStoreWithType: SeamStoreType configuration: nil URL: storeURL options: options error: &error];

Which gives me an undeclared identifier error for SeamStoreType.

What do I need to do for my code to recognize SeamStoreType?

Object not saved correctly

Object not saved correctly.

My steps:
First I create a client it works fine.
Then I create a project but the project is not saved correctly, it appears until I close and open the app. Then its gone.
The project is not synced to the cloud kit either. Thats an fail I haven’t seen before. It works local with coredata and it doesn't give me any error.
So It can be hard to debug :(

Crash in executeInResponseToFetchRequest

I see crash in executeInResponseToFetchRequest where it expects NSManagedObject but it gets NSManagedObjectID instead...

I am bridging MagicalRecord with Seam so I assume this may be the cause of me doing something wrong... or maybe not.

This is my current implementation which is simply uses Seam store, everything else is left intact:

https://gist.github.com/pronebird/1a6db53e6f75e7baf109

Log:

Not coming
Sync Performed
Sync Performed Successfully
Could not cast value of type '_NSCoreDataTaggedObjectID' (0x10784df60) to 'NSManagedObject' (0x10784e9b0).

Therefore in this context we get crash:

    // MARK : Fetch Request
    func executeInResponseToFetchRequest(fetchRequest:NSFetchRequest,context:NSManagedObjectContext) throws ->NSArray {
        let resultsFromLocalStore = try self.backingMOC.executeFetchRequest(fetchRequest)
        if resultsFromLocalStore.count > 0 {
            return resultsFromLocalStore.map({(result)->NSManagedObject in
                let result = result as! NSManagedObject <-- CRASH

Tutorial request

There is too much going on in the app.

I tried to recreate the app from scratch but its not working. I think I have missed to add something.

If you could post tutorial on medium then it would be great.

Thanks either way for this project.

Package Seam as a Carthage Framework

I was wondering if it would be possible to have Seam set up as a Carthage framework, in addition to CocoaPods. I'm not sure what the process for doing so is, so I'm not sure if this is a monumental undertaking or not, but it would be a nice addition (and, for me, match the rest of my dependancies).

I'm excited to try Seam out, in place of my own super-hacky CoreData to CloudKit sync solution.

Works in iOS 8.1, requires 9.0

I have currently tested seam in iOS 8.1 and it seems to be working fine, but the minimum deployment target is iOS 9.0 which messes up my cocoapods setup. For the sake of compatibility I'm requesting the deployment target be changed to ios 8.1 at minimum (or iOS if it is tested as working). Thanks

How does Seam handle migration?

This library looks awesome. :) I had a few questions:

  • How does Seam handle two different model versions on two different devices, both trying to use the same records/keys?
  • How does Seam handle the user downloading the app, sending data to the cloud, then downloading a newer version of the app at a later date, with an updated model version?

NSData Attribute Sync Crash

I've got my nsmanagedobject subclass which has also an nsdata attribute to store an image. That's not always needed and so when i set it to nil Seam Crashes.
Look at the screenshot below..
Hope in a fix..
Best regards
schermata 2015-08-26 alle 12 01 55

Need to read from Notification Collection

When a push notification is received indicating changes have occurred it is necessary to read from the Notification Collection see if any notifications were dropped. Since push is "best effort" delivery and only the last notification is delivered while offline it is possible for notifications to be missed. This was covered in one of the videos from WWDC 2014. I'm not sure what the API call is for doing this.

Swift 3.0 / App crashing

I have forked this project to my Bitbucket account, and have successfully got it compiling in Xcode 8, beta 6. The only problem is that the demo app is crashing on startup (I have the iCloud configurations set up on Apple's side).

Here is the crash: (SMStore.swift)

screen shot 2016-09-04 at 4 30 03 pm

I am not familiar enough with the codebase to fully understand what is going on. I could submit a pull request with my Swift 3.0 code, if that would help?

Thank you in advance for any assistance. I would really like to use this library in my application.

Unacceptable type of value for to-one relationship

When I try to edit and TimeEntry i get this error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for to-one relationship: property = "project"; desired type = TimeTarget.Project; given type = TimeTarget.Project; value = (entity: Project; id: 0x174426160 x-coredata://6B81EA38-15B7-4C85-ADB5-6640EE31DF5D-9088-000002BEECC9720D/Project/p254230CF-A9CD-4CAD-B47F-19DFBA054081 ; data: {
billable = 0;
"cks_LocalStore_Attribute_ChangeType" = nil;
"cks_LocalStore_Attribute_EncodedValues" = nil;
"cks_LocalStore_Attribute_RecordID" = nil;
client = "0x174239480 x-coredata://6B81EA38-15B7-4C85-ADB5-6640EE31DF5D-9088-000002BEECC9720D/Client/p686DBB54-ACC5-4313-8369-2DF9B8003E4B";
color = 0;
defaultHourRate = 0;
name = Kk;
timeEntries = "";
}).'

And same when I try an edit an Project:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for to-one relationship: property = "client"; desired type = TimeTarget.Client; given type = TimeTarget.Client; value = (entity: Client; id: 0x174621ac0 x-coredata://17D56827-FF19-4DDD-8161-E4C930BC4398-9102-000002BF85C10C71/Client/p686DBB54-ACC5-4313-8369-2DF9B8003E4B ; data: {
billable = 0;
color = 0;
defaultHourRate = 0;
name = Klkj;
projects = (
"0x170432e00 x-coredata://17D56827-FF19-4DDD-8161-E4C930BC4398-9102-000002BF85C10C71/Project/p9E6EA418-FF51-492C-84ED-575A76659490",
"0x170432e20 x-coredata://17D56827-FF19-4DDD-8161-E4C930BC4398-9102-000002BF85C10C71/Project/p254230CF-A9CD-4CAD-B47F-19DFBA054081"
);
}).'

The client I can edit / save without problem. It first happens when I have closed the app and reopened the app again.

Model:
1f1e4122-2db4-11e5-9773-68432c8cc9c9

Zone.swift: Operations created, but not added to NSOperationQueue

In Zone.swift::subscriptionExistsOnServer an CKFetchSubscriptionsOperation operation is created, but never added to NSOperationQueue!

And also in Zone.swift::createSubscription(completionBlock: the CKFetchSubscriptionsOperation operation is created, but never added to the NSOperationQueue!

Is this intended behaviour?

CloudKit Public database support

Personally I don't really see the need for private database support since we already have iCloud Core Data storage which does the same thing. Public on the other hand introduces many opportunities. Can't you use queries for higher change tag or modified time to enable you to do the sync without the requirement for custom zones and change requests?

TVOS support

Support for TVOS framework would be great, especially because on TVOS Core Data is not guaranteed to be persistent.

unexpectedly found nil while unwrapping an Optional value

This code works the first time though when I run it a second time on the line:

  • result.name = "(result.name! ) ClientChange" I get the error
    (unexpectedly found nil while unwrapping an Optional value)

let moc = CoreDataStack.defaultStack.managedObjectContext

    let task: Task = NSEntityDescription.insertNewObjectForEntityForName("Task", inManagedObjectContext: moc) as! Task
    task.name = "HElaLuia"

    let cycling: Task = NSEntityDescription.insertNewObjectForEntityForName("Task", inManagedObjectContext: moc) as! Task
    cycling.name = "Foolish"

    let biking: Task = NSEntityDescription.insertNewObjectForEntityForName("Task", inManagedObjectContext: moc) as! Task
    biking.name = "Acting"

    let outdoorTasksTag = NSEntityDescription.insertNewObjectForEntityForName("Tag", inManagedObjectContext: moc) as! Tag
    outdoorTasksTag.name = "AnotherTag"

    let newTasksTag = NSEntityDescription.insertNewObjectForEntityForName("Tag", inManagedObjectContext: moc) as! Tag
    newTasksTag.name = "Just Another Tag"
    newTasksTag.task = biking

    outdoorTasksTag.task = cycling


    if moc.hasChanges
    {
        do
        {
            try moc.save()
        }
        catch let error as NSError?
        {
            print("Error Occured \(error!)", terminator: "\n")
        }
    }
    CoreDataStack.defaultStack.seamStore!.triggerSync()



            do
            {
                try moc.save()
            }
            catch
            {
                print("Error thrown baby", terminator: "\n")
            }



            let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: "Task")
            do
            {
                let results = try moc.executeFetchRequest(fetchRequest)
                for result in results as! [Task]
                {


                    result.name = "\(result.name! ) ClientChange"
                    NSLog ("result.name  %@ \n",result);
                }
                try moc.save()
            }
            catch
            {

            }

Also can you give a demo of how to use the cloudKit functionality.
Thank you in Advance. :)

Crash because of NSMutableOrderedSet

Hello,

When using this library I get the following error message:
Could not cast value of type '_NSFaultingMutableOrderedSet' (0x19fe9c2e8) to 'NSSet' (0x19fe879e8).
It occurs in SMStore.swift - setRelationshipValuesForBackingObject: because of this line:

let relationshipValue: Set<NSObject> = sourceObject.valueForKey(relationship.name) as! Set<NSObject>

I can't find my mistake since I already got the inverse relations set up as you are describing in the README. I hope you can give me a hint why this does not work.

Here is my xcdatamodeld setup :
bildschirmfoto 2015-12-28 um 18 32 51
bildschirmfoto 2015-12-28 um 18 32 29
bildschirmfoto 2015-12-28 um 18 32 40
bildschirmfoto 2015-12-28 um 18 32 15

Getting NSInternalInconsistencyException

Hi Nofel

I seem to have everything setup but when I launch my app I am getting the following exception:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Entity already contains a property named sm_LocalStore_RecordID.'

It looks like it is happening in:

func addExtraBackingStoreAttributes(toEntity entity: NSEntityDescription)

line:

 entity.properties.append(recordIDAttribute)

Have you any ideas why this may be happening?

Just a little bit more background as my setup wasn't too straightforward.

I'm using the framework in an Objective C app - and struggled to get it to link using CocoaPods. So for now I've just copied in your Swift code files and accessing the Swift via #import "ProjectName-Swift.h"

This is how I am adding the Store Type.

 smStore = [coordinator addPersistentStoreWithType:SMStore.type configuration:nil URL:storeUrl options:nil error:nil];

(I had to use SMStore.type directly as I couldn't get at SeamStoreType)

Any help or pointers would be much appreciated.
Thank you

Manual attaching of CKAssets to a record

It is best practice to store big blobs of data (such as images) on the filesystem. An interface to add CKAssets to records would be desirable.

Since the CKSRecordContext is holding all records, the user could manually attach CKAssets to records before calling save() on it. Maybe even an automated option might be possible (e.g. if there is a file path stored in an attribute, a CKAsset could be created)?

WatchOS2 support!

With the current implementation there is no way to sync with the Apple watch app. It would be great if we found a way to do it. As off WatchOS2, there are two stores now, so this library would be in great demand if it works with the watch app

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.