Giter Club home page Giter Club logo

geneticskit's Introduction

GeneticsKit

CI Status Version License Platform

Simple and flexible mapping for any object.

Basics

Let's say you're starting with a class:

@interface Person : NSObject

@property (copy, nonatomic) NSString *firstName;
@property (copy, nonatomic) NSString *lastName;
@property (strong, nonatomic) NSURL *avatarURL;

@end

Now let's say you've got some JSON:

{
    "first_name": "Harry",
    "last_name": "Potter",
    "avatars": ["http://...", "http://...", "http://..."]
}

Let's get started!

Create a genome

A genome is just an array of GNKGene objects. A gene represents the mapping of a single trait between two objects. So for our JSON:

NSArray *jsonGenome = @[GNKMakeGene(@"first_name", @selector(firstName)),
                        GNKMakeGene(@"last_name", @selector(lastName)),
                        GNKMakeGene(@"avatars[0]", @selector(avatarURL), [URLTransformer new])];

And we're done! GNKGene objects are initialized with a GNKSourceTrait, a GNKReceivingTrait, and an optional NSValueTransformer. The GNKMakeGene macro simplifies this by allowing you to provide one to three arguments and will attempt to convert them to the correct type. It's pretty smart and can take selectors and primitive numbers. No more having to type NSStringFromSelector(@selector(...)) just to add some compile-time safety.

Transfer traits

Now that we have our genome, we can use it to transfer values from our JSON onto our model:

NSDictionary *json = ...;
Person *person = [Person new];

[GNKLab transferTraitsFromSource:json receiver:person genome:jsonGenome options:0];

person.firstName; // "Harry"
person.lastName; // "Potter"
person.avatarURL; // "http://..."

Tada!

Find different traits

Now let's say we got some new JSON from our server:

{
    "first_name": "Harry",
    "last_name": "Porker",
    "avatars": [...]
}

For whatever reason, we only want to have one person instance, and only update it when we need to. We can easily find out whether the JSON has different values from our instance using our genome:

NSDictionary *newJSON = ...;

NSSet *differentGenes = [GNKLab findGenesWithDifferentTraitsFromSource:newJSON receiver:person genome:jsonGenome options:0];

differentGenes.count; // 1
differentGenes.anyObject; // "<GNKGene:...> first_name ==> firstName"

Now we know that only the firstName needs to be updated. In fact, we can just convert the different genes into an array and use that as a new genome!

Available traits and trait-convertibles

The driving force behind GeneticsKit are two protocols: GNKSourceTrait and GNKReceivngTrait. These two protocols make up the designated initializer for GNKGene. To mask some of the implementation drudgery, GeneticsKit provides the GNKTrait class cluster to provide some common traits.

Additionally, some Foundation classes have been extended to conform to the GNKSourceTraitConvertible and GNKReceivingTraitConvertible protocols.

Foundation class Protocols Description
NSString GNKSourceTraitConvertible, GNKReceivingTraitConvertible Converts the string into either a single index or key trait or a sequence of the two.
NSNumber GNKSourceTraitConvertible, GNKReceivingTraitConvertible Converts the number into an index trait.
NSIndexPath GNKSourceTraitConvertible, GNKReceivingTraitConvertible Converts the index path into a sequence of index traits.
NSArray GNKSourceTraitConvertible, GNKReceivingTraitConvertible Converts the array into a sequence of traits.
NSOrderedSet GNKSourceTraitConvertible, GNKReceivingTraitConvertible Converts the ordered set to a sequence of traits.
NSIndexSet GNKSourceTraitConvertible Converts the index set into an aggregate of index traits.
NSSet GNKSourceTraitConvertible Converts the set into an aggregate of traits.
NSNull GNKSourceTraitConvertible Equivalent to the identity trait.

Why to all

You may be wondering, why on earth do I need this library? For one, it's simple. Look how quickly we were able to make our JSON gneome. Two, it's very flexible. Because we've separated the mapping from the model class and the source type, if we suddenly discover that we need another JSON source that provides Person instances, we don't need to subclass Person, but instead just make a new genome! For example let's consider this new JSON source:

[
    "Harry", // The first name will always be index 0
    "Potter", // The last name will always be index 1
    [
        {"url": "https://..."},
        {...},
        {...}
    ] // The array of avatars will always be index 2
]

This JSON is horrible, but we can work with it if we need to:

NSArray *horribleGenome = @[GNKMakeGene(0, @selector(firstName)),
                            GNKMakeGene(1, @selector(lastName)),
                            GNKMakeGene(@"[2][0].url", @selector(avatarURL), [URLTransformer new])];

This has no impact on our jsonGenome because why should it?

GeneticsKit is also flexible because it doesn't require major changes to your architecture to implement. If you've made models in Core Data, you can keep them there. If you like to use raw NSMutableDictionary models, go ahead! As long as you've created a genome that is meaningful, it will work.

If you're not sold, or you think you need something more heavy duty, here are a few frameworks you can consider:

Installation

GeneticsKit is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod "GeneticsKit"

Author

Zach Radke, [email protected]

License

GeneticsKit is available under the MIT license. See the LICENSE file for more info.

geneticskit's People

Contributors

zradke avatar

Stargazers

 avatar

Watchers

 avatar

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.