Share extension like whatsapp and telegram iOS

In this example project we shall try exactly to replicate the same behavior to our app share option, by sharing text, image or a link from another app.

How to create a share extension like whatsapp and telegram in iOS (objective-C)?
You might have wondered when to click on share on whats from an another app it loads a list of your recent contact list to share. In this example project we shall try exactly to replicate the same behavior to our app share option, by sharing text, image or a link from another app.

            screen-1                screen-2

Pre-requisites
Xcode
Objective-C
Basic knowledge on iOS table view
Basic knowledge on iOS collection view
Basic knowledge on iOS share extension

Getting Started
For setting up your basic app as in our example project refer this link . With your main application open in Xcode let’s begin to add share extension to the app. We shall use NSUserDefaults to share data from share extension to the main app.

Step 1. Add  share extension.
   First step is to add share extension to your main app. To add a share extension go to your project >> Targets , at the bottom of the page click on the plus button. Then select share extension in the options, click next, give a name for your share extension and add it your project.

Step 2. Configure app group.
  Next step is to configure your app groups so that the share extension can access your main app data when required. Go to your project >> target, there go to Capabilities option, Scroll until you find app group section. Switch the state to On condition. Enable your app group identifier so the your share and main app can share data between each other properly. ( On how to add app group identifier refer apple developer website for configure app group section).
Now do the same in your share extension (project >> share extension) as capabilities also. Switch the app group to on condition with its app group identifier ( Note: The app group identifier must be same as that of main app) and proceed to next step.

Step 3. Setup your Share story board.
Go to mainInterface.storyBoard, Drag and drop a UIViewcontroller and embed it in a UINavigationContoller. Next add a tableView inside the UIViewcontroller to load the list of user. Define the tableView properties and data in shareViewcontroller.m file. Add search to filter the user list based on name. Call the delegates and make the necessary UI arrangements as per the requirements.

Step 4. Specify the types supported by your extension.
Next step is to give instruction to the share extension to support the required type of contents that can be shared through it. Open the share extension info.plist add specify the NSExtesion key. An example key is illustrated here.

<!-- setup NSExtension --> 
<key>NSExtension</key> <dict> 
<key>NSExtensionAttributes</key> 
<dict> 
<key>NSExtensionActivationRule</key> 
<dict> <!-- Setup support for attachments with max count--> 
<key>NSExtensionActivationSupportsAttachmentsWithMaxCount</key> 
<integer>10</integer> <!-- Setup support for images with max image count -->
 <key>NSExtensionActivationSupportsImageWithMaxCount</key> 
<integer>10</integer> <!-- setup support for text -->
 <key>NSExtensionActivationSupportsText</key> <true/> 
<!-- Setup support for url--> 
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key> 
<integer>1</integer> 
</dict> 
</dict>

Step 5. Detect type of data shared.
Now we have to categories the shared contents based on the type of data that is being shared. It can be categorised in the following way,

NSMutableArray *pathSelectedArray;
  NSString *pathSelected;
  for (NSItemProvider *itemProvider in (
           (NSExtensionItem *)self.extensionContext.inputItems[0])
           .attachments) {
    NSLog(@"share type: %@", itemProvider);
    if ([itemProvider hasItemConformingToTypeIdentifier:@"public.plain-text"]) {
      //** if shared content is text **//
      [itemProvider
          loadItemForTypeIdentifier:@"public.plain-text"
                            options:nil
                  completionHandler:^(id item, NSError *error) {
                    if ([(NSObject *)item isKindOfClass:[NSString class]]) {
                      shareText =
                          [NSString stringWithFormat:@"%@", (NSString *)item];
                      NSLog(@"share itemProvider text: %@", shareText);
                    }
                  }];
    }
    //** if shared content is url **//
    if ([itemProvider hasItemConformingToTypeIdentifier:@"public.url"]) {
      [itemProvider
          loadItemForTypeIdentifier:@"public.url"
                            options:nil
                  completionHandler:^(id item, NSError *error) {
                    if ([(NSObject *)item isKindOfClass:[NSURL class]]) {
                      shareUrl =
                          [NSString stringWithFormat:@"%@", (NSURL *)item];
                      NSLog(@"share url: %@", shareUrl);
                    }
                  }];
    }
    //** if shared content is image **//
    if ([itemProvider hasItemConformingToTypeIdentifier:@"public.image"]) {
            [itemProvider loadItemForTypeIdentifier:@"public.image" options:nil completionHandler: ^(id item, NSError *error) {
        UIImage *sharedImage = nil;
                //** if shared content is image with url **//
                if([(NSObject*)item isKindOfClass:[NSURL class]]) {
        pathSelected = [NSString stringWithFormat:@"%@", (NSURL *)item];
        if (self.pathSelected.length != 0 ||
            ![DSUtilityManager stringIsNull:pathSelected]) {
          pathSelected = [DSUtilityManager neutraliseString:pathSelected];
          sharedImage = [UIImage
              imageWithData:[NSData dataWithContentsOfURL:(NSURL *)item]];
          [pathSelectedArray addObject:@{ @"mediaurl" : sharedImage }];
          NSLog(@"share pathSelected: %@", pathSelectedArray);
        } }else if([(NSObject*)item isKindOfClass:[UIImage class]]) {
            //** if shared content is just a image **//
            sharedImage = (UIImage*)item;
        [pathSelectedArray addObject:@{ @"mediaurl" : sharedImage }];
        NSLog(@"share UIImage: %@", sharedImage); }
    }];
  }
}

