create data model for JSON - IOS/Objective-C - ios

I'm developing an IOS application in Objective C, in which i'l call a URL to retrieve an array JSON objects (restaurants). I want to parse them onto a objective-C Model. Using them to populate on to a UICollectionView that i have already designed. My task requires me to design this model to store the Json objects and then use them to populate onto UICollectionView. I don't know how to achieve this in Objective-C, please help me on this. The JSON retrieved is as follows.
"restaurants" : [
{
"name": "Burger Bar",
"backgroundImageURL": "http://somthing.com/Images/1.png",
"category" : "Burgers",
"contact": {
"phone": "1231231231",
"formattedPhone": "(123) 123-1231",
"twitter": "1twitter"
},
"location": {
"address": "5100 Belt Line Road, STE 502",
"crossStreet": "Dallas North Tollway",
"lat": 32.950787,
"lng": -96.821118,
"postalCode": "75254",
"cc": "US",
"city": "Addison",
"state": "TX",
"country": "United States",
"formattedAddress": [
"5100 Belt Line Road, STE 502 (Dallas North Tollway)",
"Addison, TX 75254",
"United States"
]
}
},
{
"name": "seafood Kitchen",
"backgroundImageURL": "http://somthing.com/Images/2.png",
"category": "Seafood",
"contact": {
"phone": "3213213213",
"formattedPhone": "(321) 321-3213",
"twitter": "2twitter"
},
"location": {
"address": "18349 Dallas Pkwy",
"crossStreet": "at Frankford Rd.",
"lat": 32.99908456526653,
"lng": -96.83018780592823,
"postalCode": "33331",
"cc": "US",
"city": "Dallas",
"state": "TX",
"country": "United States",
"formattedAddress": [
"18349 Dallas Pkwy (at Frankford Rd.)",
"Dallas, TX 75287",
"United States"
]
}
}
]
Below code shows how to call URL and retrieve and print the parse JSON objects.
NSString *urlString = #"http://somthing.com/Images/collection.json";
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (!error) {
NSError* parseError;
id parse = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&parseError];
NSLog(#"%#", parse);
}
}];
How to create the restaurant data model. Or is there any other way to go about this?

There's no need for any external library whatsoever. Look at the data that you get, and it's obvious that you want a class each representing a contact, a location, a restaurant, and you want to translate the JSON response into an array of restaurants. It's obvious what properties the contact, location and restaurant should have.
For each of the classes, you don't want the init method at all, so declare an init method with flags that make its use illegal. For each class, declare a method initWithJSONDictionary:(NSDictionary*)dict which takes the appropriate dictionary as an argument, extracts all the properties from the dictionary, logs if the values are not what you expect and returns nil if the data is faulty.
Use NSJSONSerialization to parse the complete JSON data, check that it's an array and each array element is a dictionary, and call [[MyRestaurant alloc] initWithJSONDictionary:...] for each dictionary.
That's absolutely straightforward, and for something simple like your case it should take you an hour or two to write bullet proof code for this.

You could use Json2Model from here https://github.com/fredlo2010/Json2Model
It would generate 4 object for you:
Restaurants.h
Restaurant.h
Contact.h
Location.h
Here is an example of Contact.h and Contact.n
#import <Foundation/Foundation.h>
#interface Contact : NSObject
#property (strong, nonatomic) NSString *twitter;
#property (strong, nonatomic) NSString *phone;
#property (strong, nonatomic) NSString *formattedPhone;
- (instancetype) initWithTwitter: (NSString *)twitter andPhone: (NSString *)phone andFormattedPhone: (NSString *)formattedPhone;
#end
#import "Contact.h"
#implementation Contact
- (instancetype) initWithTwitter: (NSString *)twitter andPhone: (NSString *)phone andFormattedPhone: (NSString *)formattedPhone {
self = [super init];
if (self) {
self.twitter = twitter;
self.phone = phone;
self.formattedPhone = formattedPhone;
}
return self;
}
#end

