Thursday, September 17, 2015

Database Integration Of Objective C With SQLite

Database Integration : 

1) Create new Project 

2) Add libsqlite3.0.dylib, UIKit, Foundation, Coregraphics Frameworks

3) Set -fno-objc-arc flag to FMDatabase.m, FMDatabaseAdditions.m, FMResultSet.m

4) Drag and droop SQLite File to the project

5) Crate Constant.h file for setting constant fixed value ex like db name, messages etc.

// Constant.h

#import "SharedDataManager.h"
#import "AppDelegate.h"

#define HEADER_FONT            [UIFont fontWithName:@"HelveticaNeue" size:18]

#define kDATA_STORAGE_PATH [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]
#define kDB_NAME           @“dbname.sqlite"
#define kDB_PATH           [kDATA_STORAGE_PATH stringByAppendingPathComponent:kDB_NAME]
#define kIMG_PATH          [kDATA_STORAGE_PATH stringByAppendingPathComponent:@"Images"]

#define kSHARED_INSTANCE    [SharedDataManager sharedDbManager]

#define kDATABASE           [kSHARED_INSTANCE database]
#define kAPP_DELEGATE   (AppDelegate *)[[UIApplication sharedApplication] delegate]

// SharedDataManager.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "FMDatabase.h"

@interface SharedDataManager : NSObject {
    
    FMDatabase      *database;

}

+ (SharedDataManager *)sharedDbManager;

@property (nonatomic, retain) FMDatabase            *database;
@end


//  SharedDataManager.m


#import "SharedDataManager.h"

@implementation SharedDataManager
@synthesize database;


+ (SharedDataManager *)sharedDbManager  {
static SharedDataManager *sharedDbManager;

@synchronized(self) {
if(!sharedDbManager) {
sharedDbManager     = [[SharedDataManager alloc] init];
}
}
return sharedDbManager;
}
- (id)init {
    
    self = [super init];
if (self != nil)
{
        if(!self.database) {
            self.database       = [FMDatabase databaseWithPath:kDB_PATH];
        }
    }
    [self copyDatabaseToPath];
    [self openDb];
    return self;
}
-(void) copyDatabaseToPath {
    NSFileManager *fileManager = [NSFileManager defaultManager] ;
    if(![fileManager fileExistsAtPath:kDB_PATH]) {
        NSString *fromPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:kDB_NAME];
        [fileManager copyItemAtPath:fromPath toPath:kDB_PATH error:nil];
    }
    
}
-(void) openDb {
    if (![self.database open]) {
        NSLog(@"Could not open db.");
    }
}


// in pch #import "Constant.h"

// Basic operations

- (IBAction)addData:(id)sender
{
    
    NSString *query = [NSString stringWithFormat:@"INSERT INTO STUDENT (STUDENTid,NAME) VALUES (%@,'%@')",self.textViewNumber.text,self.textViewName.text];
    
    [kDATABASE executeUpdate:query];
    
    self.textViewNumber.text = self.textViewName.text = @"";
    
}

- (IBAction)showData:(id)sender
{
    [names removeAllObjects];
    
    
    NSString *selectQuery = @"SELECT * FROM STUDENT";
    
    FMResultSet *rs = [kDATABASE executeQuery:selectQuery];
    
    while ([rs next])
    {
        NSLog(@"data :- %d %@",[rs intForColumn:@"STUDENTid"],[rs stringForColumn:@"NAME"]);
        [names addObject:[rs stringForColumn:@"NAME"]];
    }
    
    [self.myTableView reloadData];

}

- (IBAction)searchAction:(id)sender
{
    NSString *keyWord = [self.textViewSearchName text];
    
    NSString *selectQuery = @"SELECT * FROM STUDENT";
    
    FMResultSet *rs = [kDATABASE executeQuery:selectQuery];
    
    while ([rs next])
    {
        NSString *selectedName = [rs stringForColumn:@"NAME"];
        if ([keyWord isEqualToString:selectedName])
        {
            toggleFound = 1;
            break;
        }
        else
        {
            toggleFound = 0;
        }
    }
    
    toggleFound?(self.labelStaus.text = @"Found"):(self.labelStaus.text = @"Not Found");

}


- (IBAction)deleteAction:(id)sender
{
    NSString *keyWord = [self.textViewDeleteName text];
    
    NSString *deleteQuery = [NSString stringWithFormat:@"DELETE * FROM STUDENT WHERE NAME = '%@'",keyWord];
    
    NSLog(@"Delete Query = %@",deleteQuery);
    [kDATABASE executeQuery:deleteQuery];
    [self.myTableView reloadData];

}

IMP Things for iOS Developers

#define KPreference [NSUserDefaults standardUserDefaults]

#define IS_IPAD (( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) ? YES : NO)
#define IS_IPHONE_4 (([UIScreen mainScreen].bounds.size.height == 480.0f)?YES:NO)
#define IS_IPHONE_5 (([UIScreen mainScreen].bounds.size.height == 568.0)?YES:NO)
#define IS_IPHONE_6 (([UIScreen mainScreen].bounds.size.height == 667.0)?YES:NO)
#define IS_IPHONE_6P (([UIScreen mainScreen].bounds.size.height == 736.0)?YES:NO)

#define KMyDevicePostFix (( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) ? @"_iPad" : (([UIScreen mainScreen].bounds.size.height == 480.0f)? @"_iPhone" : (([UIScreen mainScreen].bounds.size.height == 568.0)? @"_iPhone5" : (([UIScreen mainScreen].bounds.size.height == 667.0)? @"_iPhone6": @"_iPhone6P" ) ) ) )

#define KBaseAPIURL @""


#define KDeviceUDID [[[UIDevice currentDevice] identifierForVendor] UUIDString]

// Important shared functions 

+ (id) getNewViewControllerObjectOf : (NSString *) strClassName
{
    return [[NSClassFromString(strClassName) alloc]initWithNibName:[NSString stringWithFormat:@"%@%@",strClassName,KMyDevicePostFix] bundle:nil];
}

+ (id) getNewObjectOf : (NSString *) strClassName
{
    id genericObject;
    
    // Login Screen object selection
    
    if ([strClassName isEqualToString:@"LoginVc"])
    {
        LoginVc *loginScreen;
        
        if (IS_IPAD)
        {
            //loginScreen = [[LoginVc alloc]initWithNibName:@"LoginVc_iPad" bundle:nil];
        }
        else
        {
            if(IS_IPHONE_4)
            {
                loginScreen = [[LoginVc alloc]initWithNibName:@"LoginVc_iPhone" bundle:nil];
            }
            else if(IS_IPHONE_5)
            {
                loginScreen = [[LoginVc alloc]initWithNibName:@"LoginVc_iPhone5" bundle:nil];
            }
            else if(IS_IPHONE_6)
            {
                loginScreen = [[LoginVc alloc]initWithNibName:@"LoginVc_iPhone6" bundle:nil];
            }
            else
            {
                loginScreen = [[LoginVc alloc]initWithNibName:@"LoginVc_iPhone6P" bundle:nil];
            }
        }
        genericObject = loginScreen;
    }

return genericObject;
}



+ (BOOL) NSStringIsValidEmail:(NSString *)checkString
{
    BOOL stricterFilter = YES;
    
    NSString *stricterFilterString = @"[A-Z0-9a-z\\._%+-]+@([A-Za-z0-9-]+\\.)+[A-Za-z]{2,4}";
    NSString *laxString = @".+@([A-Za-z0-9-]+\\.)+[A-Za-z]{2}[A-Za-z]*";
    NSString *emailRegex = stricterFilter ? stricterFilterString : laxString;
    NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
    return [emailTest evaluateWithObject:checkString];
}



+ (BOOL) isDataNull : (NSString *) stringData
{
    BOOL flagValidData = YES;
    
    if (stringData == (id)[NSNull null])
    {
        // stringData is null
        
        flagValidData = NO;
    }
    
    return flagValidData;
}



