Custom Model in Objective C

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

Posted in Cocoa, Objective C

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Recent Posts


Hit Counter provided by technology news