Tuesday, 20 January 2015

Database Level Security in Application using SqlSipher,FMDB,OpenSSl



Application Database Security

In One of my application I have to make my application security proof, that means no one can theft your data.
I have used database in my application which stores some confidential data ,then I can make it secure by  using these frameworks:

OpenSSl
SqlCipher
FMDB

SqlCipher has two version Commercial and Free edition.

We will use Free edition:
I will elaborate here step by step explanation to give security.

 First create new project from Xcode . I am using  Xcode 6.1












OpenSSL
Download OpenSSl Version . 
I downloaded openssl-1.0.1j.tar.gz (MD5) (SHA1) (PGP sign)  [LATEST]

 Then follow these much steps: 
  •    Open Terminal
  •    Go to documents -> make one folder named code ->  run this script as under

cd ~/Documents/code % curl -o openssl-1.0.1j.tar.gz  http://www.openssl.org/source/openssl-1.0.0e.tar.gz tar xzf openssl-1.0.0e.tar.gz 



SQLCipher

% cd ~/Documents/code/SQLCipherApp % git clone https://github.com/sqlcipher/sqlcipher.git


% cd ~/Documents/code/SQLCipherApp % git clone https://github.com/sqlcipher/openssl-xcode.git


XCode project settings


Add OpenSSL Source Tree


The OpenSSL XCode project includes a project template that relies on the OpenSSL configure and make system to build the libraries. However, it automatically detects the appropriate build settings for architecture (i386, x86_64, arvm6, armv7), build tools, and SDK. This makes it ideal for inclusion in an iPhone project.

Switch into your project's root directory and checkout the OpenSSL XCode project
SQLCipher uses sub-projects to manage build dependencies and static linking. Before writing code to use SQLCipher you must setup XCode, and your project, to build SQLCipher.











Now that the XCode global preferences are setup we will move on to the project configuration.


In the application project, click on the top level Project item. Right click on the project and choose "Add Files to "Project"", or press option-command-a, to add a re source. Navigate to the project directory, inside the sqlcipher folder, and add the sqlcipher.xcodeproj. If you have multiple targets, be sure to add the file to both. Repeat the same step for openssl-xcode/openssl.xcodeproj.



Add subproject references












Configure build dependencies















Set build architectures and CFLAGS

So if you’re still in development and need frequent access to your DB for debugging purposes, leave the encryption part to the end.
Be sure to verify the PGP and/or SHA1 signature of the archive before use.


Switch into your project's root directory and checkout the SQLCipher project code

OpenSSL can be tricky to compile properly from source. It's even more complex when you're dealing with multiple target architectures (iOS development targets i386 for the simulator but armv6 and armv7 for a device)




We must add build dependencies to ensure that SQLCipher is compiled before the application code. Select your application target and open the Info panel. Under the Build Phases tab, in the Target Dependencies section, we will add both openssl/crypto and sqlcipher/sqlcipher. Use Command-click to select both at once.
Then, under the Link Binary With Libraries section, add libcrypto.a and libsqlcipher.a.


Make sure that libsqlite3.dylib is not selected as a link dependency.
Add the same set of dependencies and link settings to any other targets in your project that will depend on SQLCipher, i.e. unit tests.
Select the top level project and choose the Build Settings Tab, and expand the Architectures setting. Leave the Debug setting as the default. Ensure the Release architectures are correct (e.g. armv7 and armv7s for iOS, x86_64 for MacOS). Change them if necessary. This will ensure that all dependent projects will be deployable on all desired architectures.
Next, locate the Header Search Paths setting, and add "sqlcipher" as a search path. This will ensure that XCode can find the required header for the SQLCipher library. Ensure that the "recursive" box is not checked on the includes, or the build may fail.
Finally, under "Other C Flags", add -DSQLITE_HAS_CODEC to the Debug and Release C Flag settings. This will ensure that the SQLite key management functions are defined for use by the application.
NOTE:

 If you choose to change either the build architectures or the compiler used, you must apply the same changes to the build settings under the openssl.xcodeproj and sqlcipher.xcodeproj. The three settings must match across all projects.