Use JSONModel https://github.com/icanzilb/JSONModel
.h file
#import "JSONModel.h"
#interface location : JSONModel
{
}
#property (nonatomic,strong) NSString *address;
#property (nonatomic,strong) NSString *crossStreet;
#property (nonatomic,strong) NSString *lat;
#property (nonatomic,strong) NSString *lng;
#property (nonatomic,strong) NSString *postalCode;
#property (nonatomic,strong) NSString *cc;
#property (nonatomic,strong) NSString *city;
#property (nonatomic,strong) NSString *state;
#property (nonatomic,strong) NSString *country;
#property (nonatomic,strong) NSArray *formattedAddress;
#end
#interface contact:JSONModel
{
}
#property (nonatomic,strong) NSString *phone;
#property (nonatomic,strong) NSString *formattedPhone;
#property (nonatomic,strong) NSString *twitter;
#end
#interface Restaurant : JSONModel
#property (nonatomic,strong) location *objectLocation;
#property (nonatomic,strong) contact *objContact;
#property (nonatomic,strong) NSString *name;
#property (nonatomic,strong) NSString *backgroundImageURL;
#property (nonatomic,strong) NSString *category;
#end
.m file
#implementation Restaurant
-(id)init{
self = [super init];
if (self) {
_category = #"";
_name = #"";
_backgroundImageURL = #"";
}
return self;
}
#end
#implementation contact
-(id)init{
self = [super init];
if (self) {
_phone = #"";
_formattedPhone = #"";
_twitter = #"";
}
return self;
}
#end
#implementation location
-(id)init{
self = [super init];
if (self) {
_address = #"";
_crossStreet = #"";
_lat = #"";
_lng= #"";
_postalCode = #"";
_city = #"";
_state = #"";
_cc = #"";
_country = #"";
}
return self;
}
//objects is the response object
NSArray* models = [Restaurant arrayOfModelsFromDictionaries: objects];

Store the array of restaurants from json in your model object and then you can retrieve the data required for your collection view from model so that all parsing stuff will remain in your model.
.h
#interface Model : NSObject
#property(nonatomic,strong)NSArray *restaurants;
#end
.m
#implementation Model
-(NSIteger)getRestaurantsCount{
return restaurants.count;
}
//getRestaurantAtIndex:
//getRestaurantNameAtIndex:
#end

