Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save At Position #105

Open
vishaldeshai opened this issue Sep 2, 2017 · 11 comments
Open

Save At Position #105

vishaldeshai opened this issue Sep 2, 2017 · 11 comments

Comments

@vishaldeshai
Copy link

Hello,

Can we save Object at first location.

I would like store/insert object at first position is it possible??

thanks in advance.

@dimazen
Copy link
Contributor

dimazen commented Sep 2, 2017

Hello. What do you mean by "first position"? Sorting?

@vishaldeshai
Copy link
Author

First we are getting array and that array sorted and i have stored inside coredata.

but after that i am inserting new recored inside coredata. after that that record i am getting in last position but i would like to get that record at first position..

@dimazen
Copy link
Contributor

dimazen commented Sep 2, 2017

Are you inserting objects as a part of mapping or manually?

@vishaldeshai
Copy link
Author

vishaldeshai commented Sep 2, 2017

mapping like

[MagicalRecord saveWithBlock:^(NSManagedObjectContext * _Nonnull localContext) {
                    arr = [FEMDeserializer collectionFromRepresentation:[dict objectForKey:@"data"] mapping:[_LeadStatusList defaultMapping] context:localContext];
                } completion:^(BOOL contextDidSave, NSError * _Nullable error) {
                    [self.view makeToast:dict[@"message"]];
                    [self.navigationController popViewControllerAnimated:YES];
                }];

@dimazen
Copy link
Contributor

dimazen commented Sep 2, 2017

Are you talking about root object order or it is a relationship?

@vishaldeshai
Copy link
Author

Order

@dimazen
Copy link
Contributor

dimazen commented Sep 2, 2017

I meant is it an order of the root object or an order of the relationship's object

@vishaldeshai
Copy link
Author

relationship object.

@dimazen
Copy link
Contributor

dimazen commented Sep 2, 2017

In this case you should create your own assignment policy that will manage order in a way that you need. See Assignment Policy description. Also take a look at the implementation of the FEMAssignmentPolicyCollectionReplace to get an idea of how it works.

@vishaldeshai
Copy link
Author

Can you explain me how assignment policy works with replacing particular object???

@dimazen
Copy link
Contributor

dimazen commented Sep 5, 2017

Sorry, I was busy.
Sure, here is an explanation:

Lets say that we're mapping a response for an object Object that has a relationship children with values A, B, C. Response contains same Object but with the relationship values C, D. Resulting relationship should looks like C, D, while A and B should b removed.
Type of the collection that holds both relationships depends on the property type that holds that relationship. For our example lets assume that property is of NSSet type as the default for the CoreData's to-many relationships.

Therefore legend looks like this:

  • context.sourceRelationshipValue - corresponds to a collection with A, B, C. NSSet.
  • context.sourceRelationshipValue - corresponds to a collection with C, D. NSSet.

Here is the code with explanations:

FEMAssignmentPolicy FEMAssignmentPolicyCollectionReplace = ^id(FEMRelationshipAssignmentContext *context) {
    // There is no reason to run complex logic in case previous relationship value was nil (i.e. no A, B, C)
    // In this case we're just returning target value. "Target" means the one that I'd like to have for my Object
    if (!context.sourceRelationshipValue) return context.targetRelationshipValue;

    // This is another corner case when we're ensuring that backend has responded with something. Otherwise we're just returning previous value of the relationship and skip complex logic (i.e. keeping `children` at `A, B, C` values.
    if (context.targetRelationshipValue) {
        // This is an internal check, because FEM maintains its own protocol for common collections like NSArray, NSSet, NSOrderedSet (and mutable counterparts) that knows how to perform a replace. Search for a FEMExcludableCollection for more info. 
        NSCAssert(
            [context.sourceRelationshipValue conformsToProtocol:@protocol(FEMExcludableCollection)],
            @"Collection %@ should support protocol %@",
            NSStringFromClass([context.targetRelationshipValue class]),
            NSStringFromProtocol(@protocol(FEMExcludableCollection))
        );
        
        // As I mentioned above, FEM knows how to replace contents of one collection by another one. 
        // For a replacement algorithm looks as follows: find a "delta" between previous collection and a new one (all of the objects that are not presented in the targetRelationshipValue) and delete them 
        // Then simply return targetValue. 
        id objectsToDelete = [(id <FEMExcludableCollection>)context.sourceRelationshipValue collectionByExcludingObjects:context.targetRelationshipValue];
        for (id object in objectsToDelete) {
            [context deleteRelationshipObject:object];
        }
    } else {
        for (id object in context.sourceRelationshipValue) {
            [context deleteRelationshipObject:object];
        }
    }

    return context.targetRelationshipValue;
};

Now going back to your question about how to alway prepend your objects in the beginning of the relationship:

If this is not a replacement, then:

  • Declare your relationship as an ordered one (should be NSOrderedSet)
  • Declare your custom merge policy with a following logic
    • Handle corner cases like no sourceRelationshipValue or targetRelationshipValue
    • When both values presented: assert that both have type of the NSOrderedSet
    • You can make a mutable copy of the sourceRelationshipValue
    • Iterate over new values from targetRelationshipValue and run - [resultingMutableOredereSet insertObject:newObject atIndex:0]

Few comments: this doesn't handle complex cases when target relationship value contains new and old values in a mixed order. Therefore values like this [New, New, Old, New] can not be handled correctly and will be inserted into the resulting site in the following order [New, New, New, Old].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants