{"id":13992714,"url":"https://github.com/mutualmobile/MMRecord","last_synced_at":"2025-07-22T16:31:40.518Z","repository":{"id":7628156,"uuid":"8987633","full_name":"mutualmobile/MMRecord","owner":"mutualmobile","description":"Seamless Web Service Integration and Core Data Model Population","archived":false,"fork":false,"pushed_at":"2017-01-10T20:09:25.000Z","size":2333,"stargazers_count":689,"open_issues_count":17,"forks_count":76,"subscribers_count":41,"default_branch":"master","last_synced_at":"2025-06-24T07:17:12.849Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mutualmobile.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-03-24T14:48:46.000Z","updated_at":"2025-03-17T12:18:11.000Z","dependencies_parsed_at":"2022-09-05T04:31:31.088Z","dependency_job_id":null,"html_url":"https://github.com/mutualmobile/MMRecord","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/mutualmobile/MMRecord","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mutualmobile%2FMMRecord","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mutualmobile%2FMMRecord/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mutualmobile%2FMMRecord/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mutualmobile%2FMMRecord/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mutualmobile","download_url":"https://codeload.github.com/mutualmobile/MMRecord/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mutualmobile%2FMMRecord/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266531090,"owners_count":23944042,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-09T14:02:06.137Z","updated_at":"2025-07-22T16:31:36.142Z","avatar_url":"https://github.com/mutualmobile.png","language":"Objective-C","funding_links":[],"categories":["Objective-C"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://www.github.com/mutualmobile/MMRecord/raw/gh-pages/Images/MMRecord-blog_banner.png\") alt=\"MMRecord Blog Banner\"/\u003e\n\u003c/p\u003e\n\nMMRecord is a block-based seamless web service integration library for iOS and Mac OS X. It leverages the [Core Data](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/CoreData_ObjC/_index.html) model configuration to automatically create and populate a complete object graph from an API response. It works with any networking library, is simple to setup, and includes many popular features that make working with web services even easier. Here's how to make a request for App.net Post records:\n\n\n```objective-c\nNSManagedObjectContext *context = [[MMDataManager sharedDataManager] managedObjectContext];\n\n[Post \n startPagedRequestWithURN:@\"stream/0/posts/stream/global\"\n data:nil\n context:context\n domain:self\n resultBlock:^(NSArray *posts, ADNPageManager *pageManager, BOOL *requestNextPage) {\n\t NSLog(@\"Posts: %@\", posts);\n }\n failureBlock:^(NSError *error) {\n\t NSLog(@\"%@\", error);\n }];\n```\n\nKeep reading to learn more about how to start using MMRecord in your project!\n\n## Getting Started\n\n- [Download MMRecord](https://github.com/mutualmobile/MMRecord/archive/master.zip) and try out the included example apps.\n- Continue reading the integration instructions below.\n- Check out the [documentation](http://mutualmobile.github.com/MMRecord/Documentation/) for all the rest of the details.\n- Review the [examples](https://github.com/mutualmobile/MMRecord#example-usage) below for inspiration on specific usage.\n- Read about MMRecord's support for [Swift](https://github.com/mutualmobile/MMRecord#swift-examples) and [Tweaks](https://github.com/mutualmobile/MMRecord#tweaks).\n- If you run into any issues, check out some useful [debugging](https://github.com/mutualmobile/MMRecord#debugging) tips.\n\n---\n##Installing MMRecord\n\u003cimg src=\"https://cocoapod-badges.herokuapp.com/v/MMRecord/badge.png\"/\u003e\u003cbr/\u003e\nYou can install MMRecord in your project by using [CocoaPods](https://github.com/cocoapods/cocoapods):\n\n```Ruby\npod 'MMRecord', '~\u003e 1.4.1'\n```\n\n## Overview\n\nMMRecord is designed to make it as easy and fast as possible to obtain native objects from a new web service request. It handles all of the fetching, creation, and population of NSManagedObjects for you in the background so that when you make a request, all you get back is the native objects that you can use immediately. No parsing required.\n\nThe library is architected to be as simple and lightweight as possible. Here's a breakdown of the core classes in MMRecord.\n\n\u003ctable\u003e\n  \u003ctr\u003e\u003cth colspan=\"2\" style=\"text-align:center;\"\u003eCore\u003c/th\u003e\u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"http://mutualmobile.github.com/MMRecord/Documentation/Classes/MMRecord.html\"\u003eMMRecord\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003e\n      A subclass of \u003ctt\u003eNSManagedObject\u003c/tt\u003e that defines the \u003ctt\u003eMMRecord\u003c/tt\u003e interface and initiates the object graph population process.\n      \n      \u003cul\u003e\n        \u003cli\u003eEntry point for making requests\u003c/li\u003e\n        \u003cli\u003eUses a registered \u003ctt\u003eMMServer\u003c/tt\u003e class for making requests\u003c/li\u003e\n        \u003cli\u003eInitiaties the population process using the \u003ctt\u003eMMRecordResponse\u003c/tt\u003e class\u003c/li\u003e\n\t\t\u003cli\u003eReturns objects via a block based interface\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"http://mutualmobile.github.com/MMRecord/Documentation/Classes/MMServer.html\"\u003eMMServer\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003e\n\t  An abstract class that defines the request interface used by \u003ctt\u003eMMRecord\u003c/tt\u003e.\n\t  \n      \u003cul\u003e\n        \u003cli\u003eDesigned to be subclassed\u003c/li\u003e\n        \u003cli\u003eSupports any networking framework, including local files and servers\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n  \n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://www.github.com/mutualmobile/MMRecord/raw/gh-pages/Images/MMRecord-architecture-diagram.png\") alt=\"MMRecord Architecture Diagram\"/\u003e\n\u003c/p\u003e\n\n\u003ctable\u003e\n  \u003ctr\u003e\u003cth colspan=\"2\" style=\"text-align:center;\"\u003ePopulation\u003c/th\u003e\u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"http://mutualmobile.github.com/MMRecord/Documentation/Classes/MMRecordResponse.html\"\u003eMMRecordResponse\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eA class that handles the process of turning a response into native \u003ctt\u003eMMRecord\u003c/tt\u003e objects.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"http://mutualmobile.github.com/MMRecord/Documentation/Classes/MMRecordProtoRecord.html\"\u003eMMRecordProtoRecord\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eA container class used as a placeholder for the object graph during the population process.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"http://mutualmobile.github.com/MMRecord/Documentation/Classes/MMRecordRepresentation.html\"\u003eMMRecordRepresentation\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eA class that defines the mapping between a dictionary and a Core Data \u003ctt\u003eNSEntityDescription\u003c/tt\u003e.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"http://mutualmobile.github.com/MMRecord/Documentation/Classes/MMRecordMarshaler.html\"\u003eMMRecordMarshaler\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eA class responsible for populating an instance of \u003ctt\u003eMMRecord\u003c/tt\u003e based on the \u003ctt\u003eMMRecordRepresentation\u003c/tt\u003e.\u003c/td\u003e\n  \u003c/tr\u003e\n\n  \u003ctr\u003e\u003cth colspan=\"2\" style=\"text-align:center;\"\u003ePagination\u003c/th\u003e\u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"http://mutualmobile.github.com/MMRecord/Documentation/Classes/MMServerPageManager.html\"\u003eMMServerPageManager\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eAn abstract class that defines the interface for handling pagination.\u003c/td\u003e\n  \u003c/tr\u003e\n  \n  \u003ctr\u003e\u003cth colspan=\"2\" style=\"text-align:center;\"\u003eCaching\u003c/th\u003e\u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"http://mutualmobile.github.com/MMRecord/Documentation/Classes/MMRecordCache.html\"\u003eMMRecordCache\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eA class that maps \u003ctt\u003eNSManagedObject\u003c/tt\u003e ObjectIDs to an \u003ctt\u003eNSCachedURLResponse\u003c/tt\u003e.\u003c/td\u003e\n  \u003c/tr\u003e\n  \n    \u003ctr\u003e\u003cth colspan=\"2\" style=\"text-align:center;\"\u003eDebugging\u003c/th\u003e\u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"http://mutualmobile.github.com/MMRecord/Documentation/Classes/MMRecordDebugger.html\"\u003eMMRecordDebugger\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eA class that manages \u003ctt\u003eNSError\u003c/tt\u003e objects to provide debugging feedback.\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://www.github.com/mutualmobile/MMRecord/raw/gh-pages/Images/MMRecord-parsing.png\") alt=\"MMRecord Population Architecture\"/\u003e\n\u003c/p\u003e\n\n\u003ctable\u003e\n  \u003ctr\u003e\u003cth colspan=\"2\" style=\"text-align:center;\"\u003eSubspecs\u003c/th\u003e\u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://github.com/mutualmobile/MMRecord/tree/master/Source/MMRecordAFServer\"\u003eAFServer\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eAn example \u003ctt\u003eMMServer\u003c/tt\u003e subclass that implements \u003ctt\u003eAFNetworking\u003c/tt\u003e 1.0.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://github.com/mutualmobile/MMRecord/tree/master/Source/AFMMRecordSessionManagerServer\"\u003eSessionManagerServer\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eAn example \u003ctt\u003eMMServer\u003c/tt\u003e subclass that implements \u003ctt\u003eAFNetworking\u003c/tt\u003e 2.0.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://github.com/mutualmobile/MMRecord/tree/master/Source/MMRecordJSONServer\"\u003eJSONServer\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eAn example \u003ctt\u003eMMServer\u003c/tt\u003e subclass that can read local JSON files.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://github.com/mutualmobile/MMRecord/tree/master/Source/MMRecordDynamicModel\"\u003eDynamicModel\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eA custom \u003ctt\u003eMMRecordRepresentation\u003c/tt\u003e and \u003ctt\u003eMMRecordMarshaler\u003c/tt\u003e subclass pair that stores the original object dictionary as a transformable attribute.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://github.com/mutualmobile/MMRecord/tree/master/Source/AFMMRecordResponseSerializer\"\u003eResponseSerializer\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eA custom \u003ctt\u003eAFHTTPResponseSerializer\u003c/tt\u003e that creates and returns \u003ctt\u003eMMRecord\u003c/tt\u003e instances in an \u003ctt\u003eAFNetworking\u003c/tt\u003e 2.0 success block.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://github.com/mutualmobile/MMRecord/tree/master/Source/FBMMRecordTweakModel\"\u003eTweakModel\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eAn \u003ctt\u003eMMRecord\u003c/tt\u003e subspec that implements support for Facebook Tweaks to tweak \u003ctt\u003eMMRecord\u003c/tt\u003e response handling behavior.\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Integration Guide\n\nMMRecord does require some basic setup before you can use it to make requests. This guide will go take you through the steps in that configuration process.\n\n### Server Class Configuration\n\nMMRecord requires a registered server class to make requests. The server class should know how to make a request to the API you are integrating with. The only requirement of a server implementation is that it return a response object (array or dictionary) that contains the objects you are requesting. A server might use [AFNetworking](https://github.com/AFNetworking/AFNetworking) to perform a GET request to a specific API. Or it might load and return local JSON files. There are two subspecs which provide pre-built servers that use AFNetworking and local JSON files. Generally speaking though, you are encouraged to implement your own server to talk to the API you are using.\n\nOnce you have defined your server class, you must register it with MMRecord:\n\n```objective-c\n[Post registerServerClass:[ADNServer class]];\n```\n\nNote that you can register different server classes on different subclasses of MMRecord.\n\n```objective-c\n[Tweet registerServerClass:[TWSocialServer class]];\n[User registerServerClass:[MMJSONServer class]];\n```\n\nThis is helpful if one endpoint you are working with is complete, but another is not, or is located on another API.\n\n#### AFNetworking\n\nWhile you are encouraged to create your own specific server subclass for your own integration, MMRecord does provide base server implementations as subspec examples for AFNetworking 1.0 and AFNetworking 2.0. You can consult the AFServer subspec for AFNetworking 1.0, or the AFMMRecordSessionManagerServer subspec for AFNetworking 2.0. You can check out the new AFNetworking 2.0 server in the [Foursquare example app](https://github.com/mutualmobile/MMRecord/tree/master/Examples/MMRecordFoursquare/MMRecordFoursquare).\n\nIn addition, we provide the AFMMRecordResponseSerializer subspec specially for AFNetworking 2.0. This response serializer can be used for AFNetworking 2.0 in order to provide parsed and populated MMRecord instances to you in an AFNetworking success block. For more information please check out this [blog post](http://mutualmobile.github.io/blog/2014/01/14/afnetworking-response-serialization-with-mmrecord-1-dot-2/) or view the example [below](https://github.com/mutualmobile/MMRecord/#afmmrecordresponseserializer).\n\n### MMRecord Subclass Implementation\n\nYou are required to override one method on your subclass of MMRecord in order to tell the parsing system where to locate the object(s) you wish to parse. This method returns a key path that specifies the location relative to the root of the response object. If your response object is an array, you can just return nil.\n\nIn an App.net request, all returned objects are located in an object called \"data\", so our subclass of \u003ctt\u003eMMRecord\u003c/tt\u003e will look like this:\n\n```objective-c\n@interface ADNRecord : MMRecord\n@end\n\nstatic NSDateFormatter *ADNRecordDateFormatter;\n\n@implementation ADNRecord\n\n+ (NSString *)keyPathForResponseObject {\n    return @\"data\";\n}\n\n+ (NSDateFormatter *)dateFormatter {\n    if (!ADNRecordDateFormatter) {\n        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];\n        [dateFormatter setDateFormat:@\"yyyy-MM-dd'T'HH:mm:ssZ\"]; // \"2012-11-21T03:57:39Z\"\n        ADNRecordDateFormatter = dateFormatter;\n    }\n    \n    return ADNRecordDateFormatter;\n}\n\n@end\n```\nThere are also some optional methods you may wish to implement on \u003ctt\u003eMMRecord\u003c/tt\u003e. One such method returns a date formatter configured for populating attributes of type Date. You can override this method to populate date attributes using a formatted date string. Unix number time stamp dates are supported by default.\n\nNote that these methods were implemented on a class called \u003ctt\u003eADNRecord\u003c/tt\u003e, which is a subclass of \u003ctt\u003eMMRecord\u003c/tt\u003e. Additional entities are subclasses of \u003ctt\u003eADNRecord\u003c/tt\u003e, and do not need to implement these methods themselves.\n\n### Model Configuration\n\nThe Core Data \u003ctt\u003eNSManagedObjectModel\u003c/tt\u003e is very useful. At a highlevel, the model is composed of a list of entities. Likewise, an API is typically composed of a list of endpoints. MMRecord takes advantage of this convention to map an entity representation to an endpoint representation in order to create native objects from an API response. \n\nMMRecord leverages the introspective properties of the Core Data model to decide how to parse a response. The class you start the request from is considered to be the root of the object graph. From there, MMRecord looks at that \u003ctt\u003eNSEntityDescription\u003c/tt\u003e's attributes and relationships and attempts to populate each of them from the given response object. That information is very helpful, because it makes population of most attributes very straightforward. Because of this, it's helpful if your data model entity representations maps very closely to your API endpoint response representations.\n\n#### Primary Key\n\nMMRecord works best if there is a way to uniquely identify records of a given entity type. That allows it to fetch the existing record (if it exists) and update it, rather than create a duplicate one. To designate the primary key for an entity, we leverage the entity's user info dictionary. Specify the name of the primary key property as the value, and \u003cb\u003eMMRecordEntityPrimaryAttributeKey\u003c/b\u003e as the key.\n\n![MMRecord Primary Key](https://www.github.com/mutualmobile/MMRecord/raw/gh-pages/Images/MMRecord-primary-key.png)\n\nNote that the primary key can be any property, which includes a relationship. If a relationship is used as the primary key, MMRecord will attempt to fetch the parent object and search for the associated object in the relationship.\n\n![MMRecord Relationship Primary Key](https://www.github.com/mutualmobile/MMRecord/raw/gh-pages/Images/MMRecord-relationship-primary-key.png)\n\nYou can also inject a primary key at population time if you know the key for a record which does not exist in the API response dictionary being used to populate the record. An example of this being used is [below](https://github.com/mutualmobile/MMRecord/#mmrecordoptions-and-primary-key-injection). This option is not intended to replace proper model configuration, but can be used for additional flexibility. One way you can consider using this option is by parsing the contents of the dictionary to create your own unique identifier for a given record.\n\n#### Alternate Property Names\n\nSometimes, you may need to define an alternate name for a property on one of your entities. This could be for a variety of reasons. Perhaps you don't like your Core Data property names to include underscores? Perhaps the API response changed, and you don't want to change your NSManagedObject property names. Or maybe the value of a property is actually inside of a sub-object, and you need to bring it up to root level. Well, that's what the \u003cb\u003eMMRecordAttributeAlternateNameKey\u003c/b\u003e is for. You can define this key on any attribute or relationship user info dictionary. The value of this key can be an alternate name, or alternate keyPath that will be used to locate the object for that property.\n\n![MMRecord Alternate Name Key](https://www.github.com/mutualmobile/MMRecord/raw/gh-pages/Images/MMRecord-alternate-name-key.png)\n\nFor reference, here's a truncated version of the App.net User object to illustrate how those configuration values were determined:\n\n```json\n{\n    \"id\": \"1\", // note this is a string\n    \"username\": \"johnappleseed\",\n    \"name\": \"John Appleseed\",\n    \"avatar_image\": {\n        \"height\": 512,\n        \"width\": 512,\n        \"url\": \"https://example.com/avatar_image.jpg\",\n        \"is_default\": false\n    },\n    \"cover_image\": {\n        \"width\": 320,\n        \"height\": 118,\n        \"url\": \"https://example.com/cover_image.jpg\",\n        \"is_default\": false\n    },\n\t\"counts\": {\n\t\t\"following\": 100,\n\t\t\"followers\": 200,\n        \"posts\": 24,\n        \"stars\": 76\n    }\n}\n```\n\n## Example Usage\nHere's a few examples of the various types of requests you can make with MMRecord. Notice that AFMMRecordResponseSerializer is a subspec of MMRecord.\n\n### Standard Request\n\n```objective-c\n+ (void)favoriteTweetsWithContext:(NSManagedObjectContext *)context\n                           domain:(id)domain\n                      resultBlock:(void (^)(NSArray *tweets))resultBlock\n                     failureBlock:(void (^)(NSError *))failureBlock {\n    [Tweet startRequestWithURN:@\"favorites/list.json\"\n                          data:nil\n                       context:context\n                        domain:self\n                   resultBlock:resultBlock\n                  failureBlock:failureBlock];\n}\n```\n\n### Paginated Request\n\n```objective-c\n@interface Post : ADNRecord\n+ (void)getStreamPostsWithContext:(NSManagedObjectContext *)context\n                           domain:(id)domain\n                      resultBlock:(void (^)(NSArray *posts, ADNPageManager *pageManager, BOOL *requestNextPage))resultBlock\n                     failureBlock:(void (^)(NSError *error))failureBlock;\n@end\n\n@implementation Post\n+ (void)getStreamPostsWithContext:(NSManagedObjectContext *)context\n                           domain:(id)domain\n                      resultBlock:(void (^)(NSArray *posts, ADNPageManager *pageManager, BOOL *requestNextPage))resultBlock\n                     failureBlock:(void (^)(NSError *error))failureBlock {\n    [self startPagedRequestWithURN:@\"stream/0/posts/stream/global\"\n                              data:nil\n                           context:context\n                            domain:self\n                       resultBlock:resultBlock\n                      failureBlock:failureBlock];\n}\n@end\n```\n\n### Batched Request\n\n```objective-c\n[Tweet startBatchedRequestsInExecutionBlock:^{\n    [Tweet\n     timelineTweetsWithContext:context\n     domain:self\n     resultBlock:^(NSArray *tweets, MMServerPageManager *pageManager, BOOL *requestNextPage) {\n         NSLog(@\"Timeline Request Complete\");\n     }\n     failureBlock:^(NSError *error) {\n         NSLog(@\"%@\", error);\n     }];\n    \n    [Tweet\n     favoriteTweetsWithContext:context\n     domain:self\n     resultBlock:^(NSArray *tweets, MMServerPageManager *pageManager, BOOL *requestNextPage) {\n         NSLog(@\"Favorites Request Complete\");\n     }\n     failureBlock:^(NSError *error) {\n         NSLog(@\"%@\", error);\n     }];\n} withCompletionBlock:^{\n    NSLog(@\"Request Complete\");\n}];\n```\n\n### Fetch First Request\n\n```objective-c\nNSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@\"User\"];\nNSPredicate *predicate = [NSPredicate predicateWithFormat:@\"SELF.name contains[c] %@\", name];\nNSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@\"name\" ascending:YES];\nfetchRequest.predicate = predicate;\nfetchRequest.sortDescriptors = @[sortDescriptor];\n\n[self\n startRequestWithURN:[NSString stringWithFormat:@\"stream/0/users/%@\", name]\n data:nil\n context:context\n domain:domain\n fetchRequest:fetchRequest\n customResponseBlock:nil resultBlock:^(NSArray *records, id customResponseObject, BOOL requestComplete) {\n     if (resultBlock != nil) {\n         resultBlock(records, requestComplete);\n     }\n }\n failureBlock:failureBlock];\n```\n\n### AFMMRecordResponseSerializer\n\n```objective-c\nMMFoursquareSessionManager *sessionManager = [MMFoursquareSessionManager sharedClient];\n    \nNSManagedObjectContext *context = [[MMDataManager sharedDataManager] managedObjectContext];\nAFHTTPResponseSerializer *HTTPResponseSerializer = [AFJSONResponseSerializer serializer];\n    \nAFMMRecordResponseSerializationMapper *mapper = [[AFMMRecordResponseSerializationMapper alloc] init];\n[mapper registerEntityName:@\"Venue\" forEndpointPathComponent:@\"venues/search?\"];\n    \nAFMMRecordResponseSerializer *serializer =\n    [AFMMRecordResponseSerializer serializerWithManagedObjectContext:context\n                                            responseObjectSerializer:HTTPResponseSerializer\n                                                        entityMapper:mapper];\n    \nsessionManager.responseSerializer = serializer;\n\n[[MMFoursquareSessionManager sharedClient]\n GET:@\"venues/search?ll=30.25,-97.75\"\n parameters:requestParameters\n success:^(NSURLSessionDataTask *task, id responseObject) {\n     NSArray *venues = responseObject;\n         \n     self.venues = venues;\n         \n     [self.tableView reloadData];\n } \n failure:failureBlock];\n```\n\n## MMRecordOptions Examples\n`MMRecordOptions` is a way to customize the behavior of a request. One of the ways you can use it is to specify blocks that apply to the following request after you specify a set of options. This allows you to do things like insert a new primary key for a record or specify orphan deletion behaviors.\n\n### Primary Key Injection\n\n```objective-c\nMMRecordOptions *options = [Post defaultOptions];\n    \noptions.entityPrimaryKeyInjectionBlock = ^id(NSEntityDescription *entity,\n                                             NSDictionary *dictionary,\n                                             MMRecordProtoRecord *parentProtoRecord) {\n    if ([[entity name] isEqualToString:@\"CoverImage\"]) {\n        if ([[parentProtoRecord.entity name] isEqualToString:@\"User\"]) {\n            if (parentProtoRecord.primaryKeyValue != nil) {\n                return parentProtoRecord.primaryKeyValue;\n            }\n        }\n    }\n    \n    return nil;\n};\n    \n[Post setOptions:options];\n\n[Post\n getStreamPostsWithContext:context\n domain:self\n resultBlock:^(NSArray *posts, ADNPageManager *pageManager, BOOL *requestNextPage) {\n    [self populatePostsTableWithPosts:posts];\n }\n failureBlock:failureBlock];\n```\n\n### Orphan Deletion\n\n```objective-c\nMMRecordOptions *options = [Tweet defaultOptions];\n\noptions.deleteOrphanedRecordBlock = ^(MMRecord *orphan,\n                                      NSArray *populatedRecords,\n                                      id responseObject,\n                                      BOOL *stop) {\n    Tweet *tweet = (Tweet *)orphan;\n        \n    if ([tweet isFavorite]) {\n        return NO;\n    }\n        \n    return YES;\n};\n\n[Tweet setOptions:options];\n    \n[Tweet\n timelineTweetsWithContext:context\n domain:self\n resultBlock:^(NSArray *tweets, MMServerPageManager *pageManager, BOOL *requestNextPage) {\n     self.tweets = tweets;\n     [self.tableView reloadData];\n }\n failureBlock:failureBlock];\n```\n\n## Swift Examples\nWhile MMRecord is implemented in Objective-C, you can also use the library from to build your model in Swift. The main thing you should be aware of when building your model in Swift is that entity managed object class names need to be fully namespaced. An example of that is below.\n  \n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://www.github.com/mutualmobile/MMRecord/raw/gh-pages/Images/MMRecord-swift.png\") alt=\"MMRecord Model Configuration for Swift\"/\u003e\n\u003c/p\u003e\n\nNote that MMRecordAtlassian is used as the namespace for the Issue class in Swift. This is because the default namespace is the product name for your project. Please be aware that using special characters or spaces in your product name may lead to issues here. Typically those characters get replaced by underscores in your namespace, but for best results, simply use a single word for your product name to avoid issues.\n\nYou should also remember to import MMRecord.h, and any of its subspecs you use, in your Objective-C Bridging Header. Then, you're ready to go building your MMRecord model in Swift!\n\nHere's a few examples of using MMRecord in Swift.\n\n### Swift MMRecord Subclass Implementation\n\n```swift\nimport CoreData\n\nclass Plan: ATLRecord {\n    @NSManaged var name: NSString\n    @NSManaged var id: NSString\n    \n    override class func keyPathForResponseObject() -\u003e String {\n        return \"plans.plan\"\n    }\n}\n```\n\n### Standard Swift Request\n\n```swift\nPlan.startRequestWithURN(\"/plans\",\n\tdata: nil,\n\tcontext: managedObjectContext,\n\tdomain: self,\n\tresultBlock: {records in\n\t\tvar results: [Plan] = records as [Plan]\n                \n\t\tself.plans = results\n\t\tself.tableView.reloadData()\n\t},\n\tfailureBlock: { error in\n            \n\t})\n```\n\n### Swift Request with MMRecordOptions\n\n```swift\nvar options = Issue.defaultOptions()\n\noptions.entityPrimaryKeyInjectionBlock = {(entity, dictionary, parentProtoRecord) -\u003e NSCopying in\n    let dict = dictionary as Dictionary\n    let key: AnyObject? = dict[\"id\"]\n    let returnKey = key as String\n    return returnKey\n}\n\noptions.recordPrePopulationBlock = { protoRecord in\n    let proto: MMRecordProtoRecord = protoRecord\n    let entity: NSEntityDescription = protoRecord.entity\n    \n    var dictionary: AnyObject! = proto.dictionary.mutableCopy()\n    var mutableDictionary: NSMutableDictionary = dictionary as NSMutableDictionary\n    var primaryKey: AnyObject! = \"\"\n    \n    if (entity.name == \"OutwardLink\") {\n        primaryKey = mutableDictionary.valueForKeyPath(\"outwardIssue.key\")\n    }\n    \n    if (entity.name == \"InwardLink\") {\n        primaryKey = mutableDictionary.valueForKeyPath(\"inwardIssue.key\")\n    }\n    \n    mutableDictionary.setValue(primaryKey, forKey: \"PrimaryKey\")\n    \n    proto.dictionary = mutableDictionary\n}\n\nIssue.setOptions(options)\n\nIssue.startRequestWithURN(\"/issue\",\n\tdata: nil,\n\tcontext: managedObjectContext,\n\tdomain: self,\n\tresultBlock: { records in\n   \t\tvar results: [Issue] = records as [Issue]\n    \t\n    \tself.results = results\n    \tself.tableView.reloadData()\n\t},\n\tfailureBlock: { error in\n    \n\t})\n```\n\n## Tweaks\n\nMMRecord also provides the TweakModel subspec that implements support for Facebook Tweaks. You can use Tweaks to modify most MMRecord parsing and population parameters. This can be useful if you're working on an app where the API is in flux and is still being actively developed. The UI for Tweaks will show you a list of MMRecord entities in your data model, the primary key for each entity, all of the keys used to populate various attributes, and the key path that points to instances of that entity in the data model. Here's how you use it.\n\n```objective-c\n#define FBMMRecordTweakModelDefine\n    [FBMMRecordTweakModel loadTweaksForManagedObjectModel:\n        [MMDataManager sharedDataManager].managedObjectModel];\n```\n\nThats all you need to enable Tweaks in your MMRecord project. As a best practice, you should only use the #define in Debug mode. \n\nAfter its setup, here's what the Tweaks UI looks like with MMRecord.\n\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://www.github.com/mutualmobile/MMRecord/raw/gh-pages/Images/MMRecord-tweaks.png\") alt=\"MMRecord Tweaks UI\"/\u003e\n\u003c/p\u003e\n\n## Debugging\n\n`MMRecordDebugger` is a class used by `MMRecord` to provide debugging information back to you about how your model is configured and how MMRecord is handling the response handed to it by your server class. You can use MMRecordDebugger to help resolve issues that may exist in your model configuration, or identify inconsistencies with your response format.\n\nMMRecord is designed to make it as fast and easy as possible to serialize managed objects from a web service. One of the goals of the library is to provide meaningful means of customization to support all sorts of response formats, while still maintaining an easy to use primary interface that does not require excessive configuration and setup. In most cases, the amount of configuration and customization required by a user of MMRecord will depend on how complex the response format of your web service is.\n\nWhen MMRecord encounters an error while handling a request it may take a few measures based on the severity of the error.\n\n- Assertions. In some cases, like if a managed object class being populated is not a subclass of MMRecord, an assertion will be thrown.\n- Logs. In many cases, MMRecord will log a message containing the error to the console. By default MMRecord will not actually print anything to the console, unless you specify a logging level manually. This is for security reasons.\n- Non-failure Errors. In some cases, MMRecord will create an `NSError` describing an issue, and associate it with the `MMRecordDebugger`. However, if the error isn't serious enough, the request will not fail.\n- Failure Errors. In several cases, MMRecord will create an `NSError` describing a critical issue it encountered while handling a request. These errors are associated with the debugger, and will be passed back into the failureBlock indicating a reason that the request failed.\n\nIf you encounter issues with a request, your first step should be to enable MMRecord logging, using the command below.\n\n```objective-c\n[MMRecord setLoggingLevel:MMRecordLoggingLevelAll];\n```\n\nYou can lower the logging level incrementally to receive finer grained logging information, but its a good idea to start with the highest level to get a broader picture of what is going on.\n\nIf your request is failing, you can use the `NSError` object that is passed into the failure block to review all sorts of data about the failure. The error parameter in the failure block will actually include the `MMRecordDebugger` instance, which contains all of the errors encountered while handling the request, and various bits of state relevant to the critical error.\n\nThe debugger is attached to the `NSError` in its userInfo dictionary. Here's an example of how you can use it.\n\n```objective-c\n     failureBlock:^(NSError *error) {\n         NSDictionary *recordDictionary = [[error userInfo] valueForKey:MMRecordDebuggerParameterRecordDictionary];\n         \n         MMRecordDebugger *debugger = [[error userInfo] valueForKey:MMRecordDebuggerKey];\n         NSArray *allErrors = [debugger errorsEncounteredWhileHandlingResponse];\n         id responseObject = [debugger responseObject];\n         NSString *entityName = [[debugger initialEntity] name];\n     }];\n```\n\nIf you encounter errors that you would like to see tracked, or have suggestions about the severity of some errors, please create an issue or file a pull request.\n\n## Requirements\n\nMMRecord 1.4.0 and higher requires either [iOS 6.0](https://developer.apple.com/library/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS6.html) and above, or [Mac OS 10.8](https://developer.apple.com/library/mac/releasenotes/macosx/whatsnewinosx/Articles/MacOSX10_8.html) ([64-bit with modern Cocoa runtime](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtVersionsPlatforms.html)) and above.\n\n### ARC\n\nMMRecord uses ARC.\n\nIf you are using MMRecord in your non-arc project, you will need to set a `-fobjc-arc` compiler flag on all of the MMRecord source files.\n\n## Credits\n\nMMRecord was created by [Conrad Stoll](http://conradstoll.com) at [Mutual Mobile](http://www.mutualmobile.com).\n\n## License\n\nMMRecord is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmutualmobile%2FMMRecord","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmutualmobile%2FMMRecord","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmutualmobile%2FMMRecord/lists"}