At this point you should be able to build the XCode project without errors. Note that the first time you build the application for a particular architecture (Simulator for instance), it will take much longer than usual. This is because SQLCipher and OpenSSL are compiled from source for the specific architecture. You can keep track of the status under Build Results. Subsequent builds for the same platform will be much quicker since the libraries don’t need to be recompiled.













Sql Cipher Options:

If you want to use Free edition use
If you want to use Commercial Version use:

3) download FMDB

You can download FMDB from here:

Here I show you how to use FMDB wrapper with Sql Cipher with Database:
You have to use two database here you have to attach encrypted database



     - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentDir = [documentPaths objectAtIndex:0];
        self.databasePath = [documentDir stringByAppendingPathComponent:@"gameDefault.sqlite"];
        [self createAndCheckDatabase]
    }


You’ll notice that I also call a separate method createAndCheckDatabase which actually do the verification I told above and create a copy of the database file in case it does not exist in the Documents folder.

      NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);


        NSString *documentDir = [documentPaths objectAtIndex:0];
        NSString *ecDB = [documentDir stringByAppendingPathComponent:@"encrypted.sqlite"];
    
        // SQL Query. NOTE THAT DATABASE IS THE FULL PATH NOT ONLY THE NAME
        const char* sqlQ = [[NSString stringWithFormat:@"ATTACH DATABASE '%@' AS encrypted KEY 'secretKey';",ecDB] UTF8String];
        
        sqlite3 *unencrypted_DB;    
        if (sqlite3_open([self.databasePath UTF8String], &unencrypted_DB) == SQLITE_OK) {
    
            // Attach empty encrypted database to unencrypted database
            sqlite3_exec(unencrypted_DB, sqlQ, NULL, NULL, NULL);
            
            // export database
            sqlite3_exec(unencrypted_DB, "SELECT sqlcipher_export('encrypted');", NULL, NULL, NULL);
            
            // Detach encrypted database
            sqlite3_exec(unencrypted_DB, "DETACH DATABASE encrypted;", NULL, NULL, NULL);
            
            sqlite3_close(unencrypted_DB);


        }


        else {
            sqlite3_close(unencrypted_DB);
            NSAssert1(NO, @"Failed to open database with message '%s'.", sqlite3_errmsg(unencrypted_DB));
        }
        
        self.databasePath = [documentDir stringByAppendingPathComponent:@"encrypted.sqlite"];



After you’ve done this, you’ll have your database in the Documents folder where it will be accessible to the application to read/write.
So, in order for you to have an encrypted database, you’ll need to create a new blank encrypted database and then ATTACH you existing database to it. By attaching, you will have everything that you had in your unencrypted database in the new encrypted one.
Let’s start by importing SQLite to your AppDelegate.m file. At the top of you file add
Now inside of the createAndCheckDatabase method, add the following below what we already have


Breaking down this code

1.    In the first 3 lines we get the Documents Directory path and set the NSString ecDB to that path with the new database name.

2.    Then we create the SQL Query we’re going to execute first to do the ATTACH. Note that we set 2 parameters in there, the DATABASE and the KEY. The DATABASE should be the full path to the encrypted database you want to create, in this case, string ecDB, and the KEY parameter is the key that’s going to be use to ENCRYPT your database, so choose a strong one



3.    We then connect to the unencrypted database and run 3 SQL Queries, the ATTACH, the EXPORT which will export the new encrypted database with your data to the path you chose and finally the DETACH to detach the database from the unencrypted file.

    4.    And the last command is the one which will set my AppDelegate databasePath        property to the new Encrypted Database we created. In my case this is very important because in my classes, I call AppDelegate to get the path to open the database
This part is now complete and you have your encrypted database. If you go to your Application Documents folder you will now see 2 files, gameDefault.sqlite and encrypted.sqlite.
Now comes the easy part. You should already have all your methods to INSERT, UPDATE, CREATE, etc… in your code, so you should need just to add a single line of code after every time you open the database.
.
If you try to open your encrypted db it’s not going to work because you need your secret key. so add the setKey method after you open your db
And you’re done! that should convert your existing DB into an encrypted db.
FYI: I tried opening my encrypted database in several sqlite browser programs and none could open because it was encrypted, but the code is able to insert, update, delete, etc… to your db just fine.



