<commit_before>A project to be used as the starting point for a new iOS project.

This project uses Cocoapods.

## First steps
    cd to TSBoilerplate
    pod install
    sudo cp App/Model/CoreDataModel/MogenTemplate/mogenerator /usr/bin
    open TSBoilerplate.xcworkspace

## Includes:
* TSNetworking
* Mogenerator (Arc and NSCoding support for model files)
* Thanks to [Tyrone](https://github.com/tyrone-sudeium) for his guidance on Commands

## Data persistance:
When you want to change the data model, as in, add new entities, or change properties of existing ones, make the change in the Model.xcdatamodel file (like you would for a core data app), change the scheme to "Generate Data Model" and build the project. That will instigate mogenerator to make the change and your data model objects in App/Model/ModelObjects will be updated (or added).

The source files will be generated in App/Model/ModelObjects/ - you will need to drag these into the project after the entity is first created (they will simply update in place thereafter if you made changes to that model object in the .xcdatamodel).

When you want to add a new entity, make sure you set the data type to that entity's name. I.e.

![data model](http://i.imgur.com/8seiyZQ.png)

## Networking: 
TSNetworking - <a href="https://github.com/timsawtell/TSNetworking" target="_blank">https://github.com/timsawtell/TSNetworking</a>

## Commands:
The commands subsystem is broken up into synchronous and asynchronous command which are executed by TSCommandRunner.
Commands are the way of having your controllers tell "the system" to do something and don't get bogged down with the business logic. As a general rule, anything can READ from the Model, however only COMMANDS can change the model. 
Your view controller will get the user's data, for example a name, and set that on a command. It will then run a command to update a model object with that data. This allows decoupling of view controllers to model objects.

Example usage for Synchronous

    GroupCommand *groupCommand = [GroupCommand new];
    groupCommand.groupName = kGroupName;
    groupCommand.saveModel = YES; // at the end of the execute method, save the model.
    [[TSCommandRunner sharedCommandRunner] executeSynchronousCommand:groupCommand];

or Asynchronous

    MemberDisplayCommand *memberDisplayCommand = [MemberDisplayCommand new];
    memberDisplayCommand.group = [Model sharedModel].group;
    memberDisplayCommand.commandCompletionBlock = ^ (NSError *error) {
        DLog(@"Your first completion block!");
        DLog(@"Erorr says: %@", [error localizedDescription]);
    };
    [[TSCommandRunner sharedCommandRunner] executeAsynchronousCommand:memberDisplayCommand];

an Asynchronous Webservice command

    TwitterCommand *twitterCommand = [TwitterCommand new];
    twitterCommand.screenName = kTwitterScreenName;
    twitterCommand.includeRetweets = YES;
    twitterCommand.includeEntities = NO;
    twitterCommand.tweetCount = kTweetCount;
    twitterCommand.twitterCommandCompletionBlock = ^ (NSError *error) {
        if (error != nil) {
            DLog(@":( Erorr says: %@", [error localizedDescription]);
        } else {
            /* we don't know what's happened, but we trust that the model is updated. 
            The programmer doesn't need to handle the tweet results, the command has already done that.
            you would usually call something like [self.tableView reloadData] here */
            for (Tweet *tweet in [Model sharedModel].tweets) {
                DLog(@"%@ - %@", tweet.user.name, tweet.text);
            }
        }
    };
    [[TSCommandRunner sharedCommandRunner] executeAsynchronousCommand:twitterCommand];

## License
MIT License as per the LICENSE file and http://www.opensource.org/licenses/MIT<commit_msg>new readme<commit_after>A project to be used as the starting point for a new iOS project.

This project uses Cocoapods.

## First steps
    cd to cloned directory
    pod install
    sudo cp App/Model/CoreDataModel/MogenTemplate/mogenerator /usr/bin
    open the .xcworkspace

## Includes:
* TSNetworking
* Mogenerator (Arc and NSCoding support for model files)

## Data persistance:
The app uses an archived root object as the data persistence mechanism. The data model lives in memory from app launch. The data model is designed using the standard Core Data editor, however the app does not use NSManagedObjects. The Mogenerator tool will build classes for you based on the templated in the MogenTemplate directory.

When you want to change the data model, as in, add new entities, or change properties of existing ones, make the change in the Model.xcdatamodel file (like you would for a core data app), change the scheme to "Generate Data Model" and build the project. That will instigate mogenerator to make the change and your data model objects in App/Model/ModelObjects will be updated (or added).

The source files will be generated in App/Model/ModelObjects/ - you will need to drag these into the project after the entity is first created (they will simply update in place thereafter if you made changes to that model object in the .xcdatamodel).

When you want to add a new entity, make sure you set the data type to that entity's name. I.e.

![data model](http://i.imgur.com/8seiyZQ.png)

## Networking: 
[TSNetworking](https://github.com/timsawtell/TSNetworking) library.
This project uses Builder classes to create model objects from the JSON data returned from the API.
A typical scenario

                                            ------- results ----------
                                            |                        |
                                            v                        |
    View Controller -> Command Center -> Command (Networking Task)  -|
                                            |
                                             --> Builder (to create model objects)            
                                          
                                           

## Business Logic
The app uses the concept of Commands to be self contained classes that execute one specific use case. The commands can be run synchronously (just subclass the Command class) or asynchronously (subclass the AsynchronousCommand class). The different between them is the thread that they run on. Synchronous commands run on the main thread, so when you call them in your view controllers or in Command Center they will execute before the next line of code starts. Asynchronous commands on the other hand are passed to a background queue and they will eventually execute on another thread, which means that they can't have any UI changes in the execute method. 

To perform UI changes after the command has finished, add the code to that command's completionBlock property. All networking use cases ("get customer details", "submit payment" etc.) are asynchronous, you need the app to do something when the data is fetched from the server.

## MVC and how it's used in this project
Model.m is the central data model instance, it is the data store, and it is used as the single source of truth. You won't find View Controllers owning business objects in this project.

View Controllers _NEVER_ change model objects. This is a self imposed rule to avoid what I usually find on other projects, your data is updated by some other unknown controller and it's very difficult to find out who did it.

CommandCenter.m is where you issue your use cases.

View Controller -> Command Center -> Command (which updates the model) 

or 

View Controller -> Command Center (which updates the model).

in this paradigm there are only two places that a model object can be updated, in a command or in CommandCenter.

View Controllers read data directly from the model, or through an Accessor (if business logic needs to be applied to a data structure, i.e. sorting).
{'fraction_non_alphanumeric': 0.059375792945952806, 'fraction_numerical': 0.0002537427048972342, 'mean_word_length': 3.231347289318304, 'pattern_counts': {'":': 1, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 4, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1302626', 'n_tokens_mistral': 1955, 'n_tokens_neox': 1873, 'n_words': 990}