Search code examples
iosobjective-ciphone-5

How can I Asynchronously load an image URL using UIPasteboard for animated .gif


I have a UIButton on my view and here is the code when I press that button

- (IBAction)sendSMS:(UIButton *)sender 
{
    NSData *gifImage = [[NSData alloc] initWithContentsOfURL:url];

    UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard];
    pasteBoard.persistent = YES;
    //pasteBoard.image = self.messageViewImage;
    [pasteBoard setData:gifImage forPasteboardType:@"com.compuserve.gif"];

    NSString *phoneToCall = @"sms:";
    NSString *phoneToCallEncoded = [phoneToCall     stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
    NSURL *url = [[NSURL alloc] initWithString:phoneToCallEncoded];
    [[UIApplication sharedApplication] openURL:url];
}

I'm trying to copy an animated gif to be pasted in an mms message. How can I accomplish this task asynchronously? Current when I hit the button it takes about 3 seconds and the button has a blue background and then the mms message pops up. How can I make this a better experience for the user?


Solution

  • One way to achieve your goal is to use the MessageUI framework to display the MFMessageComposeViewController with the GIF added as an attachment. Using this approach, you never have to switch the user to the Messages app—it's all done inside your own app. Here is how you do that.

    The first step is to add the following frameworks to your project:

    • MessageUI.framework
    • MobileCoreServices.framework

    In your view controller, add the following imports:

    #import <MessageUI/MessageUI.h>
    #import <MobileCoreServices/UTCoreTypes.h>
    

    Next, define property for the MFMessageComposeViewController:

    @property (nonatomic, strong) MFMessageComposeViewController *messageController;
    

    We're defining a property so that we can handle the user hitting Cancel within the MMS view later.

    In the view controller's viewDidLoad, add this:

    self.messageController = [[MFMessageComposeViewController alloc] init];
    self.messageController.messageComposeDelegate = self;
    

    You want your sendSMS method to look like this:

    - (IBAction)sendSMS:(UIButton *)sender 
    {
        [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
            NSData *gifData = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
    
            if ([MFMessageComposeViewController canSendText]) {
                [self.messageController addAttachmentData:gifData typeIdentifier:(__bridge NSString *)kUTTypeGIF filename:@"animated.gif"];
    
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self presentViewController: self.messageController animated:YES completion:NULL];
                });
            }
    
            [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        });
    }
    

    In this method, the GIF is downloaded in the background and assigned to gifData. gifData is then added as attachment to the message composer view and the composer view is displayed to the user.

    When the user sends the MMS or hits the Cancel button, messageComposeViewController:didFinishWithResult: is called. In that method, you need to dismiss the message composer modal view:

    - (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
    {
        [self.smsComposer dismissViewControllerAnimated:YES completion:NULL];
    }
    

    The result parameter will either be MessageComposeResultCancelled, MessageComposeResultSent, or MessageComposeResultFailed depending upon what the user did.