Pages

Wednesday 21 March 2012

Sharing data among iOS applications using UIPasteboard

Hello Friends,
As iOS apps have their own sandbox and one app can't read data of other application, for security reason its look good and really its good.One day i got a requirement in which i need to share data of one app with other app.First i thought it is not possible in an environment like sandbox, i searched on google and got a luck on  stackoverflow saying use UIPasteboard but a programmer like me expect some code. That day i  did not get any thing more than a little luck saying don't worry it is possible using UIpasteboard so in this post i am going to talk about UIPasteboard and write some basic codes.

UIPasteboard:
   UIPasteboard is a class given in UIKit.framework.You can use it to share data within the application and with other applications.

I am using two application to demonstrate the use of UIPasteboard.
  1. PBWriter
  2. PBReader 
let's create first application named as PBWriter or you can name something else.This application take some input from user and save those in UIPasteboard.User Interface of this application look like this - 

Enter data in above fields, hit "Save in PB" button it will save the data in Pasteboard.Oh! i have not discussed any thing about code. let's write code -

You can use any of following methods to create/get Pasteboard object, i am using "pasteboardWithName:create:"
  • +generalPasteboar //use this to get system pasteboard
  • +pasteboardWithName:create: //use this to create your own pasteboard

//use reverse DNS notation to keep you Paste board unique 
NSString *PBNAME = @"com.codingForBugs.PBDemo.PBDemo";


 UIPasteboard *pb = [UIPasteboard pasteboardWithName:PBNAME create:YES];//create a new PB if does not exists 

By default custom pasteboards are not persistent, you need to make it manually.If not required in your case just ignore it.

//pass yes to make pasteboard persistent 
[pb setPersistent:YES];


If you are not setting Persistent  property to YES, remamber that pastboard will be removed when your application quit.Now we have pasteboard and we need to write user information in it.

Note:Pasteboard will be removed when application uninstalled not matter it is persistent or not. 

There are some predefine properties in which you can write your data like string, strings, url,image, items etc.For example you have only one string you can use "string" property of UIPasteboard. If you want to save more than one item than better to use items properties like - 
    NSMutableArray *pbValues = [[NSMutableArray alloc] init];
    NSDictionary *d1 = [NSDictionary dictionaryWithObject:name.text forKey:@"name"];
    NSDictionary *d2 = [NSDictionary dictionaryWithObject:s1Value.text forKey:@"dob"];
    NSDictionary *d3 = [NSDictionary dictionaryWithObject:s2Value.text forKey:@"age"];
    NSDictionary *d4 = [NSDictionary dictionaryWithObject:s3Value.text forKey:@"height"];
    [pbValues addObject:d1];
    [pbValues addObject:d2];
    [pbValues addObject:d3];
    [pbValues addObject:d4];
    
    //save all items in pasteboard
    [pb setItems:pbValues];
When you will hit "Save in PB" it call a method "saveButtonClicked:", this method look like this
- (IBAction)saveButtonClicked:(id)sender {
    //get paste board 
    
    UIPasteboard *pb = [UIPasteboard pasteboardWithName:PBNAME create:YES];//create a new PB if does not exists 
    
    //make PB persistent. PB will be deleted when its owner application uninstalled
    [pb setPersistent:YES];
    
    //save values in PB with unique key so thet other application can read it
    NSLog(@"name = %@",name.text);
    NSMutableArray *pbValues = [[NSMutableArray alloc] init];
    NSDictionary *d1 = [NSDictionary dictionaryWithObject:name.text forKey:@"name"];
    NSDictionary *d2 = [NSDictionary dictionaryWithObject:nameValue.text forKey:@"dob"];
    NSDictionary *d3 = [NSDictionary dictionaryWithObject:ageValue.text forKey:@"age"];
    NSDictionary *d4 = [NSDictionary dictionaryWithObject:heightValue.text forKey:@"height"];
    [pbValues addObject:d1];
    [pbValues addObject:d2];
    [pbValues addObject:d3];
    [pbValues addObject:d4];
    
    //save all items in pasteboard
    [pb setItems:pbValues];
    
}

If you calls setItems: again, it overwrites previous values to prevent it use addItems: as [pb addItems:newValues]
Now we have finish the writer part we need to write a reader application that will read the data save in pasteboard. Reader app ui look like this - 
When you will hit the "Read PB" button one pop-up will come displaying whatever information we have saved in pasteboard.To read data first we need to get the pasteboard, we will retrieve dat using any of following function - 
  • dataForPasteboardType:
  • string
  • strings
  • items and so on 


