Sharing image and text to Facebook Messenger with

2019-02-25 11:58发布

问题:

Question

What changes to the code below must be made to ensure Messenger plays nicely with UIActivityViewController and shares both the image and text, or at the very least, the image?


Background

I am using UIActivityViewController to share text and images from my app and send them to email, messages and other sharing apps. UIActivityViewController is great and works in a simple and standard way with most apps… but, I’m having issues with Messenger (Facebook Messenger) which doesn’t want to cooperate.

In the below code, I tap a UIButton which takes a snapshot image of the screen, turns it into a .png, and then sends the prepared image (imageShare) along with my prepared text (textShare) to the UIActivityViewController. This simple method allows my app to successfully share to email, messages and many other sharing apps except Messenger.

(Side note, Facebook is only able to share the prepared image (imageShare) but not the text.)


Issues

These are the problems when trying to share with UIActivityViewController to Messenger :

  • When sharing activityItems: [textShare, imageShare]

    • Messenger only sends the shared text.
  • When sharing activityItems: [textShare]

    • The option to share to Messenger is not even available in UIActivityViewController.
  • When sharing activityItems: [imageShare]

    • An error is displayed: “Couldn't Load Content. There was a problem while loading your content. Please try again.”

Code

@IBAction func myButton(sender: UIButton) {

    // Take snapshot of screen
    let imageSnapshot: UIImage!
    UIGraphicsBeginImageContextWithOptions(self.view.frame.size, false, 0)
    self.view.drawViewHierarchyInRect(CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height), afterScreenUpdates: false)
    imageSnapshot = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    // Prepare text to share
    let textShare: String!
    textShare = "This is my original text."

    // Prepare image to share
    let imageShare: NSData
    imageShare = UIImagePNGRepresentation(imageSnapshot)!

    // Share text and image
    let activity = UIActivityViewController(activityItems: [textShare, imageShare], applicationActivities: nil)
    if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
        self.presentViewController(activity, animated: true, completion: nil)
    }

}

Image

iOS presenting the UIActivityViewController with available applications.

回答1:

Try to use UIImage instead NSData. You can convert UIImage to AnyObject and add to your array.

Also look at this question: Sharing image using UIActivityViewController



回答2:

let textShare = "This is my original text."
var shareObject = [AnyObject]()
if textShare != nil {
    shareObject.append(textShare as AnyObject)
}

let Yourimage = UIImage(named: "image.png")
let imageData = UIImagePNGRepresentation(Yourimage!) as NSData? 

if let data = imageData {
    shareObject.append(data)
}

if shareObject.count > 0 { // check condition for text and image
    let activityViewController = UIActivityViewController(activityItems: shareObject, applicationActivities: nil)
    activityViewController.popoverPresentationController?.sourceView = self.view
    present(activityViewController, animated: true, completion: nil)
}


回答3:

So in the end what was needed was an extra step of converting NSData back into UIImage.

Note, the one issue with this approach of converting NSData back into UIImage is that it produces image quality that is either lossless (i.e. Message and Mail) or lossy (i.e. Notes, Photos, Messenger).

Interestingly Messages, Mail, and a variety of third party sharing apps were quite content sharing the NSData in the UIActivityViewController whereas Messenger would just not tolerate it. (I'd be interested to understand why exactly?)


The changes

From this:

    // Prepare image to share
    let imageShare: NSData
    imageShare = UIImagePNGRepresentation(imageSnapshot)!

To that:

    // Prepare image to share
    let imageShareData: NSData
    imageShareData = UIImagePNGRepresentation(imageSnapshot)!
    let imageShare = UIImage(data: imageShareData)!

The final working code

@IBAction func myButton(sender: UIButton) {

    // Take snapshot of screen
    var imageSnapshot: UIImage!
    UIGraphicsBeginImageContextWithOptions(self.view.frame.size, false, 0)
    self.view.drawViewHierarchyInRect(CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height), afterScreenUpdates: false)
    imageSnapshot = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    // Prepare text to share
    let textShare: String!
    textShare = "This is my original text."

    // Prepare image to share
    let imageShareData: NSData
    imageShareData = UIImagePNGRepresentation(imageSnapshot)!
    let imageShare = UIImage(data: imageShareData)!

    // Share text and image
    let activity = UIActivityViewController(activityItems: [textShare, imageShare], applicationActivities: nil)
    if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
        self.presentViewController(activity, animated: true, completion: nil)
    }

}