Tuesday, 21 October 2014

Push-Notification Change in iOS8

in ios 8 so many things change in one of them one change is related to push notification.

If you run your old push notification code in Xcode 6 then it will give you warning also some methods deprecated in ios 8
registerForRemoteNotificationTypes is deprecated in ios 8 instead of it in ios 8 we use UIUserNotificationSettings like this way:

           #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
            if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
                UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
                [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
            } else {
                [[UIApplication sharedApplication]
                 registerForRemoteNotificationTypes:
                 (UIRemoteNotificationTypeAlert |
                  UIRemoteNotificationTypeBadge |
                  UIRemoteNotificationTypeSound)];
            }
        #else
            [[UIApplication sharedApplication]
             registerForRemoteNotificationTypes:
             (UIRemoteNotificationTypeAlert |
              UIRemoteNotificationTypeBadge |
           
 
     UIRemoteNotificationTypeSound)];
    #endif


and for delegate methods,



      #pragma mark - Push Notification
 
    - (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
   
    // Prepare the Device Token for Registration (remove spaces and < >)
    NSString *TokenID = [[[[deviceToken description]
                               stringByReplacingOccurrencesOfString:@"<"withString:@""]
                              stringByReplacingOccurrencesOfString:@">" withString:@""]
                             stringByReplacingOccurrencesOfString: @" " withString: @""];
   
     
        [ApplicationPreferences setTokenId:TokenID];
    if (DEBUG_MODE) {
    NSLog(@"device token - %@",[NSString stringWithFormat:@"Device Token = %@",TokenID]);
            NSUUID *oNSUUID = [[UIDevice currentDevice] identifierForVendor];
            NSLog(@"Vendor token - %@",[NSString stringWithFormat:@"Device Token = %@",[oNSUUID UUIDString]]);
    }
 
    }
 
    - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
    {
        //register to receive notifications
        [application registerForRemoteNotifications];
    }
 
    - (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
        if (DEBUG_MODE) {
    NSLog(@"Push Error- %@",[NSString stringWithFormat: @"Error: %@", err]);
        }
    }
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
     
    }

Thanks .

Sunday, 12 October 2014

ios 8 changes for actionsheet


In ios 8 apple has changed so many things i here faced one problem in my own project so , i just want to provide the solution in replacement of UIActionsheet.

   in ios 8 UIActionSheet deprecated as well its delegate methods also deprecated. Instead of that UIAlertController with prefferedstyle 
UIAlertControllerStyleActionSheet  is used. you can check this thread as well:

https://developer.apple.com/library/ios/documentation/Uikit/reference/UIActionSheet_Class/index.html

This example will work both in ios 8 and previous version of it.



in .h file declare this variable


@interface demoProfileForBuyer{
 UIActionSheet *ac_sheet_fordate;
    UIToolbar *pickerToolBar_fordate;

    UIDatePicker *optionPickerDate;
UIAlertController *alertController;
}

in .m file

