3lvis / sync Goto Github PK
View Code? Open in Web Editor NEWJSON to Core Data and back. Swift Core Data Sync.
License: MIT License
JSON to Core Data and back. Swift Core Data Sync.
License: MIT License
I updated from 1.0.8 to the latest 1.0.11 and noticed relationships are no longer being sync'd; they show nil. I tried 1.0.10 with the same results, then 1.0.9 which works. Did something change between 1.0.9 and 1.0.10 that I'm not aware of that requires an update on my end? I checked the README and didn't see anything...
Unfortunately, the latest version of Sync is not compatible with the use_frameworks!
option of cocoa pods.
import "DATAStack.h"
(in NSArray+Sync.h
) needs to be changed to import <DATAStack/DATAStack.h>
for this to work (which would fail without the option).
Any ideas on how to make this work? The option is needed to include Pods written in swift, so not using the option is not an option I fear :)
I've been wondering what if we changed the API to something more simple.
// [Sync changes:notes entityName:@"Notes" dataStack:self.dataStack completion:nil];
+ (void)changes:(NSArray *)changes
entityName:(NSString *)entityName
dataStack:(DATAStack *)dataStack
completion:(void (^)(NSError *error))completion;
// [Sync processChanges:notes usingEntityName:@"Notes" dataStack:self.dataStack completion:nil];
+ (void)processChanges:(NSArray *)changes
usingEntityName:(NSString *)entityName
dataStack:(DATAStack *)dataStack
completion:(void (^)(NSError *error))completion;
Hi guys,
Really like this pod so far, nice work! I was wondering if foreign key relationship is supported. Say you have this json:
{ "project":
{ "id": 12345,
"name": "My Project",
"category": 1,
"teamMemberIDs": [1, 2, 3, 4]
}
}
where the category would be a relation to a category and the teamMemberIDs a relation to multiple users.
When you tap in the link 'see another example' it takes you to a 404 page, the link should be:
https://github.com/hyperoslo/Sync/blob/master/Examples/AppNet/Example/Networking.m#L41
Now it's: https://github.com/hyperoslo/Sync/blob/master/Example/Example/Networking.m#L41
Main endpoint:
https://news.layervault.com/?format=json
I have a nested JSON ex:
{
"name":"Huy",
"contact": {
"skype":"huyle",
"email":"[email protected]"
}
How I can flat them into 1 ManagedObject? Ex:
User
hyper.primaryKey
in addition to hyper.remoteKey
.parent
relationship is needed for recursive entitiesWould be great if we had better logging of what happens when Sync is performed, this would help for example when debugging issues.
Are there any plans to have this support relationships and nested entities by recursing through the JSON?
Assuming I'm building a Twitter client. I only want to fetch new tweets and save them. Old tweets not presented during a syncing should remain the same. I know I can use predicate to exclude all existing tweets to prevent them from deleted. But is there an option to not delete unpresented tweets?
If this is not a feature Sync would target, is there any alternative library to do so?
Thanks!
This is just an idea:
I think, having the access to the proper NSManagedObjectContext is enough for sync engine.
If there are special 'query' helpers needed, just create context extension class.
My goal is to map JSON which looks like this..
[
{
"id": "1",
"a": {
"b": {
"name": "hello"
}
}
}
]
.. to an NSManagedObject that looks like this:
@property (nonatomic, retain) NSString * remoteID;
@property (nonatomic, retain) NSString * name;
.. So that I can sync it using your library (which is great by the way).
There's nothing useful at the 'a' and 'b' levels, so I don't really want to create relationships for them.
I tried putting:
hyper.remoteKey = a.b.name
.. into the xcdatamodel file, but no luck.
Any ideas? I suppose I could pre-process the NSDictionary before I pass it into Sync?
Would it be possible to add an attribute to an entity and based on the value the changes are not synced?
This is very useful in an app where you want to support offline usage. For example: If the user is makes changes to an object but the app has no internet connection, his changes are saved in core data. Now when he does a pull to refresh his changes will be overwritten. If there would be such an attribute the syncing for this object would be skipped.
Similar to this a modified attribute would be useful, if the modified attribute doesn't differ from the value in the JSON syncing should be skipped improving performance.
Hey,
do you plan to support custom transformations? Say I have a color encoded in a string using the #ARGB format (e.g. #FF00FF00 for green) and i want to persist it as a UIColor in a transformable property in my managed object. Is something like this already supported?
br
denis
Hello,
I need some help for creating the Data Model based on this JSON :
{
"posts": [
{
"id": "",
"title": "",
"author": {
"id": "",
"name": ""
},
"related": {
"id": "",
"name": ""
},
"original_post": {
"id": "",
"title": "",
"author": {
"id": "",
"name": ""
},
"related": { ... },
"original_post": { ... }
}
}]
}
Thanks a lot !
Is seams like it crashing now
I was thinking today, all the classes of the networking part are pretty similar if you use Apple's networking, so I was thinking in adding a method that let you just type Sync from that URL into this entityName, so the user, in the same ViewController for example, can just type:
[Sync changesFromURL:@"Whatever"
inEntityNamed:@"Story"
dataStack:dataStack
completion:^(NSError *error) {
}];
Then we would do all the requests and stuff! :)
I had issues with Many to Many relationships. I found the problem happens at this line:
childPredicate = [NSPredicate predicateWithFormat:@"ANY %K.%K = %@", relationshipName, destinationLocalKey, [children valueForKey:destinationRemoteKey]];
I noticed that we generate a predicate that points to the child but since it has relationshipName in it, it ends up being invalid predicate.
The predicate that that line generates is
ANY fulfillers.xid = (<some xids>)
But it does it on fulfillers Model.
Here is a JSON sample:
{
"xid":"mstaff_F58dVBTsXznvMpCPmpQgyV",
"user":{
"full_name":"Ashkan Nasseri",
"email":"[email protected]",
"phone":"###-###-####",
"xid":"usr_8YQhMfiLvXEg6TaD7YKyjL",
"photo_inventory":true
},
"image":"a.jpg",
"image_xs":"s.jpg",
"fulfillers":[
{
"xid":"ffr_AkAHQegYkrobp5xc2ySc5D",
"name":"New York"
},
{
"xid":"ffr_n5eGjfHQRqKr4tAfL7RNi9",
"name":"Chicago"
}
],
"current_vehicle":{
"xid":"vhc_test",
"name":"Test"
}
}
I fixed the problem by removing %k. and relationshipName from the predicate generation, everything works fine for me now but it breaks testCustomPrimaryKey.
id
and remoteID
or just
note`Hello, is it possible to export my core data model into JSON file using Sync? Or at least something like that?
I have a json structure that looks something like this:
{
"name": "...",
"id": "...",
"foo": {
"bar": "..."
}
}
foo
is a seperate entity with no primary key. The NSFetchRequest
crashes in safeObjectInContext:entityName:remoteID:
due to nil comparison in the NSPredicate
: https://github.com/hyperoslo/Sync/blob/master/Source/Sync.m#L147
When an attribute of an entity has both hyper.isPrimaryKey and hyper.remoteKey defined, an incorrect value is used for fetching existing objects from the database. -[NSEntityDescription(Sync) sync_remoteKey] doesn't take the hyper.remoteKey property into account.
For example, in my use case, I have a local property "imageId" and a remote JSON property for the primary key of "ImageId". I have "ImageId" stored under hyper.remoteKey for this property. sync_remoteKey then takes the value from sync_localKey, which is the correct "ImageId" string and pushes it through hyp_remoteString which changes it to "image_id", which isn't present in the JSON. As a result, no remote IDs are located, no local objects can be fetched, and updates and deletions never happen.
I was thinking on making a screencast on how to make a Designer News client under 10 minutes using Sync.
Swift
+ Core Data
)Podfile
(Sync
+ DATASource
+ Networking
), run pod install
DATASource
Sync
from the ViewController
What do you guys think?
I'm testing the sync functionality and all seems to work fine in my initial data request (viewDidLoad). I fetch the JSON from the server, pass it to Sync and my CoreData gets updated nicely.
However, when I make a change server side a few seconds later and do a refresh I can see the modified JSON coming in but Sync doesn't seem to sync the changes to the database?
Any idea what this might be?
When a primary key is missing Sync
just crashes with a localKey parameter not found
message.
Ideally the error should say "Local primary key not found, Sync uses remoteID
by default but if you have another local primary key make sure to mark it with "hyper.isPrimaryKey" : "YES"
in your attribute's user info.
NSString *localKey = [entity sync_localKey];
NSParameterAssert(localKey);
NSString *remoteKey = [entity sync_remoteKey];
NSParameterAssert(remoteKey);
Crash when mapping many to many relationship in NSManagedObject+Sync#sync_processToManyRelationship:usingDictionary:andParent:dataStack : 116
, uses remote relationship name on entity, for ex, should be likedPosts instead of liked_posts.
I had Sync working with version 1.0.1, then updated to 1.0.2 today and now my app crashes with the below. I reverted back to 1.0.1, and it works again.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSDictionary initWithObjects:forKeys:]: count of objects (4) differs from count of keys (0)'
*** First throw call stack:
(
0 CoreFoundation 0x0000000103907c65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000105472bb7 objc_exception_throw + 45
2 CoreFoundation 0x0000000103850210 -[NSDate isEqual:] + 0
3 CoreFoundation 0x00000001038628e4 +[NSDictionary dictionaryWithObjects:forKeys:] + 52
4 DATAFilter 0x000000010337033e +[DATAFilter changes:inEntityNamed:localKey:remoteKey:context:predicate:inserted:updated:] + 702
5 Sync 0x00000001033a29cc +[Sync changes:inEntityNamed:predicate:parent:inContext:dataStack:completion:] + 1484
6 Sync 0x00000001033a3ef2 -[NSManagedObject(SyncPrivate) sync_processToManyRelationship:usingDictionary:andParent:dataStack:] + 1986
7 Sync 0x00000001033a335e -[NSManagedObject(SyncPrivate) sync_processRelationshipsUsingDictionary:andParent:dataStack:error:] + 558
8 Sync 0x00000001033a45b5 -[NSManagedObject(SyncPrivate) sync_processToOneRelationship:usingDictionary:andParent:dataStack:error:] + 1365
9 Sync 0x00000001033a35fd -[NSManagedObject(SyncPrivate) sync_processRelationshipsUsingDictionary:andParent:dataStack:error:] + 1229
10 Sync 0x00000001033a2cbc __78+[Sync changes:inEntityNamed:predicate:parent:inContext:dataStack:completion:]_block_invoke + 172
11 DATAFilter 0x0000000103370816 +[DATAFilter changes:inEntityNamed:localKey:remoteKey:context:predicate:inserted:updated:] + 1942
12 Sync 0x00000001033a29cc +[Sync changes:inEntityNamed:predicate:parent:inContext:dataStack:completion:] + 1484
13 Sync 0x00000001033a1c69 __61+[Sync changes:inEntityNamed:predicate:dataStack:completion:]_block_invoke + 121
14 DATAStack 0x000000010337d76a __43-[DATAStack performInNewBackgroundContext:]_block_invoke + 58
15 CoreData 0x0000000103469a79 developerSubmittedBlockToNSManagedObjectContextPerform + 201
16 libdispatch.dylib 0x0000000106939614 _dispatch_client_callout + 8
17 libdispatch.dylib 0x00000001069206a7 _dispatch_queue_drain + 2176
18 libdispatch.dylib 0x000000010691fcc0 _dispatch_queue_invoke + 235
19 libdispatch.dylib 0x00000001069233b9 _dispatch_root_queue_drain + 1359
20 libdispatch.dylib 0x0000000106924b17 _dispatch_worker_thread3 + 111
21 libsystem_pthread.dylib 0x0000000106ca6637 _pthread_wqthread + 729
22 libsystem_pthread.dylib 0x0000000106ca440d start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Hi there! It's me again :)
I definitely want to write your documentation, but right now my code starts falling apart. So here is the problem:
I have the following CoreData Model set up:
Now I want to add a picture locally by doing the following (I am using old code that I wrote when I did not use Sync yet):
So I basically get an image, that I want to add to the Photo Items
func gotimage(image:UIImage){
let col = GrocliCollectionManager.sharedInstance.getDefaultWriteCollection()
let uid = createUniqueFileUIDForCollection(col)
//create subdir if needed
GrocliFileHandler.sharedInstance.createFolderForCollection(col)
let filename = (col.remoteID + "/" + uid + ".jpg")
let ok = self.writeImage(image, to: filename)
if(ok){
let photoDic = [
"id" : uid,
"collectionId" : col.remoteID,
"fileurl" : filename,
"isBought" : false
]
var photo = GrocliCollectionManager.sharedInstance.createNonExistingPhoto(photoDic)
if(photo != nil){
photo?.isDownloaded = true
photo?.isUploaded = false
col.photos = col.photos.setByAddingObject(photo!)
photo?.collectionId = col.remoteID
//println(GrocliFileHandler.sharedInstance.createFileName(photo!))
var error:NSError?
//photo?.managedObjectContext?.save(&error)
(UIApplication.sharedApplication().delegate as! AppDelegate).dataStack?.persistWithCompletion({ () -> Void in
if(GrocliLoginHandler.sharedInstance.loggedIn as Bool){
GrocliAPIHandler.sharedInstance.uploadPicture(photo!)
}
})
if(error != nil){
GrocliErrorHandler.handleCoreDataSaveError(error!)
}
}
}
}
The createNonExistingPhoto(dict:NSdictionary)
function basically just take a JSON array and creates a CoreDAta PhotoItem on the AppDelegate's Datastack's mainContext
.
You see, that I tried different version to save and tested those. They work. Now the uploading takes place in the APIHandler's uploadPicture
. When the uploading was successful, I get a server response which contains the new ID for the photo which I need to set. I do this in the completionHandler
if let success: AnyObject = jsonDictionary!["success"]{
if(success as! Bool){
println(jsonDictionary)
if let payload = jsonDictionary!["payload"] as? NSDictionary{
println(payload)
let file = payload["file"] as! NSDictionary
photo.remoteID = file["id"] as! String
photo.isUploaded = true
}
var err:NSError?
//photo.managedObjectContext?.save(&err)
(UIApplication.sharedApplication().delegate as! AppDelegate).dataStack!.persistWithCompletion({ () -> Void in
if(err != nil){
GrocliErrorHandler.handleCoreDataSaveError(err!)
}else{
//self.getCollections()
}
})
}
}
For example I got a file Dictionary that looked likes this
file = { fileurl = "dd432a4135acb80e/D4CE12234E9A4AFEB5FD.jpg"; id = 1a309871d7618851; isBought = 0; };
Again this does work. I can successfully save this photo. Now I use a NSFetchedResultsController on the Photos that I set up like this:
func photoItemFetchRequest()->NSFetchRequest{
var request = NSFetchRequest(entityName: "GrocliPhotoItem")
request.predicate = NSPredicate(format: "deletedOnServer == NO && collection != nil", argumentArray: ["isDownloaded","deletedOnServer", "collection"])
// TODO Gekaufte nicht anzeigen
var sortDesc = NSSortDescriptor(key: "collection.remoteID", ascending: true)
var ownColDesc = NSSortDescriptor(key: "collection.ownCollection", ascending: false)
//var boughtSortDes = NSSortDescriptor(key: "isBought", ascending: true)
request.sortDescriptors = [ownColDesc,sortDesc]
return request
}
func getFetchedResultsController() -> NSFetchedResultsController {
//TODO cache löschen wegtun
NSFetchedResultsController.deleteCacheWithName("collectionCache")
var fetchedResultsController = NSFetchedResultsController(fetchRequest: photoItemFetchRequest(), managedObjectContext: self.appDelegate!.dataStack!.mainContext, sectionNameKeyPath: "collection.remoteID", cacheName: "collectionCache")
return fetchedResultsController
}
Like I said: everything seems to be working fine. If I now pull all images from the server I get the following json Response
[{ collectionId = dd432a4135acb80e; fileurl = "dd432a4135acb80e/D4CE12234E9A4AFEB5FD.jpg"; id = 1a309871d7618851; isBought = 0; }, { collectionId = dd432a4135acb80e; fileurl = "dd432a4135acb80e/E2A376033B294FC5A005.jpg"; id = 7b298fbb38ba3a65; isBought = 0; }, { collectionId = dd432a4135acb80e; fileurl = "dd432a4135acb80e/CB26B84FC46241CEA84C.jpg"; id = ae6c424bd4665b9c; isBought = 0; }, { collectionId = dd432a4135acb80e; fileurl = "dd432a4135acb80e/D3113522D516495A9F5F.jpg"; id = 719b416f0cc3fa70; isBought = 0; }]
The ID and the filePath of the first item actually exist in the database since I save the file Dictionary (see above). I use sync in the following way
let firstItem = photoArray.first
if (firstItem != nil && firstItem!["id"] != nil) {
let id = firstItem!["collectionId"] as? String // find out which collection to update
if(id != nil){
if let collection = self.getCollection(id: id!){
println(photoArray)
Sync.changes(photoArray, inEntityNamed: "GrocliPhotoItem", parent: collection, dataStack: self.appDelegate!.dataStack!, completion: { (error) -> Void in
if(error == nil){
GrocliFileDownloader.sharedInstance.downloadAllFilesForCollection(collection)
}else{
GrocliErrorHandler.handleFilesSyncError(error)
}
})
}
}
}
This seems to work, too.
Nonetheless the fetchedResultsController fails instantly afterwards with
erminating app due to uncaught exception 'NSRangeException', reason: '*** -[_PFArray objectAtIndex:]: index (3) beyond bounds (3)'
Is it possible, that Sync first updates and adds items and deletes items in a second save afterwards? Then the fetchedResultsController would call the controllerDidChangeContent function right after the first save and it would report more items that it really has when it saves all the deletes right afterwards. When it is then asked for the items that don't exist anymore, it crashes. Does that make sense? The other question then is: Why is the picture not updated? I suggest, that it does not delete/update properly, because if it is the very first item, my fetchedResultsController contains the same item two times. Thanks in advance! I hope everything is going well.
Best regards,
Pascal
Do you have any plan to support Realm database?
At the moment we are using id
for a primary key but that's not the case for all the backends.
The idea is to support something like the custom mappers =>https://github.com/hyperoslo/NSManagedObject-HYPPropertyMapper/releases/tag/2.9
So adding a @{@"sync.primary_key" : @"YES"}
would treat the selected attribute as a primary key
Linked to => Foreverland/SYNCPropertyMapper#51
Add a section explaining how to Sync some elements while excluding others. Related to #62.
You can exclude a few elements to be synced by providing a NSPredicate.
So for example you could say "Sync Users excluding offline ones".
Here your Users that have theisOffline
flag set toYES
will be skipped.
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isOffline = %@", @NO];
[Sync changes:JSON
inEntityNamed:@"User"
predicate:predicate
dataStack:dataStack
completion:^{
// New objects have been inserted
// Existing objects have been updated
// And not found objects have been deleted
}];
Hi there!
I am sorry for bothering you but I tried to get this running for two hours right now and I seem to be stuck.
I am using the following setup in CoreData
and I have an [NSDictionary] array (that I formed out of a json response).
(I don't get to choose the json response and I get the same error using the json response instead of the array so I figured that I could go on in using the array.)
[{
id = 224f02078c4278c2;
name = "Pascal Blunk";
ownCollection = 0;
owner = {
id = 32492cc981632817;
name = "Pascal Blunk";
};
}, {
id = e393ed8b0c1368fc;
name = pascal7;
ownCollection = 1;
owner = {
id = 739b7ba364ddd874;
name = pascal7;
};
users = (
739b7ba364ddd874
);
}]
Every item in that array is a specific collection. The owner property is an object of type User. Users is an array of user_ids. I used to fill in the CoreData myself but now I want to switch to your powerful code. When primitively calling Sync.changes with the array given I get the following stack trace
2015-06-22 22:54:19.615 Grocli[11780:3544854] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0x7ff821c5dcb0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key id.'
*** First throw call stack:
(
0 CoreFoundation 0x000000010dd31c65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010d9cabb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010dd318a9 -[NSException raise] + 9
3 Foundation 0x000000010d40582a -[NSObject(NSKeyValueCoding) valueForUndefinedKey:] + 226
4 Foundation 0x000000010d35eb23 -[NSObject(NSKeyValueCoding) valueForKey:] + 251
5 Foundation 0x000000010d35e914 -[NSArray(NSKeyValueCoding) valueForKey:] + 437
6 Grocli 0x000000010cd08bf7 -[NSManagedObject(Sync) sync_processToManyRelationship:usingDictionary:andParent:dataStack:] + 1095
7 Grocli 0x000000010cd083de -[NSManagedObject(Sync) sync_processRelationshipsUsingDictionary:andParent:dataStack:error:] + 606
8 Grocli 0x000000010cd0ac2c __78+[Sync changes:inEntityNamed:predicate:parent:inContext:dataStack:completion:]_block_invoke + 172
9 Grocli 0x000000010ccfdcc6 +[DATAFilter changes:inEntityNamed:localKey:remoteKey:context:predicate:inserted:updated:] + 1942
10 Grocli 0x000000010cd0a934 +[Sync changes:inEntityNamed:predicate:parent:inContext:dataStack:completion:] + 1748
11 Grocli 0x000000010cd09a99 __61+[Sync changes:inEntityNamed:predicate:dataStack:completion:]_block_invoke + 121
12 Grocli 0x000000010cd014ba __43-[DATAStack performInNewBackgroundContext:]_block_invoke + 58
13 CoreData 0x000000010cfd7a79 developerSubmittedBlockToNSManagedObjectContextPerform + 201
14 libdispatch.dylib 0x0000000110a7c614 _dispatch_client_callout + 8
15 libdispatch.dylib 0x0000000110a636a7 _dispatch_queue_drain + 2176
16 libdispatch.dylib 0x0000000110a62cc0 _dispatch_queue_invoke + 235
17 libdispatch.dylib 0x0000000110a663b9 _dispatch_root_queue_drain + 1359
18 libdispatch.dylib 0x0000000110a67b17 _dispatch_worker_thread3 + 111
19 libsystem_pthread.dylib 0x0000000110de9637 _pthread_wqthread + 729
20 libsystem_pthread.dylib 0x0000000110de740d start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException
I am not quite sure, but I would guess, that the code fails when it comes to handling the array 'users' since there is no 'id' field given. So I basically have two questions: a) Do you think that this is the problem and b) Can I somehow tell your code that it should handle all items in the users array as IDs?
I would like to be able to cancel Sync operation.
When I call sync It should probably return Sync Operation the would have a cancel method.
Sync *operation = [Sync changes:JSON
inEntityNamed:@"User"
predicate:predicate
dataStack:dataStack
completion:^{
//...
}];
[operation cancel];
Sync provides a predicate method to filter which methods would be synced for example providing a predicate for startTime > now
only should sync elements that start in the future and ignore all the other elements that don't apply to this predicate.
We should add more consistency in our Core Data User Info keys, taking some inspiration from mogenerator we could do something like this => https://github.com/rentzsch/mogenerator/wiki/Core-Data-User-Info-Keys#attribute-key-value-pairs
// Sync.h
static NSString * const SyncCustomPrimaryKey = @"sync.primary_key";
static NSString * const SyncCustomRemoteKey = @"hyper.remote.key";
// HYPPropertyMapper.h
static NSString * const HYPPropertyMapperCustomRemoteKey = @"mapper.remote.key";
// Sync.h
static NSString * const SyncCustomPrimaryKey = @"hyper.isPrimaryKey";
static NSString * const SyncCustomRemoteKey = @"hyper.remoteKey";
// HYPPropertyMapper.h
static NSString * const HYPPropertyMapperCustomRemoteKey = @"hyper.remoteKey";
Some JSON items don't provide an id
, for example a Comment in Designer News API
https://news.layervault.com/?format=json
Any ideas on what would be the best way to approach this?
Right now, we're saving the URL of the image, maybe someone wants to save all the image, for some user case, like doing a ProfileImage, and you don't want to network all the time.
I was thinking in a UserInfo key, hyper.saveDataImage
, or something like that.
I guess the best explanation would be, process the image if the user wants to.
I have a Model with many Relationship. In the JSON I have a simpler model without all relationship
When I Sync numbers, it crashes because trying to set Parent unit
property on Number (unit is relationship to OrganizationUnit, but I don't want to sync organisations here, just numbers)
JSON Example:
[{
"id": 1,
"number": 10.0,
"numberType": 0,
"children" : [
{
"id": 2,
"number": 11.0,
"numberType": 0
},
{
"id": 3,
"number": 12.0,
"numberType": 0,
}
]
}]
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for to-one relationship: property = "unit"; desired type = REMAOrganizationUnit; given type = REMANumber; value = <REMANumber: 0x7aeac650>
it has a relationship with name unit
that point to parent organization, but there is no organization in the JOSN and I don't want to process it
I noticed while attempting to integrate Sync into a separate project, that if I don't have either a remoteID property (and corresponding "id" property in the JSON) or hyper.isPrimaryKey specified for a property on that entity, that the app crashes with an EXC_BAD_ACCESS on line 148 of Sync.m. It appears that the issue is that both remoteID and localKey are nil. I then added an "id" property to every object in my JSON and a matching remoteID property to each entity in my model, and it works. Is this intentional? There are cases where a primary key isn't always desired for every entity.
In our service, we can have multiple markets, but these markets are retrieved individually and separately, not as one large request. I noticed that if I retrieve an initial market and insert it using Sync, then retrieve a subsequent (different) market and insert it, it removes the first market from Core Data, and so on, even if they have different remoteID
s. This is fine if you are feeding it one huge JSON with your entire model, but would it be possible to support use cases like ours, where you may be retrieving new entities separately and needing to add them into the existing Core Data model, instead of overwriting everything?
Right now we only have support for UITableView, right?
"Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray'"
I got this error on my first launch on every new test device
this is my coredata model, and i've set id as hyper.isPrimaryKey.
Can you please help me?
Thank you
Hi. Did you try to combine your project with MagicalRecord?
I see, that it closely integrated with DATAStack
and it seems, like quite bit different way to manage with Core Data, than Magical Record
implementation.
MR use simple method:
+ (void)setupCoreDataStack;
for initialisation of DataStack)
Is there any way to integrate Sync
with MagicalRecord
?
Sometimes JSON can look like the following, which is a dictionary with dynamic keys.
"inputConfiguration": {
"justAHint" : [ "a", "b" ],
"keyboardConfiguration": "telephone",
"someOtherConfiguration": { "this": "that", "here": "there"}
},
Or even a dictionary with a static key, but an array of objects (no keys):
"aliasLabels" : ["Option Three A", "Option Three B"]
These are obviously difficult to map into objects. Core Data allows storing Dictionaries and Arrays as a transformable attribute type. It would be great if Sync allowed storing a part of the JSON in this manner.
One way it could work, to use my inputConfiguration
example above, would be to create a corresponding Core Data attribute called inputConfiguration
with a transformable type, and defined as a dictionary in its entity's class definition. Then have another user info key/value pair, for instance hyper.isCollection
, which would tell Sync not to map that out into objects, but instead just store that part of the JSON in the inputConfiguration
attribute as a dictionary.
It could theoretically work the same way for the array of objects with no keys in my 2nd example. Normally Sync would see that and think it's a relationship to be mapped, but perhaps when it doesn't find a relationship named aliasLabels
in the Core Data model, it could then check for an attribute by that same name and if it has the hyper.isCollection
(or whatever) key/value pair, just store that piece of JSON as an array.
A separate (nicer, but more complex) idea I had for actually mapping this type of JSON out into objects, could go something like this:
For the array with no keys (to use my example again), you would still have your typical to-many relationship called aliasLabels
to another entity. The entity should have a single attribute (string in this case). Sync could either deduce from there only being one attribute that this must be the attribute to map the value to, or a new hyper.defaultValue
(or whatever) user info key/value pair could be used to indicate this is the attribute to map to.
The dictionary with dynamic keys would probably be a lot more difficult to map, since it could contain any number of objects. So it would have to be treated as a to-many relationship, and each of those key/value pairs as a separate entity. Then in those entities you would need at least 2 attributes; one to store the dynamic key, and another for the actual value. Then you would of course have to define a user info key/value pair for them, such as hyper.dynamicKey
and hyper.defaultValue
so Sync would know which to map into. That would work for dictionaries with dynamic keys where the objects are always the same, but unfortunately still wouldn't work with my example above, since those objects themselves can be anything. That's where being able to store the data as a dictionary/array would still be nice.
Sorry for the long post, but I really like this library and think having support for a broader type of potential JSON would make it even more useful.
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.