Sunday, July 2, 2017

Lossless Image Compression (Objective C)

July 02, 2017 Posted by CHANDAN MAKHIJA 1 comment
Hello, welcome again to my tips. Today i will talk about lossless image compression in iOS. You might have come across a situation when you want to upload image to a server. At that time uploading huge size image can take lot of time, so u might have compressed image using UIImageJPEGRepresentation or UIImagePNGRepresentation. So you might wonder that what i will talk on this, as this is a single line of code. But don't worry i will not talk on this. I have something other to tell you today.

What is lossless compression ?

Lossless compression means that as the file size is compressed, the picture quality remains the same, it does not get worse. Also, the file can be decompressed to its original quality.

How it can be done ?

As there are many third party library for this, i have almost used all of them. They either reduce the dimension of the image to reduce its size or does lossy compression. But i have found one third party library that does lossless image compression. I will talk about it in a while. First let me tell you what is WebP format.

What is WebP format ?

WebP is a modern image format that provides superior lossless and lossy compression for images on the web. WebP lossless images are 26% smaller in size compared to PNGs. WebP lossy images are 25-34% smaller than comparable JPEG images at equivalent SSIM quality index.
Lossless WebP supports transparency (also known as alpha channel) at a cost of just 22% additional bytes. For cases when lossy RGB compression is acceptable, lossy WebP also supports transparency, typically providing 3× smaller file sizes compared to PNG.
So you can easily guess what will this library do. Yes, you are right this library converts PNG or JPEG format to WebP format, which will do the lossless image compression to almost 26%. So just click here and download that zip file and then copy UIImage+WebP.h and UIImage+WebP.m into your application. Now import "UIImage+WebP.h". Now use this function to change the image format
+ (void)imageToWebP:(UIImage *)image quality:(CGFloat)quality alpha:(CGFloat)alpha preset:(WebPPreset)preset
    completionBlock:(void (^)(NSData *result))completionBlock
       failureBlock:(void (^)(NSError *error))failureBlock;
Yes now it has been done, if you want to covert it back to the original format then use this function 
+ (void)imageWithWebP:(NSString *)filePath
      completionBlock:(void (^)(UIImage *result))completionBlock
         failureBlock:(void (^)(NSError *error))failureBlock;
I will show you the image which i have compressed, you can compare its quality. Its a lossless compression.

Original Image (1.10 MB)



Compressed Image (856 KB)




--------------------------------------------------------------------------------------------------------------------------

Saturday, July 1, 2017

Web Scrapping (Objective C)

July 01, 2017 Posted by CHANDAN MAKHIJA No comments
Hi i am back again with some new tips, hope you like it and find it useful. I hope you know the term "Web Scraping", if not then no need to worry, i will first explain you what is "Web Scraping" in detail and why do we need it and then i will explain you how you can do web scraping in iOS.

What is Web Scraping ?

In simple words we can define web scraping as "Web scraping (web harvesting or web data extraction) is data scraping used for extracting data from websites." Web scraping a web page involves fetching it and extracting from it. Fetching is the downloading of a page (which a browser does when you view the page). Therefore, web crawling is a main component of web scraping, to fetch pages for later processing. Once fetched, then extraction can take place. The content of a page may be parsed, searched, reformatted, its data copied into a spreadsheet, and so on. Web scrapers typically take something out of a page, to make use of it for another purpose somewhere else. An example would be to find and copy names and phone numbers, or companies and their URLs, to a list (contact scraping).
Web scraping is used for contact scraping, and as a component of applications used for web indexingweb mining and data mining, online price change monitoring and price comparison, product review scraping (to watch the competition), gathering real estate listings, weather data monitoring, website change detection, research, tracking online presence and reputation, web mashup and, web data integration.

How we can do Web Scraping in iOS ?

There are many ways by which you can do web scraping. First you can use Apple's library called libxml2.dylib. I will not explain you this method in detail, but i will provide you the link from where you can learn how to use this lib. You can click here to go directly to that link. This will explain you in detail about web scraping, if you know about it you can skip this part but i will recommend you to read about it. Next, it will explain you how to include this lib in xcode project along with the code that can be used in web scraping.
Second way of web scraping is by using third party libraries. These are open source libraries. You only have to include these libraries in your project and start using them. I will provide you the links of libraries that i have used. 

If you are coding in objective C then click here and if you are coding in swift then click here.

You might be wondering that i am only just providing links here without explaining anything. But that's not the case. I will explain you the most easiest way to do web scraping without using any libraries. So are you ready !. Lets begin

Third way of web scraping is very simple as i said before. First add a UIWevView to a storyboard. Make IBOutlet of UIWebView. Now below i will explain you with the code. I will write code in objective C.

Make a function as shown below that will accept a url as a string

- (void)loadRequestFromString:(NSString*)urlString
{
    NSURL *url = [NSURL URLWithString:urlString];
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
    [self.myWebView loadRequest:urlRequest];
}

Now call this function in the viewDidLoad method like this 

[self loadRequestFromString:pageURL];

where pageURL is the url of the page on which you want to do web scraping. Now add a button to a storyboard, on which scraping will be done. Make IBAction of that button as shown below and connect that button with it.

- (IBAction)getTableBtnPressed:(id)sender
{
}

Here i will show you how to scrap a table out of a web page. Now implement the IBAction as shown below

- (IBAction)getTableBtnPressed:(id)sender
{ 
NSString* string = [_myWebView stringByEvaluatingJavaScriptFromString: @"document.getElementsByClassName('table table-bordered')[0].innerHTML;"];
NSString *htmlString = [NSString stringWithFormat:@"%@%@%@",@"<html><body><table>",string,@"</table></body></html>"];
 [_myWebView loadHTMLString:[htmlString stringByReplacingOccurrencesOfString:@"\n" withString:@"<br/>"] baseURL:nil];
}

You might be confused, what is happening in the above code. But don't worry i will explain you line by line.

NSString* string = [_myWebView stringByEvaluatingJavaScriptFromString: @"document.getElementsByClassName('table table-bordered')[0].innerHTML;"]; 

here _myWebView is the IBOutlet of UIWebView. Call the method of UIWebView class i.e stringByEvaluatingJavaScriptFromString, which accepts the string as a parameter. This parameter @"document.getElementsByClassName('table table-bordered')[0].innerHTML;" will provide all the html tags used in the web page of a particular class named as "table table-bordered". If you want to get this class name, you can easily get this by loading the web page in the google chrome. After the page is loaded, right click on the web page and then click on the inspect button. A window will get open that will contain the elements of the web page as shown below.


Now to get the class for the particular item that you want to scrap, just click on top arrow button and then hover on the item that you want to scrap. I will show you the class of the table which i am scraping.



so  now you have learned how you can get the class for a particular element, lets get back to the code.
If you have many tags with the same class name then this function will return all those tags in the array. For example, you have 2 tables with the same class name, you will get those two table elements in the array. Its upto you whether you want both tables or first table or a second table. If you want both table then remove that subscript [0] from the code. If you want first table write subscript [0] and so on. In the above example i am only retrieving first table.

NSString *htmlString = [NSString stringWithFormat:@"%@%@%@",@"<html><body><table>",string,@"</table></body></html>"];

This line is very simple, it is only converting your string into html string, by placing opening and closing html and body tags. 

 [_myWebView loadHTMLString:[htmlString stringByReplacingOccurrencesOfString:@"\n" withString:@"<br/>"] baseURL:nil];

Last step, load that html string into the webview by replacing all new line with a <br/> tag. 

Now run the application. You will see that you have successfully scraped the table out of a web page.
Below is the screenshot of a table which i have scraped.






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.