- (void)viewDidLoad
{

    [super viewDidLoad];
    pickerToolBar_fordate = [[UIToolbar alloc] initWithFrame:CGRectMake(-8, 0, 320, 44)];
    
    pickerToolBar_fordate.barStyle = UIBarStyleBlack;
    [pickerToolBar_fordate sizeToFit];
    
    NSMutableArray *barItemsDate = [[NSMutableArray allkioc] init];
    
    
    UIBarButtonItem *flexSpaceDate = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
    [barItemsDate addObject:flexSpaceDate];
    
    UIBarButtonItem *doneBtnDate = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(pickerViewDoneBirthday)];
    [barItemsDate addObject:doneBtnDate];
    
    [pickerToolBar_fordate setItems:barItemsDate animated:YES];
    
    optionPickerDate = [[UIDatePicker alloc] initWithFrame:CGRectMake(-8, 44, 320, 200)];
    
    
    optionPickerDate.datePickerMode = UIDatePickerModeDate;
    [optionPickerDate setMaximumDate: [NSDate date]];
    optionPickerDate.datePickerMode = UIDatePickerModeDate;
    optionPickerDate.hidden = NO;
    optionPickerDate.date = [NSDate date];
    optionPickerDate.backgroundColor = [UIColor whiteColor];
    
    if(IS_IOS_8){

        alertController = [UIAlertController alertControllerWithTitle:@"" message:@"" preferredStyle:UIAlertControllerStyleActionSheet];
        
        UIAlertAction *alertAction = [UIAlertAction actionWithTitle:@"" style:UIAlertActionStyleDefault handler:nil];
        [alertController addAction:alertAction];
        [alertController addAction:alertAction];
        [alertController addAction:alertAction];
        [alertController addAction:alertAction];        
        [alertController.view addSubview:pickerToolBar_fordate];
        [alertController.view addSubview:optionPickerDate];        
    } else {
    ac_sheet_fordate = [[UIActionSheet alloc] initWithTitle:@"test"
                                                   delegate:self
                                          cancelButtonTitle:@"cancel"
                                     destructiveButtonTitle:nil
                                          otherButtonTitles:@"dev",@"dev", nil];
    [ac_sheet_fordate setActionSheetStyle:UIActionSheetStyleBlackOpaque];
    [ac_sheet_fordate setBackgroundColor:[UIColor blackColor]];
    [ac_sheet_fordate addSubview:pickerToolBar_fordate];
    [ac_sheet_fordate addSubview:optionPickerDate];
    }
    }

// when date picker open 

   - (IBAction)showBirthdayPicker:(id)sender{
    //    self.view.frame = CGRectMake(0, -220, self.view.frame.size.width, self.view.frame.size.height);
    UIButton *btnsender = sender;
    //[ac_sheet_fordate showInView:self.view];
    self.scrForEditProfile.contentSize = CGSizeMake(320, 1000);
    if(IS_IOS_8){
            popover = alertController.popoverPresentationController;
            if (popover)
            {
                popover.sourceView = sender;
                popover.sourceRect = CGRectMake(0, btnsender.bounds.origin.y, btnsender.bounds.size.width, btnsender.bounds.size.height);
                
                popover.permittedArrowDirections = UIPopoverArrowDirectionAny;
            }
                [self presentViewController:alertController animated:YES completion:nil];
            
    } else {
    if(IS_IOS_7){
        [ac_sheet_fordate showInView:[UIApplication sharedApplication].keyWindow];
        ac_sheet_fordate.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height-ac_sheet_fordate.frame.size.height, [UIScreen mainScreen].bounds.size.width, ac_sheet_fordate.frame.size.height);
    }
    else{
        [ac_sheet_fordate showInView:self.view];
    }
    }
    if(IS_IOS_7==FALSE && IS_HEIGHT_GTE_568==FALSE){
        [self.scrForEditProfile scrollRectToVisible:CGRectMake(self.txtDOB.frame.origin.x, self.txtDOB.frame.origin.y + 200, self.txtDOB.frame.size.width, self.txtDOB.frame.size.height) animated:NO];
    }
    else{
        [self.scrForEditProfile scrollRectToVisible:CGRectMake(self.txtDOB.frame.origin.x, self.txtDOB.frame.origin.y +300, self.txtDOB.frame.size.width, self.txtDOB.frame.size.height) animated:NO];
    }
    
}

// when date picker open user tap on done button

- (IBAction)pickerViewDoneBirthday{
    
    if(IS_IOS_8){
        [self.presentedViewController dismissViewControllerAnimated:NO completion:nil];
        
    } else {
        [ac_sheet_fordate dismissWithClickedButtonIndex:0 animated:YES];
   
    }

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"dd/MM/yyyy"];
    birthday_date = optionPickerDate.date;
    [self.btnShowDatePicker setTitle:[formatter stringFromDate:optionPickerDate.date] forState:UIControlStateNormal];
    [self.btnShowDatePicker setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [self.btnShowDatePicker setTitleColor:[UIColor blackColor] forState:UIControlStateHighlighted];
    self.scrForEditProfile.contentSize=CGSizeMake(320 , 700);
    [self.scrForEditProfile scrollsToTop];
    
}


