5

I tried to do like this, but it does not work, the text is not copied

 if let urlScheme = URL(string: "instagram-stories://share") {

 if UIApplication.shared.canOpenURL(urlScheme) {
                
 let imageData: Data = UIImage(systemName:"pencil.circle.fill")!.pngData()!
 let items:[String: Any] = ["public.utf8-plain-text": "text","com.instagram.sharedSticker.backgroundImage": imageData]
    
 UIPasteboard.general.setItems([items])
    
 UIApplication.shared.open(urlScheme, options: [:], completionHandler: nil)
 }}

I would really appreciate any advice

  • 1
    can you add some more code on how you create and initialize your imageData and urlScheme objects ? And what is the goal - what should be in your pasteboard and what should be shared to instagram ? – Shawn Frank Jan 18 '22 at 03:34
  • in the pasteboard should be some link that can be inserted (i.e., click on the screen until the paste button appears) and a background image for the story – Maksim Panteleev Jan 18 '22 at 06:01

2 Answers2

2

2 things I can think of:

First, I am not sure the below data in your array can be properly handled by pastebin

let items:[String: Any] = ["public.utf8-plain-text": "text","com.instagram.sharedSticker.backgroundImage": imageData]

Next it seems that the activity of sharing causes data in the PasteBoard to be lost so I can offer the solution to put valid data into the PasteBoard (I am using string for example, you can use something else" from the completion handler of your sharing action, something like this might solve it:

UIApplication.shared.open(urlScheme, options: [:]) { (_) in
    UIPasteboard.general.string =
        "click on the screen until the paste button appears: https://google.com"
}

EDIT

It seems your set up was right and on reading the docs, IG stories should handle the Paste automatically as it seems to check the pasteboard when you execute this url scheme: instagram-stories://share - so it seems IG checks the pasteboard and performs a paste programmatically and that is why the pasteboard gets cleared.

Maybe because the image you choose is black on the black instagram background, it seems nothing is shared but with some proper image the result seems fine.

The other thing I noticed after reading their docs, they do not allow you to set captions anymore, I cannot find this key anymore public.utf8-plain-text

Another idea I can offer to share text is to convert text into an image and add it as a sticker as the sticker layer comes on top of the background image layer.

You can find multiple ways to convert text to an image and it is not relevant to your solution, here is one way I used

So bringing the code together, I have this:

// Just an example to convert text to UIImage 
// from https://stackoverflow.com/a/54991797/1619193
extension String {
    
    /// Generates a `UIImage` instance from this string using a specified
    /// attributes and size.
    ///
    /// - Parameters:
    ///     - attributes: to draw this string with. Default is `nil`.
    ///     - size: of the image to return.
    /// - Returns: a `UIImage` instance from this string using a specified
    /// attributes and size, or `nil` if the operation fails.
    func image(withAttributes attributes: [NSAttributedString.Key: Any]? = nil, size: CGSize? = nil) -> UIImage? {
        let size = size ?? (self as NSString).size(withAttributes: attributes)
        return UIGraphicsImageRenderer(size: size).image { _ in
            (self as NSString).draw(in: CGRect(origin: .zero, size: size),
                                    withAttributes: attributes)
        }
    }
}

// Then inside some function of yours
func someFunction() {
    if let urlScheme = URL(string: "instagram-stories://share") {
        
        if UIApplication.shared.canOpenURL(urlScheme) {
            
            let imageData: Data = UIImage(named: "bg")!.pngData()!
            
            let textImage: Data = "Shawn Test".image(withAttributes: [.foregroundColor: UIColor.red,
                                                                      .font: UIFont.systemFont(ofSize: 30.0)],
                                                     size: CGSize(width: 300.0, height: 80.0))!.pngData()!
            
            let items = ["com.instagram.sharedSticker.stickerImage": textImage,
                         "com.instagram.sharedSticker.backgroundImage": imageData]
            
            UIPasteboard.general.setItems([items])
            
            UIApplication.shared.open(urlScheme, options: [:], completionHandler: nil)
        }
    }
}

I then see this in IG stories with correct background and text as sticker which can be moved.

Using Swift to send data to Instagram stories using UIPasteBoard

Only downside of using the sticker is you cannot edit the text in Instagram.

Shawn Frank
  • 4,381
  • 2
  • 19
  • 29
  • Thanks. I tried to pass data inside the completion handler, it doesn't work either ( the data in the array is ok, I checked, I can share the picture and if you don’t open instagram, then the text can be pasted. It looks like instagram erases all data in pasteboard after opening – Maksim Panteleev Jan 18 '22 at 06:57
  • Yes you are right, I notice as soon as the IG app gets opened, it says Instagram has pasted this data. – Shawn Frank Jan 18 '22 at 07:37
  • @MaksimPanteleev - please see my updated answer. – Shawn Frank Jan 18 '22 at 08:10
  • 1
    thank you very much, this option does not suit me, it is necessary that the user can create a clickable link during the publication of the story, and the text on the sticker cannot be made a clickable link – Maksim Panteleev Jan 18 '22 at 11:46
1

Regarding the research looks like the only one workaround to have a text/link copied in the Pasteboard when IG Story is opened is to use:

UIPasteboard.general.string = "your link here"

but you need to do it with a delay - like:

UIApplication.shared.open(instagramStoryURL, options: [:]) { success in
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
        UIPasteboard.general.string = "your link here"
    }
}

to try to be sure the it won't override:

UIPasteboard.general.items

that contains, for example, "com.instagram.sharedSticker.stickerImage"

Also, please be careful with a delay - as iOS has some privacy restrictions to allow copy data to UIPasteboard when the App is in background (based on the tests we have less than 1 second to do that.

It means that you could try to copy the link this way:

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(appMovedToBackground), name: UIApplication.willResignActiveNotification, object: nil)
}

@objc func appMovedToBackground() {
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.75) {
        UIPasteboard.general.string = "your link here"
    }
}

Anyway, there is one obvious inconvenience.

Each time you try to call "instagram-stories://share" API the first time - you face a system popup that asks for the permisson to allow to open Instagram and also to allow paste the data.

In this case we'll lose, for example, "com.instagram.sharedSticker.stickerImage" data as by the delay it will be overrided by UIPasteboard.general.string.

But we could to make it expected for users by any UI/UX solution with instructions/guide.