nofelmahmood / seam Goto Github PK
View Code? Open in Web Editor NEWSeamless CloudKit Sync with CoreData
Home Page: https://medium.com/@Nofel/reason-why-cloudkit-cannot-be-ignored-9c7806d76230
License: MIT License
Seamless CloudKit Sync with CoreData
Home Page: https://medium.com/@Nofel/reason-why-cloudkit-cannot-be-ignored-9c7806d76230
License: MIT License
Created a new branch for Swift 2.0
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 runs in an infinite loop, consumes more and more memory, until it finally crashes.
Steps to reproduce:
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.
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!
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.
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?
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.
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?
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.
Are many-to-many relationships supported as well? Or only one-to-many?
Example:
or
Would that be a problem?
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.
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 :(
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
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.
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.
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
This library looks awesome. :) I had a few questions:
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.
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)
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.
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.
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?
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?
My Podfile can't find it, and this page gives a 404 error: https://github.com/CocoaPods/Specs/tree/master/Specs/Seam
What am I missing?
When I fixed all errors in Xcode 9.3 with SeamDemo. but app crashed and print out "Unsupported store type."
Support for TVOS framework would be great, especially because on TVOS Core Data is not guaranteed to be persistent.
This code works the first time though when I run it a second time on the line:
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. :)
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.
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
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)?
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.