+ (NSString *) getJSONStringFromJSONObject : (NSDictionary *) jsonObject
{
    NSError *error;
    NSData *json = [NSJSONSerialization dataWithJSONObject:jsonObject
                                                   options:0
                                                     error:&error];
    NSString *jsonString1 = [[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding];
    // This will be the json string in the preferred format
    jsonString1 = [jsonString1 stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"];
    
    return jsonString1;
}



+ (NSString *) getFormattedNumbers : (int) myNumber
{
    NSNumberFormatter *formatter = [NSNumberFormatter new];
    [formatter setNumberStyle:NSNumberFormatterDecimalStyle]; // this line is important!
    
    NSString *formattedNumber = [formatter stringFromNumber:[NSNumber numberWithInteger:myNumber]];
    
    return formattedNumber;
}

+ (NSString *) getAbbrivationFromString : (NSString *) stringForProcess
{
    NSMutableString * firstCharacters = [NSMutableString string];
    NSArray * words = [stringForProcess componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    for (NSString * word in words) {
        if ([word length] > 0) {
            NSString * firstLetter = [word substringToIndex:1];
            [firstCharacters appendString:[firstLetter uppercaseString]];
        }
    }
    
    return [NSString stringWithString:firstCharacters];
}

+ (BOOL)myMobileNumberValidate:(NSString*)number
{
    NSString *numberRegEx = @"[0-9]{10}";
    NSPredicate *numberTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", numberRegEx];
    if ([numberTest evaluateWithObject:number] == YES)
        return TRUE;
    else
        return FALSE;
}


// UITableView Using custom cell


#pragma mark Setup of Table view cell

- (void)setUpTableViewCell
{
    // Maiking Selection for
    if (IS_IPAD)
    {
        
    }
    else
    {
        if(IS_IPHONE_4)
        {
            [tableViewMenu registerNib:[UINib nibWithNibName:@"MenuCellTv_iPhone" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"MenuCellReuseID"];
        }
        else if(IS_IPHONE_5)
        {
            [tableViewMenu registerNib:[UINib nibWithNibName:@"MenuCellTv_iPhone" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"MenuCellReuseID"];
        }
        else if(IS_IPHONE_6)
        {
            [tableViewMenu registerNib:[UINib nibWithNibName:@"MenuCellTv_iPhone6" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"MenuCellReuseID"];
        }
        else
        {
            [tableViewMenu registerNib:[UINib nibWithNibName:@"MenuCellTv_iPhone6P" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"MenuCellReuseID"];
        }
    }
    
    [tableViewMenu setBackgroundColor:[UIColor clearColor]];
    
    [tableViewMenu reloadData];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ModelMenuRow *singleRow = [arrayMenuItems objectAtIndex:indexPath.row];
    
    static NSString *CellIdentifier = @"MenuCellReuseID";
    MenuCellTv *cell = (MenuCellTv *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    
    cell.menuImage.image    = singleRow.menuImage;
    cell.menuName.text      = singleRow.menuTitle;
    
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
    return cell;
}


// Remove storyboard

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];


self.window.rootViewController = VcObj ;   
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    
    return YES;
}


// Custom loading 

#pragma mark Loading Progress Indicator

- (void) showLoadingView
{
    [self hideLoadingView];
    
    UIView *viewLoading = [[UIView alloc]initWithFrame:self.view.frame];
    viewLoading.tag = 500;
    UIImageView *imageViewAnimation = [[UIImageView alloc]initWithFrame:CGRectMake(0,0,150,150)];
    UILabel *labelLoadingText = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 130, 60)];
    labelLoadingText.textColor = [UIColor whiteColor];
    labelLoadingText.font = [UIFont fontWithName:@"HelveticaNeue" size:18];
    labelLoadingText.textAlignment = NSTextAlignmentCenter;
    labelLoadingText.text = KLoadingText;
    labelLoadingText.center = self.view.center;
    [viewLoading addSubview:labelLoadingText];
    
    //imageViewAnimation.layer.masksToBounds  = YES;
    imageViewAnimation.layer.cornerRadius   = imageViewAnimation.frame.size.height/2;
    imageViewAnimation.layer.borderWidth    = 1;
    imageViewAnimation.layer.borderColor    = [UIColor whiteColor].CGColor;//[UIColor colorWithRed:216.0/255.0 green:216.0/255.0 blue:216.0/255.0 alpha:1.0].CGColor;
    
    UILabel *labelRound = [[UILabel alloc]initWithFrame:CGRectMake(imageViewAnimation.frame.origin.x+imageViewAnimation.frame.size.width-5, imageViewAnimation.frame.origin.y+(imageViewAnimation.frame.size.height/2-5), 10, 10)];
    
    labelRound.layer.masksToBounds = YES;
    labelRound.layer.cornerRadius = labelRound.frame.size.height/2;
    
    //    [labelRound setBackgroundColor:[UIColor colorWithRed:216.0/255.0 green:216.0/255.0 blue:216.0/255.0 alpha:1.0]];
    
    [labelRound setBackgroundColor:[UIColor whiteColor]];
    
    [imageViewAnimation addSubview:labelRound];
    
    imageViewAnimation.center = self.view.center;
    
    viewLoading.backgroundColor = [UIColor colorWithRed:0/255 green:0/255 blue:0/255 alpha:0.5];
    [viewLoading addSubview:imageViewAnimation];
    [imageViewAnimation setImage:[UIImage imageNamed:@"loading.png"]];
    
    CABasicAnimation *rotation;
    rotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    rotation.fromValue = [NSNumber numberWithFloat:0];
    rotation.toValue = [NSNumber numberWithFloat:(2*M_PI)];
    rotation.duration = 4; // Speed
    rotation.repeatCount = HUGE_VALF; // Repeat forever. Can be a finite number.
    [imageViewAnimation.layer addAnimation:rotation forKey:@"Spin"];
    
    [self.view addSubview:viewLoading];
}

- (void) hideLoadingView
{
    for (UIView *i in self.view.subviews)
    {
        if([i isKindOfClass:[UIView class]])
        {
            UIView *selectedView = (UIView *)i;
            if(selectedView.tag == 500)
            {
                [selectedView removeFromSuperview];
                break;
            }
        }
    }
}


// AFNetworking POST JSON DATA With image

[self showLoadingView];
    
    UIImage *image = imageViewUserImage.image;
    NSData *imageData = UIImageJPEGRepresentation(image, 0.5);
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    
    NSDictionary *parameters = @{};
    
    NSString *stringURL = [NSString stringWithFormat:@"%@user_registration.php?user_name=%@&user_email=%@&user_phone=%@&password=%@", KBaseAPIURL, textFieldUserName.text, textFieldEmailId.text, textFieldMobileNumber.text, textFieldPassword.text];
    
    NSString *encodedURL = [stringURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    [manager POST:encodedURL parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
    {
        [formData appendPartWithFileData:imageData name:@"user_image" fileName:@"avatar.jpg" mimeType:@"image/jpeg"];
    }
    success:^(AFHTTPRequestOperation *operation, id responseObject)
    {
        [self hideLoadingView];
        
        NSString* responseString = [NSString stringWithUTF8String:[responseObject bytes]];
        NSLog(@"%@",responseString);
        
        NSData *data = [responseString dataUsingEncoding:NSUTF8StringEncoding];
        id jsonResponseDictonary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        
        NSLog(@"%@", [SharedDataManager getJSONStringFromJSONObject:jsonResponseDictonary]);
        
        if ([[jsonResponseDictonary objectForKey:@"result"] integerValue] == 1)
        {
            LoginVc *loginScreen = [SharedDataManager getNewObjectOf:@"LoginVc"];
            [kSlideNav switchToViewController:loginScreen withCompletion:nil];
        }
        else
        {
            UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Alert" message:[responseObject objectForKey:@"msg"] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
                         [alert show];
        }
    }
    failure:^(AFHTTPRequestOperation *operation, NSError *error)
    {
        [self hideLoadingView];
        
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Error" message:error.description delegate:self cancelButtonTitle:@"Retry" otherButtonTitles:nil];
        alert.tag = 23;
        [alert show];
        NSLog(@"Error: %@", error);
    }];


// POST DATA ONLY


[self showLoadingView];
    
    AFHTTPRequestOperationManager *manager  = [AFHTTPRequestOperationManager manager];
    
    manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:@"text/html"];
    
    NSMutableDictionary *parameters         = [[NSMutableDictionary alloc]init];
    
    NSLog(@"%@", stringLoginURL);
    
    [manager POST:stringLoginURL
       parameters: parameters
     
     
    success:^(AFHTTPRequestOperation *operation, id responseObject)
    {
        [self hideLoadingView];
         
         NSLog(@"JSON Response of login : %@", [SharedDataManager getJSONStringFromJSONObject:responseObject]);
         
         if ([[responseObject objectForKey:@"result"] integerValue] == 1)
         {
             NSMutableDictionary *dictUserDetail = [responseObject objectForKey:@"User_details"];
             [KPreference setObject:dictUserDetail forKey:@"KeyUserDetail"];
             
             HomeVc *homeScreen = [SharedDataManager getNewObjectOf:@"HomeVc"];
             [kSlideNav switchToViewController:homeScreen withCompletion:nil];
         }
         else
         {
             UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Alert" message:[responseObject objectForKey:@"msg"] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
             [alert show];
         }
         
     }
     failure:^(AFHTTPRequestOperation *operation, NSError *error)
     {
         [self hideLoadingView];
     }];




// Reachability.h

#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>


/** 
 * Create NS_ENUM macro if it does not exist on the targeted version of iOS or OS X.
 *
 **/
#ifndef NS_ENUM
#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
#endif

extern NSString *const kReachabilityChangedNotification;

typedef NS_ENUM(NSInteger, NetworkStatus) {
    // Apple NetworkStatus Compatible Names.
    NotReachable = 0,
    ReachableViaWiFi = 2,
    ReachableViaWWAN = 1
};

@class Reachability;

typedef void (^NetworkReachable)(Reachability * reachability);
typedef void (^NetworkUnreachable)(Reachability * reachability);


@interface Reachability : NSObject

@property (nonatomic, copy) NetworkReachable    reachableBlock;
@property (nonatomic, copy) NetworkUnreachable  unreachableBlock;

@property (nonatomic, assign) BOOL reachableOnWWAN;


+(instancetype)reachabilityWithHostname:(NSString*)hostname;
// This is identical to the function above, but is here to maintain
//compatibility with Apples original code. (see .m)
+(instancetype)reachabilityWithHostName:(NSString*)hostname;
+(instancetype)reachabilityForInternetConnection;
+(instancetype)reachabilityWithAddress:(void *)hostAddress;
+(instancetype)reachabilityForLocalWiFi;

-(instancetype)initWithReachabilityRef:(SCNetworkReachabilityRef)ref;

-(BOOL)startNotifier;
-(void)stopNotifier;

-(BOOL)isReachable;
-(BOOL)isReachableViaWWAN;
-(BOOL)isReachableViaWiFi;

// WWAN may be available, but not active until a connection has been established.
// WiFi may require a connection for VPN on Demand.
-(BOOL)isConnectionRequired; // Identical DDG variant.
-(BOOL)connectionRequired; // Apple's routine.
// Dynamic, on demand connection?
-(BOOL)isConnectionOnDemand;
// Is user intervention required?
-(BOOL)isInterventionRequired;

-(NetworkStatus)currentReachabilityStatus;
-(SCNetworkReachabilityFlags)reachabilityFlags;
-(NSString*)currentReachabilityString;
-(NSString*)currentReachabilityFlags;

@end


// Reachability.m

#import "Reachability.h"

#import <sys/socket.h>
#import <netinet/in.h>
#import <netinet6/in6.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>


NSString *const kReachabilityChangedNotification = @"kReachabilityChangedNotification";


@interface Reachability ()

@property (nonatomic, assign) SCNetworkReachabilityRef  reachabilityRef;
@property (nonatomic, strong) dispatch_queue_t          reachabilitySerialQueue;
@property (nonatomic, strong) id                        reachabilityObject;

-(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags;
-(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags;

@end


static NSString *reachabilityFlags(SCNetworkReachabilityFlags flags) 
{
    return [NSString stringWithFormat:@"%c%c %c%c%c%c%c%c%c",
#if TARGET_OS_IPHONE
            (flags & kSCNetworkReachabilityFlagsIsWWAN)               ? 'W' : '-',
#else
            'X',
#endif
            (flags & kSCNetworkReachabilityFlagsReachable)            ? 'R' : '-',
            (flags & kSCNetworkReachabilityFlagsConnectionRequired)   ? 'c' : '-',
            (flags & kSCNetworkReachabilityFlagsTransientConnection)  ? 't' : '-',
            (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
            (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic)  ? 'C' : '-',
            (flags & kSCNetworkReachabilityFlagsConnectionOnDemand)   ? 'D' : '-',
            (flags & kSCNetworkReachabilityFlagsIsLocalAddress)       ? 'l' : '-',
            (flags & kSCNetworkReachabilityFlagsIsDirect)             ? 'd' : '-'];
}

// Start listening for reachability notifications on the current run loop
static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) 
{
#pragma unused (target)

    Reachability *reachability = ((__bridge Reachability*)info);

    // We probably don't need an autoreleasepool here, as GCD docs state each queue has its own autorelease pool,
    // but what the heck eh?
    @autoreleasepool 
    {
        [reachability reachabilityChanged:flags];
    }
}


@implementation Reachability

#pragma mark - Class Constructor Methods

+(instancetype)reachabilityWithHostName:(NSString*)hostname
{
    return [Reachability reachabilityWithHostname:hostname];
}

+(instancetype)reachabilityWithHostname:(NSString*)hostname
{
    SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]);
    if (ref) 
    {
        id reachability = [[self alloc] initWithReachabilityRef:ref];

        return reachability;
    }
    
    return nil;
}

+(instancetype)reachabilityWithAddress:(void *)hostAddress
{
    SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);
    if (ref) 
    {
        id reachability = [[self alloc] initWithReachabilityRef:ref];
        
        return reachability;
    }
    
    return nil;
}

+(instancetype)reachabilityForInternetConnection
{
    struct sockaddr_in zeroAddress;
    bzero(&zeroAddress, sizeof(zeroAddress));
    zeroAddress.sin_len = sizeof(zeroAddress);
    zeroAddress.sin_family = AF_INET;
    
    return [self reachabilityWithAddress:&zeroAddress];
}

+(instancetype)reachabilityForLocalWiFi
{
    struct sockaddr_in localWifiAddress;
    bzero(&localWifiAddress, sizeof(localWifiAddress));
    localWifiAddress.sin_len            = sizeof(localWifiAddress);
    localWifiAddress.sin_family         = AF_INET;
    // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
    localWifiAddress.sin_addr.s_addr    = htonl(IN_LINKLOCALNETNUM);
    
    return [self reachabilityWithAddress:&localWifiAddress];
}


// Initialization methods

-(instancetype)initWithReachabilityRef:(SCNetworkReachabilityRef)ref
{
    self = [super init];
    if (self != nil
    {
        self.reachableOnWWAN = YES;
        self.reachabilityRef = ref;

        // We need to create a serial queue.
        // We allocate this once for the lifetime of the notifier.

        self.reachabilitySerialQueue = dispatch_queue_create("com.tonymillion.reachability", NULL);
    }
    
    return self;    
}

-(void)dealloc
{
    [self stopNotifier];

    if(self.reachabilityRef)
    {
        CFRelease(self.reachabilityRef);
        self.reachabilityRef = nil;
    }

self.reachableBlock          = nil;
self.unreachableBlock        = nil;
    self.reachabilitySerialQueue = nil;
}

#pragma mark - Notifier Methods

// Notifier 
// NOTE: This uses GCD to trigger the blocks - they *WILL NOT* be called on THE MAIN THREAD
// - In other words DO NOT DO ANY UI UPDATES IN THE BLOCKS.
//   INSTEAD USE dispatch_async(dispatch_get_main_queue(), ^{UISTUFF}) (or dispatch_sync if you want)

-(BOOL)startNotifier
{
    // allow start notifier to be called multiple times
    if(self.reachabilityObject && (self.reachabilityObject == self))
    {
        return YES;
    }


    SCNetworkReachabilityContext    context = { 0, NULL, NULL, NULL, NULL };
    context.info = (__bridge void *)self;

    if(SCNetworkReachabilitySetCallback(self.reachabilityRef, TMReachabilityCallback, &context))
    {
        // Set it as our reachability queue, which will retain the queue
        if(SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, self.reachabilitySerialQueue))
        {
            // this should do a retain on ourself, so as long as we're in notifier mode we shouldn't disappear out from under ourselves
            // woah
            self.reachabilityObject = self;
            return YES;
        }
        else
        {
#ifdef DEBUG
            NSLog(@"SCNetworkReachabilitySetDispatchQueue() failed: %s", SCErrorString(SCError()));
#endif

            // UH OH - FAILURE - stop any callbacks!
            SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL);
        }
    }
    else
    {
#ifdef DEBUG
        NSLog(@"SCNetworkReachabilitySetCallback() failed: %s", SCErrorString(SCError()));
#endif
    }

    // if we get here we fail at the internet
    self.reachabilityObject = nil;
    return NO;
}

-(void)stopNotifier
{
    // First stop, any callbacks!
    SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL);
    
    // Unregister target from the GCD serial dispatch queue.
    SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, NULL);

    self.reachabilityObject = nil;
}

