Saturday, April 15, 2017

How to avoid building apps that crash by parsing JSON (Objective C)

April 15, 2017 Posted by CHANDAN MAKHIJA No comments
When you’re just getting started with Objective C, it’s easy to fall into the trap of doing things the easy way, especially when working with JSON. But if you parse JSON the easy way, your app will crash, and you’ll be scratching your head wondering why. For your users and for your own sanity, don’t build apps that crash – be sure that when you parse JSON, you do it the safe way, not the easy way.

Let’s start with some simple JSON we’d like to parse:



{
"data": [ {"name":"chandan"},
          {"name":"vipul"}
         ]
}




You will parse this JSON like


NSArray* array = [dict objectForKey@"data"];



And you will receive a array of dictionary in "array". But now imagine a situation when a key "data" is now not containing an array or a key has been changed. Now what will happen, your APP will get crashed because it has not found an array. So to avoid these kind of crashes just create a category of your dictionary and add some methods as shown below.




#import "NSDictionary+RMDictionary.h"

@implementation NSDictionary (RMDictionary)

- (BOOL) boolForKey:(NSString*)aKey
{
    NSObject* value = [self valueForKey:aKey];
    if ([value isKindOfClass:[NSNumber class]])
    {
        NSNumber* num = (NSNumber*)value;
        return num.boolValue;
        
    }
    else
        return NO;
}

- (NSInteger) integerForKey:(NSString*)key
{
    NSObject* value = [self valueForKey:key];
    if ([value isKindOfClass:[NSNumber class]])
    {
        return ((NSNumber*)value).integerValue;
    }
    return 0;
}

- (NSString*) stringForKey:(NSString*)key
{
    id value = [self valueForKey:key];
    
    if ([value isKindOfClass:[NSString class]])
    {
        return (NSString*)value;
    }
    return @"";
}

- (NSDate*) dateForKey:(NSString*)key
{
    NSString* value = [self stringForKey:key];
    NSDateFormatter* formatter = [[NSDateFormatter alloc]init];
    [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
    NSDate* date = [formatter dateFromString:value];
    
    if (date)
    {
        return date;
    }
    
    return [NSDate dateWithTimeIntervalSince1970:0];
}

-(NSArray*) arrayForKey:(NSString*)key
{
    id value = [self valueForKey:key];
    if([value isKindOfClass:[NSArray class]])
    {
        return (NSArray*)value;
    }
    return [[NSArray alloc] init];
}

- (NSNumber*) numberForKey:(NSString*)key
{
    NSObject* value = [self valueForKey:key];
    if ([value isKindOfClass:[NSNumber class]])
    {
        return (NSNumber*)value;
    }
    return 0;
}

- (NSDictionary*) dictionaryForKey:(NSString*)key
{
    id value = [self valueForKey:key];
    if([value isKindOfClass:[NSDictionary class]])
    {
        return (NSDictionary*)value;
    }
    return [[NSDictionary alloc] init];
}


@end




Now instead of using "objectForKey" start using "arrayForKey" or "stringForKey". This will now avoid your APP crash, because if array is not found it will create an empty array and then return.

  

Sunday, April 2, 2017

Avoid retain cycles without doing Strong to Weak

April 02, 2017 Posted by CHANDAN MAKHIJA No comments
You all will be familiar with blocks. It plays a very important role in iOS development. When you are using blocks you might have come across with Retain Cycles. 

Retain Cycle is the condition When 2 objects keep a reference to each other and are retained, it creates a retain cycle since both objects try to retain each other, making it impossible to release.
Here the "Grandparent" retains the "parent" and "parent" retains the "child" where as "child" retains the "parent". Here a retain cycle is established between parent and child. After releasing the Grandparent both the parent and child become orphaned but the retain count of parent will not be zero as it is being retained by the child and hence causes a memory management issue.
 As you probably already know, referencing any object from inside a block captures a strong reference to it, and if that object copies/retains the block, it results in a retain cycle, that could cause a memory leak unless the block is manually nil’ed out.
So to avoid these Retail Cycles we use a weak reference with the __weak qualifier. But when i was searching some other way of doing it, i found one alternate solution for it. While going through Facebook’s Pop open source project, I came across this method.

/**@param target The object being animated.Reference the passed in target to help avoid retain loops.*/typedef BOOL (^POPCustomAnimationBlock)(id target, POPCustomAnimation *animation);
Look at the parameters of the block you can always get an implicit reference to these variables (through block’s scope variable capturing), but it’s very useful because now you can use these parameters rather than declaring a weak reference outside a block and using that.
This way you avoid retain cycles without having to do the whole strong → weak dance.