Data will be returned in form of NSData and of particular type same as properties. For example if you are assigning value to string property it will return string, when we access using other method, we need to convert it in string from NSData. When you will hit "Read PB" button "- (IBAction)readPB:(id)sender" called this method look like this -
- (IBAction)readPB:(id)sender {
    //get pasteboard with predefine name
    UIPasteboard *pb = [UIPasteboard pasteboardWithName:PBNAME create:NO];//no because we doesn't want to create a new one 
    if (pb) {
        NSArray *dataArray = [pb items];
        NSDictionary *name = [dataArray objectAtIndex:0];
        //valuesInPb use to create message text
        NSString *valuesInPb = [NSString stringWithFormat:@"Name = %@\n",
                                [[NSString alloc] initWithData:[name valueForKey:@"name"] encoding:NSUTF8StringEncoding]];
        NSDictionary *info = [dataArray objectAtIndex:1];
        valuesInPb = [NSString stringWithFormat:@"%@D.O.b = %@\n",valuesInPb,
                      [[NSString alloc] initWithData:[info valueForKey:@"dob"] encoding:NSUTF8StringEncoding]];
        NSDictionary *info1 = [dataArray objectAtIndex:2];
        valuesInPb = [NSString stringWithFormat:@"%@Age = %@\n",valuesInPb,
                      [[NSString alloc] initWithData:[info1 valueForKey:@"age"] encoding:NSUTF8StringEncoding]];
        NSDictionary *info2 = [dataArray objectAtIndex:3];
        valuesInPb = [NSString stringWithFormat:@"%@Height = %@\n",valuesInPb,
                      [[NSString alloc] initWithData:[info2 valueForKey:@"height"] encoding:NSUTF8StringEncoding]];
        [self showText:valuesInPb target:self];
        NSLog(@"%i",[dataArray count]);
    }else{
        [self showText:@"PB doesn't exists.\nYou should run PBWritter app first" target:self];
    }
}


//this method is use to display the alert vew
-(void)showText:(NSString*)textMessage target:(id)target{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"pbReader" message:textMessage delegate:target cancelButtonTitle:@"OK" otherButtonTitles: nil];
    [alert show];
    [alert release];
}
I think it  may help you, plese leave you comments.bye bye!

15 comments:

  1. Very cool, I except you write more good articles :).

    ReplyDelete
    Replies
    1. Do not except him, better encourage

      Delete
  2. Hai . i have a doubt . can u please rectify it

    Scenario 1 :
    kOpenUDIDRedundancySlots = 100;
    for (int n=0; n<kOpenUDIDRedundancySlots; n++) {
    UIPasteboard* slotPB = [UIPasteboard pasteboardWithName:slotPBid create:NO];
    }

    in Scenario1 will it generate 100 pasteBoards

    Scenario 2 :
    UIPasteboard* slotPB = [UIPasteboard pasteboardWithName:availableSlotPBid create:YES];

    after some block of code i have written

    UIPasteboard* slotPB = [UIPasteboard pasteboardWithName:slotPBid create:NO];

    in Scenario 2 : if slotPBid = availableSlotPBid
    will it get the existing pasteboard r creates a new one ?

    ReplyDelete
    Replies
    1. In Scenario 1:

      It wil not create 100 pasteBoard , because you have passed "NO" in method call, so it not create new pasteBoard, If it will find any pasteBoard with name "slotPBid", return that otherwise it will return system pasteBoard

      In Scenario 2:

      It will get existing one, if you have not removed the pasteBoard with name "availableSlotPBid"

      Delete
  3. Will this work with iOS 7?

    ReplyDelete
  4. iOS software development kit (SDK) to create applications for Apple mobile devices. The SDK includes tools and interfaces for developing, installing, running and testing apps.

    iOS Applications Development

    ReplyDelete
  5. Is this UIPasteboard will work in iOS 7? Because when I am using this then it is not working in iOS 7.

    ReplyDelete
  6. Your mentioning that a pasteboard is removed when the app is removed. It tried it, and when reinstalling the app, the pasteboard is still there.

    ReplyDelete
  7. I have also observed the same behaviour, pasteboard is still there even if app is uninstalled.

    ReplyDelete
    Replies
    1. CC: Fille,
      Guy you need to name your pasteboard after you app bundle name like:
      if your app bundle identifier is: com.test.MyApp

      Then UIPasteBoard name should be: @"com.test.MyApp.MyPasteBoard"

      Delete