#pragma mark - reachability tests

// This is for the case where you flick the airplane mode;
// you end up getting something like this:
//Reachability: WR ct-----
//Reachability: -- -------
//Reachability: WR ct-----
//Reachability: -- -------
// We treat this as 4 UNREACHABLE triggers - really apple should do better than this

#define testcase (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection)

-(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags
{
    BOOL connectionUP = YES;
    
    if(!(flags & kSCNetworkReachabilityFlagsReachable))
        connectionUP = NO;
    
    if( (flags & testcase) == testcase )
        connectionUP = NO;
    
#if TARGET_OS_IPHONE
    if(flags & kSCNetworkReachabilityFlagsIsWWAN)
    {
        // We're on 3G.
        if(!self.reachableOnWWAN)
        {
            // We don't want to connect when on 3G.
            connectionUP = NO;
        }
    }
#endif
    
    return connectionUP;
}

-(BOOL)isReachable
{
    SCNetworkReachabilityFlags flags;  
    
    if(!SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
        return NO;
    
    return [self isReachableWithFlags:flags];
}

-(BOOL)isReachableViaWWAN 
{
#if TARGET_OS_IPHONE

    SCNetworkReachabilityFlags flags = 0;
    
    if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
    {
        // Check we're REACHABLE
        if(flags & kSCNetworkReachabilityFlagsReachable)
        {
            // Now, check we're on WWAN
            if(flags & kSCNetworkReachabilityFlagsIsWWAN)
            {
                return YES;
            }
        }
    }
#endif
    
    return NO;
}

-(BOOL)isReachableViaWiFi 
{
    SCNetworkReachabilityFlags flags = 0;
    
    if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
    {
        // Check we're reachable
        if((flags & kSCNetworkReachabilityFlagsReachable))
        {
#if TARGET_OS_IPHONE
            // Check we're NOT on WWAN
            if((flags & kSCNetworkReachabilityFlagsIsWWAN))
            {
                return NO;
            }
#endif
            return YES;
        }
    }
    
    return NO;
}


// WWAN may be available, but not active until a connection has been established.
// WiFi may require a connection for VPN on Demand.
-(BOOL)isConnectionRequired
{
    return [self connectionRequired];
}

-(BOOL)connectionRequired
{
    SCNetworkReachabilityFlags flags;
if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
    {
return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
}
    
    return NO;
}

// Dynamic, on demand connection?
-(BOOL)isConnectionOnDemand
{
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
    {
return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) &&
(flags & (kSCNetworkReachabilityFlagsConnectionOnTraffic | kSCNetworkReachabilityFlagsConnectionOnDemand)));
}
return NO;
}