I hope this will help, and this code will display the same action sheet kind of view as it displayed in ios 7 .

Monday, 1 September 2014

Predicates and compound predicate to filter data

Hi friends in normal iphone application in all applications we see search feature normally.
Search can be done from server side as well as from application side locally.

we can search data locally using NSPredicate and NSCompoundPredicate .

I have one NSMutableArray which i created this way:

NSMutableArray *arrAllData = [NSMutableArray array];
[arrAllData addObject :@{@"id":@"1",@"title":@"Mittal",@"search_type":@"Sr Enginner",}];
[arrAllData addObject :@{@"id":@"2",@"title":@"Rupal",@"search_type":@"Jr Enginner",}];
[arrAllData addObject :@{@"id":@"3",@"title":@"Sunny",@"search_type":@"QA",}];
[arrAllData addObject :@{@"id":@"3",@"title":@"Adithi",@"search_type":@"Director",}];
[arrAllData addObject :@{@"id":@"3",@"title":@"Nirman",@"search_type":@"Director",}];


Now we want to filter the data according to Boss and Employee:
Please apply this code.

NSMutableArray *predicates = [NSMutableArray array];
NSString *filter = @"search_type == %@";
NSPredicate *commonPred = [NSPredicate predicateWithFormat:filter, @"Sr Enginner"];
[predicates addObject:commonPred];
NSPredicate *jrEngineerPred = [NSPredicate predicateWithFormat:filter, @"Jr Enginner"];
[predicates addObject: jrEngineerPred];
NSPredicate *QAPred = [NSPredicate predicateWithFormat:filter, @"QA"];
[predicates addObject:QA];
NSPredicate *resultPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];
NSArray *arr_Data = [arrAllData filteredArrayUsingPredicate:resultPredicate];
 NSMutableArray *arSearchEmployeeData = [arr_Data mutableCopy];


arr_Data =  [NSMutableArray alloc]init];
commonPred = [NSPredicate predicateWithFormat:filter, @"Director"];
arr_Data = [arrAllData filteredArrayUsingPredicate:
                              commonPred];
 NSMutableArray *arSearcBossData = [arr_Data mutableCopy];

Happy Coding!!

Thanks.






Wednesday, 25 June 2014

Attributed String With different Color and Italic

Hi  attributedString is introduced in ios 3.2 but However the ability to use them within certain UI controls such as UILabel, UIButton, UITextView, etc is only available since iOS6. I will discuss it here in this blog.

To give color attribute and italic effects in string you have to declare one  NSAttributedString like this :


#define MAINCOLOR [UIColor colorWithRed:51/255.0 green:51/255.0 blue:51/255.0 alpha:1.0]


NSMutableAttributedString * Subtitlestring ;
[Subtitlestring addAttribute:NSForegroundColorAttributeName value:MAINCOLOR range:NSMakeRange(0,[strMovieName length])]; 

[Subtitlestring addAttribute:NSFontAttributeName value:[[Util sharedUtil] fontOfType:
@"HelveticaNeue-Italic bold:NO size:12 range:NSMakeRange(0,[Subtitlestring length])];
[lblSubtitle setAttributedText:Subtitlestring];

This will display gray  color  and italic string in label. 

Cheers!!!!

Tuesday, 13 May 2014

Get Contacts from Address Book then compare them with database Data and check existance

One of the my project i have to display contacts from contact book and compare them from my database.

For that first you have to read data from the addressbook for that apply the code as below.

-(NSMutableArray*)getaddressBookArray{
    addressBook = nil;
    __block NSMutableArray *arrayOfPeople = nil;
    __block BOOL userDidGrantAddressBookAccess;
    CFErrorRef addressBookError = NULL;
    
    if ( ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined ||
        ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized )
    {
        addressBook = ABAddressBookCreateWithOptions(NULL, &addressBookError);
        
        dispatch_semaphore_t sema = dispatch_semaphore_create(0);
        ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error){
            userDidGrantAddressBookAccess = granted;
            arrayOfPeople = [(__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook) mutableCopy];

            dispatch_semaphore_signal(sema);
        });
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    }
    else
    {
        if ( ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusDenied ||
            ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusRestricted )
        {
            // Display an error.
        }
    }
    
    return arrayOfPeople;
    

}

