Custom Model in Objective C
Created By: Debasis Das (17-Apr-2016)
Today we will create a Custom Model in Objective C where attributes can be added from within a loop. The model will support formatters and will have convenience method to create different types of attributes.
Normally a subclass of NSDictionary or a subclass of NSObject should suffice with the only exception that though we can programatically add keys to a dictionary, the keys are unsorted and if the desired behavior is to get all the attributes in the order in which they were added, it poses a challenge.
// KSModel.h // DemoObjcKSModel // Created by Debasis Das on 17/04/16. // Copyright © 2016 Knowstack. All rights reserved. #import <Foundation/Foundation.h> @interface KSModel : NSObject -(void)createAttributes; //This is the method that subclasses needs to override to add attributes to themselves -(NSArray *)allKeys; //Returns an array of keys present in the model -(void)addStringAttribute:(NSString *)attributeName; -(void)addIntegerAttribute:(NSString *)attributeName; -(void)addFloatAttribute:(NSString *)attributeName withFormatter:(NSNumberFormatter *)numberFormatter; -(void)addDateAttribute:(NSString *)attributeName withFormatter:(NSDateFormatter *)dateFormatter; -(NSMutableArray *)allAttributesWithValues; //Returns the entire model with keys, values and formatters -(NSMutableDictionary *)findAttributeByName:(NSString *)attributeName; -(NSString *)attributeAsString:(NSString *)attributeName; -(int)attributeAsInt:(NSString *)attributeName; -(float)attributeAsFloat:(NSString *)attributeName; -(id )valueForAttributeName:(NSString *)attributeName; -(void)setValue:(id)value forAttributeName:(NSString *)attributeName; @end
// KSModel.m
// DemoObjcKSModel
// Created by Debasis Das on 17/04/16.
// Copyright © 2016 Knowstack. All rights reserved.
#import "KSModel.h"
@interface KSModel(){
NSMutableArray *attributes;
}
@end
@implementation KSModel
- (instancetype)init
{
self = [super init];
if (self) {
attributes = [[NSMutableArray alloc] init];
[self createAttributes];
}
return self;
}
-(void)createAttributes{
NSLog(@"%s",__func__);
}
-(void)addStringAttribute:(NSString *)attributeName{
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:attributeName,@"key",
@"",@"value",
nil];
[attributes addObject:dict];
}
-(void)addIntegerAttribute:(NSString *)attributeName{
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:attributeName,@"key",
[NSNull null],@"value",
nil];
[attributes addObject:dict];
}
-(void)addFloatAttribute:(NSString *)attributeName withFormatter:(NSNumberFormatter *)numberFormatter{
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:attributeName,@"key",
numberFormatter,@"formatter",
[NSNull null],@"value",
nil];
[attributes addObject:dict];
}
-(void)addDateAttribute:(NSString *)attributeName withFormatter:(NSDateFormatter *)dateFormatter{
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:attributeName,@"key",
[NSDate date],@"value",
dateFormatter,@"formatter",
nil];
[attributes addObject:dict];
}
-(NSArray *)allKeys{
NSMutableArray *keyArray = [NSMutableArray new];
for (NSDictionary *dict in attributes){
[keyArray addObject:[dict objectForKey:@"key"]];
}
return [NSArray arrayWithArray:keyArray];
}
-(NSMutableArray *)allAttributesWithValues{
return attributes;
}
-(NSMutableDictionary *)findAttributeByName:(NSString *)attributeName{
for (NSMutableDictionary *dict in attributes){
if ([attributeName isEqualToString:[dict objectForKey:@"key"]]){
return dict;
}
}
return nil;
}
-(NSString *)attributeAsString:(NSString *)attributeName{
NSMutableDictionary *dict = [self findAttributeByName:attributeName];
if ([dict objectForKey:@"formatter"] == nil){
return [NSString stringWithFormat:@"%@",[dict objectForKey:@"value"]];
}
else{
if ([[dict objectForKey:@"formatter"] isKindOfClass:[NSDateFormatter class]]){
return [[dict objectForKey:@"formatter"] stringFromDate:[dict objectForKey:@"value"]];
}
}
return [NSString stringWithFormat:@"%@",[dict objectForKey:@"value"]];
}
-(int)attributeAsInt:(NSString *)attributeName{
return [[[self findAttributeByName:attributeName] objectForKey:@"value"] intValue];
}
-(float)attributeAsFloat:(NSString *)attributeName{
NSMutableDictionary *dict = [self findAttributeByName:attributeName];
if ([dict objectForKey:@"formatter"] == nil){
return [[[self findAttributeByName:attributeName] objectForKey:@"value"] floatValue];
}
else{
if ([[dict objectForKey:@"formatter"] isKindOfClass:[NSNumberFormatter class]]){
return [[[dict objectForKey:@"formatter"] stringFromNumber:[dict objectForKey:@"value"]] floatValue];
}
}
return [[[self findAttributeByName:attributeName] objectForKey:@"value"] floatValue];
}
-(id )valueForAttributeName:(NSString *)attributeName{
return [[self findAttributeByName:attributeName] objectForKey:@"value"];
}
-(void)setValue:(id)value forAttributeName:(NSString *)attributeName{
[[self findAttributeByName:attributeName] setObject:value forKey:@"value"];
}
@end
Sample Model
@interface Department : KSModel @end
@implementation Department -(void)createAttributes{ [self addStringAttribute:@"firstName"]; [self addStringAttribute:@"lastName"]; [self addIntegerAttribute:@"age"]; [self addFloatAttribute:@"salary" withFormatter:[self numberFormatter]]; [self addFloatAttribute:@"experience" withFormatter:nil]; for (int i =0; i<2; i++){ [self addStringAttribute:[NSString stringWithFormat:@"Account%d",i]]; } [self addDateAttribute:@"openingDate" withFormatter:[self mediumStyleDateFormatter]]; [self addDateAttribute:@"closingDate" withFormatter:nil]; [self addDateAttribute:@"meetingDate" withFormatter:[self longStyleDateFormatter]]; } -(NSNumberFormatter *)numberFormatter{ NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; [formatter setMinimumFractionDigits:(unsigned int)0]; [formatter setMaximumFractionDigits:(unsigned int)2]; return formatter; } //Test with 2 Date Formatters -(NSDateFormatter *)mediumStyleDateFormatter{ NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateStyle:NSDateFormatterMediumStyle]; return dateFormatter; } -(NSDateFormatter *)longStyleDateFormatter{ NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateStyle:NSDateFormatterLongStyle]; return dateFormatter; } @end
Test Code
Department *dept = [[Department alloc] init]; NSLog(@"All Keys are as follows %@",[dept allKeys]); /* All Keys are as follows ( firstName, lastName, age, salary, experience, Account0, Account1, openingDate, closingDate, meetingDate ) */ NSLog(@"First Name BEFORE = %@",[dept attributeAsString:@"firstName"]); //First Name BEFORE = [dept setValue:@"Debasis" forAttributeName:@"firstName"]; NSLog(@"First Name AFTER = %@",[dept attributeAsString:@"firstName"]); // First Name AFTER = Debasis NSLog(@"SALARY BEFORE = %2.2f",[dept attributeAsFloat:@"salary"]); //SALARY BEFORE = 0.00 [dept setValue:@20.6589876 forAttributeName:@"salary"]; NSLog(@"SALARY AFTER = %2.2f",[dept attributeAsFloat:@"salary"]); //SALARY AFTER = 20.66 [dept setValue:@12.3 forAttributeName:@"experience"]; NSLog(@"Opening Date BEFORE = %@",[dept attributeAsString:@"openingDate"]); //Opening Date BEFORE = 17-Apr-2016 NSDate *date = [NSDate dateWithTimeIntervalSinceNow:12345678]; [dept setValue:date forAttributeName:@"openingDate"]; NSLog(@"Opening Date AFTER = %@",[dept attributeAsString:@"openingDate"]); //Opening Date AFTER = 07-Sep-2016
You can download the source code hereDemoObjcKSModel
Leave a Reply