Step 6. Share content to the user.
Select a user from the list, In didSelectRowAtIndexPath save the content data to the NSUserDefaults. Here the NSUserDefaults is to be accessed using the app group identifier i.e.,[NSUserDefaults alloc]initWithSuiteName:@”group.yourappidentifier.apps”].

//** Access the userDefault **//
  NSUserDefaults *userInputs = [[NSUserDefaults alloc]
      initWithSuiteName:@"group.yourappidentifier.apps"];
  //** access data from pre-saved data from main app **//
  NSData *dataFetch = [userInputs objectForKey:@"feedData"];
  NSMutableArray *dataInApp = [[NSMutableArray alloc]
      initWithArray:[NSArray
                        arrayWithArray:[NSKeyedUnarchiver
                                           unarchiveObjectWithData:dataFetch]]];
  //** add new data thats being shared **//
  [dataInApp
      insertObject:[NSDictionary dictionaryWithDictionary:saveDataDetails]
           atIndex:0];
  //** archive data to update userDefault **//
  NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dataInApp];
  //** update userDefaults **// [userInputs setObject:data forKey:@"feedData"];
  [userInputs synchronize];
  //** dismiss share extension after saved **//
  [self.extensionContext completeRequestReturningItems:nil completionHandler:nil];

Step 7. Step up main app data.
Add data to the main app and save the data in userDefaults in the same way as in shareViewcontroller.m file . Save the data in didFinishLaunchingWithOptions appdelegate.m file.

//** Add data to userDefault **// 
NSUserDefaults* userInputs = [[NSUserDefaults alloc]initWithSuiteName:@"group.yourappidentifier.apps"]; 
if ([userInputs objectForKey:@"feedData"]==nil) { 
//** Set default data if userDefault is empty **// 
NSData *dataSave = [NSKeyedArchiver archivedDataWithRootObject:staticDataArray]; 
[userInputs setObject:dataSave forKey:@"feedData"]; [userInputs synchronize]; } 
//** Else load data from array saved from share extension **//

Step 8. Load saved data in tableView.
Unarchive the data saved in the userDefaults, add it to an array and the table view. Refer on how to load data to the tableView cell.

//** unarchive the data from userDefaults **// 
NSUserDefaults* userDefaults = [[NSUserDefaults alloc]initWithSuiteName:@"group.yourappidentifier.apps"];
 NSData *dataFetch = [userDefaults objectForKey:@"feedData"]; 
//** load data to an array **// 
_cardDetailsArray = [NSArray arrayWithArray:[NSKeyedUnarchiver unarchiveObjectWithData:dataFetch]];

Add refresh controller to the table view to refresh tableView to check if share extension updates the userDefaults with any new data.

//** setup refresh controller **//
    refreshControl = [[UIRefreshControl alloc] init];
    [refreshControl addTarget:self action:@selector(refreshHandle) forControlEvents:UIControlEventValueChanged];
    //** add the refresh controller to the tableView **//
    _timeLineTableView.refreshControl = refreshControl;
    refreshControl.backgroundColor = [UIColor colorWithRed:0.922 green:0.922 blue:0.922 alpha:1.00]; refreshControl.tintColor = [UIColor lightGrayColor];
    //** add refresh controller function **//
    -(void)refreshHandle{ NSUserDefaults* userDefaults = [[NSUserDefaults alloc]initWithSuiteName:@"group.yourappidentifier.apps"];
        NSData *dataFetch = [userDefaults objectForKey:@"feedData"];
        //** load data to an array **//
        _cardDetailsArray = [NSArray arrayWithArray:[NSKeyedUnarchiver unarchiveObjectWithData:dataFetch]];
        //** reload tableView **//
        [self.timeLineTableView reloadData];
        //** end refreshing **//
        [refreshControl endRefreshing];
    }

Step 9. Run the code.
Now build and run the main app first so that the app load with some pre-loaded data. Then run the share extension, load it with any app. Choose the content like image, text or link that is to be share, Click on yourApp share extension. Choose the user, share it to the main app.

Conclusion
The share extension shares the content to your app and loads it as post. Here in this project we are using userDefaults to save data, even the api call can also be used to save ad load data to your app. The final project can be downloaded from this link  .

 

Leave a Reply

Your email address will not be published. Required fields are marked *