// Is user intervention required?
-(BOOL)isInterventionRequired
{
    SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
    {
return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) &&
(flags & kSCNetworkReachabilityFlagsInterventionRequired));
}
return NO;
}


#pragma mark - reachability status stuff

-(NetworkStatus)currentReachabilityStatus
{
    if([self isReachable])
    {
        if([self isReachableViaWiFi])
            return ReachableViaWiFi;
        
#if TARGET_OS_IPHONE
        return ReachableViaWWAN;
#endif
    }
    
    return NotReachable;
}

-(SCNetworkReachabilityFlags)reachabilityFlags
{
    SCNetworkReachabilityFlags flags = 0;
    
    if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) 
    {
        return flags;
    }
    
    return 0;
}

-(NSString*)currentReachabilityString
{
NetworkStatus temp = [self currentReachabilityStatus];
if(temp == ReachableViaWWAN)
{
        // Updated for the fact that we have CDMA phones now!
return NSLocalizedString(@"Cellular", @"");
}
if (temp == ReachableViaWiFi
{
return NSLocalizedString(@"WiFi", @"");
}
return NSLocalizedString(@"No Connection", @"");
}

-(NSString*)currentReachabilityFlags
{
    return reachabilityFlags([self reachabilityFlags]);
}

#pragma mark - Callback function calls this method

-(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags
{
    if([self isReachableWithFlags:flags])
    {
        if(self.reachableBlock)
        {
            self.reachableBlock(self);
        }
    }
    else
    {
        if(self.unreachableBlock)
        {
            self.unreachableBlock(self);
        }
    }
    
    // this makes sure the change notification happens on the MAIN THREAD
    dispatch_async(dispatch_get_main_queue(), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:kReachabilityChangedNotification 
                                                            object:self];
    });
}