Here three case may happen
1> First you have to check whether user has allowed access of contacts or not then array will be empty
2>  Either there are not any records in address book or not then if no contacts available then contacts array remain empty
3> If contacts found then check them from database which you stored internally like this way



In Database I have one table like contacts which has fields like firstName, lastName, number stored which came from sync api i get them in  [self getActiveUsers] Method which get data from database.


Then i make one class for make the contact object .

TKContact.h

@interface TKContact : NSObject {
    NSInteger sectionNumber;
    NSInteger recordID;
    BOOL rowSelected;
    NSString *name;
    NSString *email;
    NSString *tel;
    UIImage *thumbnail;
    NSString *lastName;
    NSString *firstName;
}

@property NSInteger sectionNumber;
@property NSInteger recordID;
@property BOOL rowSelected;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *email;
@property (nonatomic, retain) NSString *tel;
@property (nonatomic, retain) UIImage *thumbnail;
@property (nonatomic, retain) NSString *lastName;
@property (nonatomic, retain) NSString *firstName;
@property (nonatomic, retain) NSString *number;
- (NSString*)sorterFirstName;
- (NSString*)sorterLastName;


@end


TKContact.m

#import "TKContact.h"

@implementation TKContact
@synthesize name, email, tel, thumbnail, recordID, sectionNumber, lastName, firstName,number;


- (NSString*)sorterFirstName {
    if (nil != firstName && ![firstName isEqualToString:@""]) {
        return firstName;
    }
    if (nil != lastName && ![lastName isEqualToString:@""]) {
        return lastName;
    }
    if (nil != name && ![name isEqualToString:@""]) {
        return name;
    }
    return nil;
}

- (NSString*)sorterLastName {
    if (nil != lastName && ![lastName isEqualToString:@""]) {
        return lastName;
    }
    if (nil != firstName && ![firstName isEqualToString:@""]) {
        return firstName;
    }
    if (nil != name && ![name isEqualToString:@""]) {
        return name;
    }
    return nil;
}



@end