Looking at the example JSON, you are getting an array of restaurants according to the [ ] brackets. You can retrieve the array with this:
NSArray *restArray= [parse objectForKey:#"restaurants"];
Now you want to loop through that array and parse the structure like the following:
for (NSDictionary *restaurant in restArray){
NSString* name = [restaurant objectForKey:#"name"];
NSDictionary* location = [restaurant objectForKey:"location"];
//etc...
}

You can parse the data you get in your callback to NSDictionary object:
NSData *response = someData; // data you are getting in callback
NSError *error;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:response options:kNilOptions error:&error];
NSArray *restaurants = [json objectForKey:#"restaurants"];

Checkout this repo, it also comes with easy coredata integration
https://github.com/BadChoice/daikiri

Related

My application crashes with this error - 'NSInvalidArgumentException'

I have created a program to retrieve JSON file and it achieved it
NSString *FilePath = [[NSBundle mainBundle]pathForResource:#"Message" ofType:#"json"];
NSData *data = [NSData dataWithContentsOfFile:FilePath];
NSError *error;
if(error){
NSLog(#"Error and CAn't retrive data: %#", error.localizedDescription);
}else{
NSDictionary * jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(#"Your Json Dictionary values are %#", jsonDict);
for(NSDictionary *valuesDictionary in jsonDict){
ShopCollectionObject *shopObject = [[ShopCollectionObject alloc]initWithID:[[valuesDictionary objectForKey:#"message_id"]integerValue] Name:[valuesDictionary objectForKey:#"product"] TimeAsPrice:[[valuesDictionary objectForKey:#"message_time"]integerValue] Avathar:[valuesDictionary objectForKey:#"item_image"] user:[valuesDictionary objectForKey:#"user_image"] Name_User:[valuesDictionary objectForKey:#"user_name"] LocationOfUser:[valuesDictionary objectForKey:#"locate_user"]];
But My app crashes here with the above error
[self.objectForArray addObject:shopObject];
}
}
Updated my shop collection code below
Shopcollection object.h
#import <Foundation/Foundation.h>
#interface ShopCollectionObject : NSObject
-(instancetype) initWithID: (int)msgID Name:(NSString *)Profile_name TimeAsPrice:(int) GivenTimeAsPrice Avathar:(NSString *) PhotoOfAvathar user:(NSString *)UserAvathar Name_User: (NSString *) UserNames LocationOfUser:(NSString *) USerLocationGiven;
#property (nonatomic) int msgID;
#property(nonatomic, strong)NSString* Name;
#property (nonatomic) int TimeAsPrice;
#property (nonatomic,strong) NSString* Avathar;
#property (nonatomic,strong) NSString* user;
#property (nonatomic,strong) NSString* Name_User;
#property(nonatomic,strong) NSString* LocationOfUser;
#end
Shopcollectionobject.m
#import "ShopCollectionObject.h"
#implementation ShopCollectionObject
-(instancetype)initWithID:(int)msgID Name:(NSString *)Profile_name TimeAsPrice:(int)GivenTimeAsPrice Avathar:(NSString *)PhotoOfAvathar user:(NSString *)UserAvathar Name_User:(NSString *)UserNames LocationOfUser:(NSString *)USerLocationGiven{
self = [super init];
if(self){
self.msgID = msgID;
self.Name = Profile_name;
self.TimeAsPrice = GivenTimeAsPrice;
self.Avathar = PhotoOfAvathar;
self.user = UserAvathar;
self.Name_User = UserNames;
self.LocationOfUser = USerLocationGiven;
}
return self;
}
#end
You likely aren't initializing your objectForArray. So when you try to call addObject, it's calling it on a null object.
ShopCollectionObject.h
#import <Foundation/Foundation.h>
#interface ShopCollectionObject : NSObject
#property (nonatomic) int message_id;
#property (strong, nonatomic) NSString *Name;
#property (nonatomic) int TimeAsPrice;
#property (strong, nonatomic) NSString *Avathar;//user,Name_User,LocationOfUser,message_id
#property (strong, nonatomic) NSString *user;
#property (strong, nonatomic) NSString *Name_User;
#property (strong, nonatomic) NSString *LocationOfUser;
-(instancetype) initWithID: (int)msgID Name:(NSString *)Profile_name TimeAsPrice:(int) GivenTimeAsPrice Avathar:(NSString *) PhotoOfAvathar user:(NSString *)UserAvathar Name_User: (NSString *) UserNames LocationOfUser:(NSString *) USerLocationGiven;
#property (nonatomic) int msgID;
#end
ShopCollectionObject.m
#import "ShopCollectionObject.h"
#implementation ShopCollectionObject
-(instancetype)initWithID:(int)msgID Name:(NSString *)Profile_name TimeAsPrice:(int)GivenTimeAsPrice Avathar:(NSString *)PhotoOfAvathar user:(NSString *)UserAvathar Name_User:(NSString *)UserNames LocationOfUser:(NSString *)USerLocationGiven{
self = [super init];
if(self){
self.msgID = msgID;
self.Name = Profile_name;
self.TimeAsPrice = GivenTimeAsPrice;
self.Avathar = PhotoOfAvathar;
self.user = UserAvathar;
self.Name_User = UserNames;
self.LocationOfUser = USerLocationGiven;
}
return self;
}
#end
ViewController.m
#import "ViewController.h"
#import "ShopCollectionObject.h"
#interface ViewController ()
{
NSMutableArray *objectForArray;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
objectForArray = [[NSMutableArray alloc]init];
NSString *FilePath = [[NSBundle mainBundle]pathForResource:#"Message" ofType:#"json"];
NSData *data = [NSData dataWithContentsOfFile:FilePath];
NSError *error;
if(error){
NSLog(#"Error and CAn't retrive data: %#", error.localizedDescription);
}else{
NSDictionary * jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
for(NSDictionary *valuesDictionary in jsonDict){
ShopCollectionObject *shopObject = [[ShopCollectionObject alloc]initWithID:[[valuesDictionary objectForKey:#"message_id"]intValue] Name:[valuesDictionary objectForKey:#"product"] TimeAsPrice:[[valuesDictionary objectForKey:#"message_time"]intValue] Avathar:[valuesDictionary objectForKey:#"item_image"] user:[valuesDictionary objectForKey:#"user_image"] Name_User:[valuesDictionary objectForKey:#"user_name"] LocationOfUser:[valuesDictionary objectForKey:#"locate_user"]];
[objectForArray addObject:shopObject];
}
NSLog(#"%#",objectForArray);
ShopCollectionObject *data = objectForArray[0];
NSLog(#"%#",data.Name);
}
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
pls check this code

Creating a data model from JSON

I have a JSON that looks like this :
{
"club": [
{
"titles": "1",
"league": "epl",
"country": "england",
}
}
And I have created a property like this :
#property (strong, nonatomic) NSMutableArray <Clubs> *club;
The club property inherits from the Clubs class which has the titles, leagues and country properties.
When I try to create a dictionary with that data model, I am unable to access the properties inside the club array.
Am I creating the data model incorrectly ?
Creating the dictionary:
for (NSDictionary *dictionary in responseObject) {
if (![self.searchText isEqualToString:#""]) {
self.predictiveProductsSearch = [[PerdictiveSearch alloc]initWithDictionary:dictionary error:nil];
self.predictiveTableView.dataSource = self;
[self.predictiveTableView reloadData];
self.predictiveTableView.hidden = NO;
}
}
Clubs class
#import <JSONModel/JSONModel.h>
#protocol Clubs #end
#interface Clubs : JSONModel
#property (strong, nonatomic) NSString <Optional> * titles;
#property (strong, nonatomic) NSString <Optional> * league;
#property (strong, nonatomic) NSString <Optional> * country;
#property (strong, nonatomic) NSString <Optional> * topGS;
#property (strong, nonatomic) NSString <Optional> * GoalSc;
#property (strong, nonatomic) NSString <Optional> * TransferBudget;
#end
Please use below code to achieve JSON Model saving:
_club = [[NSMutableArray alloc]init];
NSDictionary *responseObject = #{
#"club": #[
#{
#"titles": #"1",
#"league": #"epl",
#"country": #"england"
}]
};
NSArray *newResponseObject = [responseObject objectForKey:#"club"];
for (NSDictionary *dictionary in newResponseObject) {
Clubs *objClubs = [[Clubs alloc]initWithDictionary:dictionary error:nil];
[_club addObject:objClubs];
}
NSLog(#"%#",[_club objectAtIndex:0]);
which print like below :
<Clubs>
[titles]: 1
[country]: england
[GoalSc]: <nil>
[league]: epl
[topGS]: <nil>
[TransferBudget]: <nil>
</Clubs>

Parsing nested json in iOS using Mantle

I'm trying to parse data received from a service using the framework Mantle. The json has nested data and I am having problems to parse it. The json is like the following:
{
"sections": [
{
"title": "title1",
"level": 1,
"content": [
{
"type": "type1",
"text": "text1"
}
],
"images": []
},
{
"title": "title2",
"level": 2,
"content": [
{
"type": "type2",
"text": "text2"
},
{
"type": "type9",
"text": "text9"
},
{
"type": "type4",
"text": "text4"
},
{
"type": "type6",
"text": "text6"
}
],
"images": [
{
"src": "http://cvbcvcv",
"caption": "caption"
}
]
}]
}
The class that I am using is:
// MainObject.h
#interface MainObject : MTLModel <MTLJSONSerializing>
#property (strong, nonatomic) NSArray *sectionsArray;
+ (NSValueTransformer *)sectionsArrayJSONTransformer;
#end
#interface Section : MTLModel <MTLJSONSerializing>
#property (strong, nonatomic) NSString *title;
#property (assign, nonatomic) NSString *level;
#property (strong, nonatomic) NSArray *content;
#property (strong, nonatomic) NSArray *images;
+ (NSValueTransformer *)contentJSONTransformer;
+ (NSValueTransformer *)imagesJSONTransformer;
#end
#interface Content : MTLModel <MTLJSONSerializing>
#property (strong, nonatomic) NSString *type;
#property (strong, nonatomic) NSString *text;
#end
#interface Image : MTLModel <MTLJSONSerializing>
#property (strong, nonatomic) NSString *src;
#property (strong, nonatomic) NSString *caption;
#end
and
//MainObject.m
#implementation MainObject
+ (NSDictionary *)JSONKeyPathsByPropertyKey
{
return #{
#"sectionsArray" : #"sections",};
}
+ (NSValueTransformer *)sectionsArrayJSONTransformer
{
return [MTLJSONAdapter dictionaryTransformerWithModelClass:[Section class]];
}
#end
#implementation Section
+ (NSDictionary *)JSONKeyPathsByPropertyKey
{
return #{
#"title" : #"title",
#"level" : #"level",
#"content" : #"content",
#"images" : #"images",};
}
+ (NSValueTransformer *)contentJSONTransformer
{
return [MTLJSONAdapter arrayTransformerWithModelClass:[Content class]];
}
+ (NSValueTransformer *)imagesJSONTransformer
{
return [MTLJSONAdapter arrayTransformerWithModelClass:[Image class]];
}
#end
#implementation Content
+ (NSDictionary *)JSONKeyPathsByPropertyKey
{
return #{
#"type" : #"type",
#"text" : #"text",};
}
#end
#implementation Image
+ (NSDictionary *)JSONKeyPathsByPropertyKey
{
return #{
#"src" : #"src",
#"caption" : #"caption",};
}
#end
Then, when I make the call to the service and try to parse the json with the following code, being responseObject the data obtained from server, the data appears nil:
for (NSArray *array in [responseObject valueForKey:#"sections"]) {
NSArray *seccionArray = [MTLJSONAdapter modelsOfClass:[Section class] fromJSONArray:array error:nil];
}
I have tried a lot of ways to parse this data well, but the app always crashes or returns nil. I hope you can help me to solve this
Why can't just one line using NSJSONSerialization?
NSMutableDictionary *yourArray = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
Then you fetch what you want from your array...

How to parse the category object recursively in parsed JSON

Hi I am getting parsed nested JSON, which has many levels. I am able to get at first level value.
How could i use same model class to fetch all nested JSON values using recursion.
My JSON is -
{
"message": "Ok",
"STATUS_CODE": "200",
"REQUEST": {
"userid": "12436124",
"command": "GETCATEGORY"
},
"RESPONSE": {
"Category": [
{
"type": "Tag",
"categoryId": 11,
"name": "Electronics",
"catIconLeft": "",
"catIconRight": "",
"parentId": 0,
"Category": [
{
"type": "Category",
"categoryId": 84,
"name": "Mobile Accessories",
"parentId": 1,
"catIconLeft": "",
"catIconRight": "",
"Category": [
{
"type": "Product",
"categoryId": 90,
"name": "Headsets",
"catIconLeft": "",
"catIconRight": "",
"parentId": 9
},
<----so on------>
The complete Parsed JSON LINK
My Code for parsing-
-(void)call_CategoryListData{
[params setObject:#"command" forKey:#"GETCATEGORY"];
[params setObject:#"userid" forKey:#"12436124"];
[serverCall actionmethod:Fake_Category parameters:params onComplete:^(NSMutableDictionary* results){
if ([results isKindOfClass:[NSDictionary class]] || [results isKindOfClass:[NSMutableDictionary class]]){
//DDLogVerbose(#"\n\n\n\n\nResult----->%#",results);
NSMutableDictionary*responseDic=[results objectForKey:#"RESPONSE"];
NSMutableArray*catArray=[responseDic objectForKey:#"Category"];
for (NSMutableDictionary *dic in catArray) {
NSMutableArray* tmp = [dic objectForKey:#"Category"];
if (tmp) {
MyCategory *cat = [[MyCategory alloc] init];
cat.type = dic[#"type"];
cat.categoryId = dic[#"categoryId"];
if ([cat.type isEqualToString:#"Tag"]) {
cat.name = dic[#"name"];
cat.categoryId = dic[#"categoryId"];
[CatTag addObject:cat.name];
[CatID addObject:cat.categoryId];
<---------so on --------------->
NSLog(#"New Objects--->%#\n\n----->%#",CatTag,CatID);
}
}
}
}
}
onError:^(NSError *error) {
// handle error here
}];
}
My Model Class-
#interface MyCategory : NSObject
#property (nonatomic, strong) NSString *type;
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *categoryId;
#property(nonatomic,strong) NSString *catIconLeft;
#property (nonatomic,strong) NSString *catIconRight;
#property (nonatomic,strong) NSString *parentId;
#property (nonatomic, strong) MyCategory*Category;
MyCategory.h file
#interface MyCategory : NSObject
#property (nonatomic, strong) NSString *type;
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *categoryId;
#property (nonatomic, strong) NSString *catIconLeft;
#property (nonatomic, strong) NSString *catIconRight;
#property (nonatomic, strong) NSString *parentId;
#property (nonatomic, strong) NSArray *categories;
- (id)initWithRootDictionary:(NSDictionary *)dictionary;
#end
MyCategory.m hile
#implementation
- (id)initWithRootDictionary:(NSDictionary *)dictionary
{
self = [super init];
self.type = dictionary[#"type"];
self.name = dictionary[#"name"];
self.categoryId = dictionary[#"categoryId"];
self.catIconLeft = dictionary[#"catIconLeft"];
self.catIconRight = dictionary[#"catIconRight"];
self.parentId = dictionary[#"parentId"];
if (dictionary[#"category"]) {
NSMutableArray *categories = [NSMutableArray new];
for (NSDictionary *cat in dictionary[#"category"]) {
MyCategory *category = [[MyCategory alloc] initWithRootDictionary:cat];
[categories addObject:category];
}
self.categories = categories;
}
return self;
}
#end
//...
-(void)call_CategoryListData
{
//...
NSMutableDictionary * responseDic = [results objectForKey:#"RESPONSE"];
NSMutableArray * catArray = [responseDic objectForKey:#"Category"];
NSMutableArray *result = [NSMutableArray new];
for (NSDictionary *categoryDic in catArray) {
MyCategory *category = [[MyCategory alloc] initWithRootDictionary:categoryDic];
[result addObject:category];
}
// Do something with result
}
This is a fast written code directly in this editor without any IDE, so possible some syntax errors :)

How to use OCMock to mock a service

I am trying to write a unit test for creating a checklistItem, with properties defined below:
typedef NS_ENUM (NSUInteger, ChecklistStatus) { Pending, Completed };
#protocol IChecklistItem <NSObject>
#property (nonatomic, assign, readonly) NSInteger Id;
#property (nonatomic, copy, readonly) NSString *Description;
#property (nonatomic, assign, readonly)BOOL IsCompleted;
#property (nonatomic, assign, readwrite) ChecklistStatus Status;
#property (nonatomic, strong, readwrite) NSDate *CompletedDate;
#property (nonatomic, copy, readwrite) NSString *CompletedByUserId;
#property (nonatomic, assign, readonly) NSInteger RoleId;
#property (nonatomic, assign, readonly) NSInteger GroupId;
#property (nonatomic, strong, readonly) NSArray<IChecklistNote> *Notes;
Right now I have this setup in my setup method in my XCTest:
_service = [[ChecklistService alloc]initWithUrl:[NSURL URLWithString:kcChecklistUrl] credentialsManager:self.credentialsManager];
And this is the rest of my Unit Test:
- (void)testCreateChecklistItem {
XCTAssertNotNil(_service);
CCChecklistItem *checklistItem = [CCChecklistItem new];
CCChecklistItem *newChecklistItem = [CCChecklistItem new];
newChecklistItem.Id = 2;
newChecklistItem.Description = #"This is the Description";
newChecklistItem.RoleId = 2;
newChecklistItem.GroupId = 3;
newChecklistItem.Notes = nil;
newChecklistItem.Status = Completed;
XCTestExpectation *checklistItemExpectation = [self expectationWithDescription:#"checklistItem"];
id delegate = OCMProtocolMock(#protocol(ChecklistServiceDelegate));
id mock = [OCMockObject mockForProtocol:(#protocol(IChecklistService))];
[[[mock stub] andReturn:newChecklistItem] createChecklistItem:checklistItem delegate:delegate];
OCMExpect(([delegate didCompleteCreateChecklistItem:[OCMArg checkWithBlock:^BOOL(id obj) {
CCChecklistItem *items = obj;
XCTAssertNotNil(items);
double checklistId = items.Id;
XCTAssert(checklistId != 0);
[checklistItemExpectation fulfill];
}]]));
[_service createChecklistItem:checklistItem delegate:delegate];
[self waitForExpectationsWithTimeout:5 handler:^(NSError *error) {
if(error) {
}
OCMVerifyAll(delegate);
}];
}
However, i get the error failed: caught "NSUnknownKeyException", "[<__NSCFString 0x7faeaad6bd60> valueForUndefinedKey:]: this class is not key value coding-compliant for the key CompletedBy."
The createChecklistItem is defined below:
- (void)createChecklistItem:(id<IChecklistItem>)checklistItem delegate:(NSObject<ChecklistServiceDelegate> *)delegate
{
NSMutableArray *mockChecklistItem = [NSMutableArray new];
[TestObjectLoader loadObject:mockChecklistItem
fromJSONFile:#"ChecklistItem"
withMapping:[MappingProvider checklistCreateMapping]];
if (delegate != nil && [delegate respondsToSelector:#selector (didCompleteCreateChecklistItem:)]) {
[delegate didCompleteCreateChecklistItem:(NSObject<IChecklistItem> *)mockChecklistItem];
}
}
Where Checklist.json is
{
"Id": 13,
"Desc": "Checklist Description",
"IsCompleted": "false",
"TypeId": 1,
"RoleId": 1,
"Status": "C",
"CompletedDateTime": "2015-06-23T00:00:00+00:00",
"CompletedBy": "AC",
"Notes": [
{
"Note": "test",
"CreatedBy": "AC",
"CreatedDateTime": "2015-06-23T00:00:00+00:00"
}
]
}
Basically, I want to mock the service and when createChecklistItem is called, I simply just want to set a random Id on the object and pass it back instead of reading it through the ChecklistService from the Json file. IS there anyway to do this? I incorporated the mock in my test but I do not believe i am using it correctly...
You don't actually need Checklist.json, you should just be returning a value with a different Id.
So...
- (void)createChecklistItem:(id<IChecklistItem>)checklistItem delegate:(NSObject<ChecklistServiceDelegate> *)delegate
{
NSMutableArray *mockChecklistItem = [NSMutableArray new];
[TestObjectLoader loadObject:mockChecklistItem
fromJSONFile:#"ChecklistItem"
withMapping:[MappingProvider checklistCreateMapping]];
if (delegate != nil && [delegate respondsToSelector:#selector (didCompleteCreateChecklistItem:)]) {
[delegate didCompleteCreateChecklistItem:(NSObject<IChecklistItem> *)mockChecklistItem];
}
}
should simply just be
checklistItem.Id = 2; //Random number

Resources