#pragma mark - Debug Description

- (NSString *) description
{
    NSString *description = [NSString stringWithFormat:@"<%@: %#x (%@)>",
                             NSStringFromClass([self class]), (unsigned int) self, [self currentReachabilityFlags]];
    return description;
}

@end


// ReachabilityManager.h

#import <Foundation/Foundation.h>

@class Reachability;

@interface ReachabilityManager : NSObject

@property (strong, nonatomic) Reachability *reachability;

#pragma mark -
#pragma mark Shared Manager
+ (ReachabilityManager *)sharedManager;

#pragma mark -
#pragma mark Class Methods
+ (BOOL)isReachable;
+ (BOOL)isUnreachable;
+ (BOOL)isReachableViaWWAN;
+ (BOOL)isReachableViaWiFi;

@end


// ReachabilityManager.m

#import "ReachabilityManager.h"
#import "Reachability.h"

@implementation ReachabilityManager

#pragma mark -
#pragma mark Default Manager
+ (ReachabilityManager *)sharedManager {
    static ReachabilityManager *_sharedManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedManager = [[self alloc] init];
    });
    
    return _sharedManager;
}

#pragma mark -
#pragma mark Memory Management
- (void)dealloc {
    // Stop Notifier
    if (_reachability) {
        [_reachability stopNotifier];
    }
}