-(void)checkContacts{
    NSMutableArray *arrNumber = [self getaddressBookArray];
    self.ContactAcccess = FALSE;
    if([arrNumber count]>0){
        self.listContent = [[NSMutableArray alloc] init];
        
        
        NSMutableArray *arr_dbContacts =  [self getActiveUsers];;
        NSMutableArray *contactArray = [[NSMutableArray alloc]init];
        if([arrNumber count]>0){
            for(NSUInteger index = 0; index <= ([arrNumber count]-1); index++){
                
                ABRecordRef currentPerson = (__bridge ABRecordRef)[arrNumber objectAtIndex:index];
                CFStringRef abName = ABRecordCopyValue(currentPerson, kABPersonFirstNameProperty);
                CFStringRef abLastName = ABRecordCopyValue(currentPerson, kABPersonLastNameProperty);
                CFStringRef abFullName = ABRecordCopyCompositeName(currentPerson);
                NSString *currentNumber = @"";
                ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(currentPerson, kABPersonPhoneProperty);
                
                for(CFIndex i = 0; i < ABMultiValueGetCount(phoneNumberProperty); i++) {
                    CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phoneNumberProperty, i);
                    currentNumber = (__bridge NSString *) phoneNumberRef;
                    if(![currentNumber isEqualToString:@""]){
                        currentNumber = [self subtractExceptNumber:currentNumber];
                        if([currentNumber length]>=8){
                            NSString *fullNameString;
                            NSString *firstString = (__bridge NSString *)abName;
                            NSString *lastNameString = (__bridge NSString *)abLastName;
                            
                            if ((__bridge id)abFullName != nil) {
                                fullNameString = (__bridge NSString *)abFullName;
                            } else {
                                if ((__bridge id)abLastName != nil)
                                {
                                    fullNameString = [NSString stringWithFormat:@"%@ %@", firstString, lastNameString];
                                }
                            }
                            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"accountnumber == %@", currentNumber];
                            NSArray *array = [arr_dbContacts filteredArrayUsingPredicate:predicate];
                            if([array count]>0){
                                TKContact *contact = [[TKContact alloc] init];
                                contact.name = fullNameString;
                                contact.number = currentNumber;
                                contact.rowSelected = NO;
                                contact.lastName = (__bridge NSString*)abLastName;
                                contact.firstName = (__bridge NSString*)abName;
                                ABRecordID contactID = ABRecordGetRecordID(currentPerson);
                                ABRecordRef origContactRef = ABAddressBookGetPersonWithRecordID(addressBook, contactID);
                                UIImage *img;
                                if (ABPersonHasImageData(origContactRef)) {
                                    NSData *imgData = (__bridge NSData*)ABPersonCopyImageDataWithFormat(origContactRef, kABPersonImageFormatOriginalSize);
                                    img = [UIImage imageWithData: imgData];
                                    
                                }
                                if(img==nil){
                                    contact.thumbnail = nil;
                                }
                                else{
                                    contact.thumbnail = img;
                                }
                                
                                [contactArray addObject:contact];
                                self.ContactAcccess = TRUE;
                            }
                            
                        }
                    }
                    
                }
                
                
                // Copy the e-mail value into a string.
                //  currentNumber = [_phoneNumbers objectAtIndex:0];
                //  currentNumber = (__bridge NSString *)(ABRecordCopyValue(currentPerson, kABPersonPhoneProperty));
            }
        }
        SEL sorter = ABPersonGetSortOrdering() == kABPersonSortByFirstName ? NSSelectorFromString(@"sorterFirstName") : NSSelectorFromString(@"sorterLastName");
        self.listContent = [[self partitionObjects:contactArray collationStringSelector:sorter] mutableCopy];

    }}


Working with UIPasteboard

Hi friends in this tutorial  we will cover how to deal with UIPasteBoard.We will cover these much tasks:


1> Reading data  from general PasterBoard
2> Writing data to general PasteBoard
3> create Pasteboard
4> remove Pasteboard


1> Reading data from general PasteBoard

if you want to read string from general pasteboard

NSString *strName = [UIPasteboard generalPasteboard].string

2> Writing  data to general PasteBoard

 [[UIPasteboard generalPasteboard]setString:@"Mittal"];

 UIImage * image=[UIImage imageWithContentsOfFile:@"FILE_PATH"];
 UIPasteboard * pasteboard=[UIPasteboard generalPasteboard];
[pasteboard setImage:image];

//Method 2
NSData *imageData = UIImagePNGRepresentation(image);
[pasteboard setData:imageData forPasteboardType:(NSString *)kUTTypePNG];

You can also set dictionary to the clipboard this way,

UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
pasteboard.persistent = NO;

NSMutableDictionary *text = [NSMutableDictionary dictionaryWithCapacity:1];
[text setValue:captionLabel.text forKey:(NSString *)kUTTypeUTF8PlainText];

NSMutableDictionary *image = [NSMutableDictionary dictionaryWithCapacity:1];
[image setValue:gratitudeImageView.image forKey:(NSString *)kUTTypePNG];

pasteboard.items = [NSArray arrayWithObjects:image,text, nil];


3> Create Custom PasteBoard

UIPasteboard *pasteboard = [UIPasteboard pasteboardWithName:@"customPasteBoard" create:YES];

 [pasteboard setPersistent:YES];
 //save the unique identifier string that we created earlier 
[pasteboard setString:@"Mittal"];

4> Remove PasteBoard

[UIPasteboard removePasteboardWithName:@"customPasteBoard"];