#pragma mark -
#pragma mark Class Methods
+ (BOOL)isReachable {
    return [[[ReachabilityManager sharedManager] reachability] isReachable];
}

+ (BOOL)isUnreachable {
    return ![[[ReachabilityManager sharedManager] reachability] isReachable];
}

+ (BOOL)isReachableViaWWAN {
    return [[[ReachabilityManager sharedManager] reachability] isReachableViaWWAN];
}

+ (BOOL)isReachableViaWiFi {
    return [[[ReachabilityManager sharedManager] reachability] isReachableViaWiFi];
}

#pragma mark -
#pragma mark Private Initialization
- (id)init {
    self = [super init];
    
    if (self) {
        // Initialize Reachability
        self.reachability = [Reachability reachabilityWithHostname:@"www.google.com"];
        
        // Start Monitoring
        [self.reachability startNotifier];
    }
    
    return self;
}

@end


// How to use reachability

// To App Delegate

// in did finish launching

// Start Monitoring
    [reachability startNotifier];
    
    // Instantiate Shared Manager
    [ReachabilityManager sharedManager];


if ([ReachabilityManager isReachable])
    {
        NSLog(@"Internet Connection is available.");
        //[WebAPI parseAndResetBadgeCountToServer];
    }
    else
    {
        NSLog(@"Internet Connection is not available.");
    }


// In screen import and use ReachabilityManager as above



// How to use collection view cells