How to navigate Share Extension to host app in Swift?

1.2k views Asked by At

How to navigate Share Extension to host app in Swift after getting URL from ShareExtension?

import UIKit
import Social
import MobileCoreServices

class ShareViewController: UIViewController {

    let sharedKey = "shareappKey"

    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationItem.title = "Picked URL"        
        getURL()
    }

    @IBAction func nextAction(_ sender: Any) {

        self.redirectToHostApp()
    }

    @IBAction func cancelAction(_ sender: Any) {

        self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
    }

    func redirectToHostApp() {

        let url = URL(string: "SelectedURL:\(sharedKey)")
        var responder = self as UIResponder?
        let selectorOpenURL = sel_registerName("openURL:")
        while (responder != nil) {
            if (responder?.responds(to: selectorOpenURL))! {
                let _ = responder?.perform(selectorOpenURL, with: url)
            }
            responder = responder!.next
        }
        self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
    }

    func getURL() {

        if let item = extensionContext?.inputItems.first as? NSExtensionItem {
            if let itemProvider = item.attachments?.first {
                if itemProvider.hasItemConformingToTypeIdentifier("public.url") {
                    itemProvider.loadItem(forTypeIdentifier: "public.url", options: nil, completionHandler: { (url, error) -> Void in

                        if let error = error {
                            print("error :-", error)
                        }
                        if (url as? NSURL) != nil {
                            // send url to server to share the link
                            do {
                                if (url as? URL) != nil {
                                    // do what you want to do with shareURL
                                    print("Selected URL :- ", url as Any)
                                    print(url as Any)

                                    let dict: [String : Any] = ["imgData" :  url as Any, "name" : "Added" as Any]
                                    print(dict)
                                    let userDefault = UserDefaults.init(suiteName: "group.com.abcd.shareapp")
                                    userDefault?.set(dict, forKey: self.sharedKey)
                                    userDefault?.synchronize()

                                   // Here I got Struct 
                                }
                            }catch let err{
                                print(err)
                            }
                        }
                        self.extensionContext?.completeRequest(returningItems: [], completionHandler:nil)
                    })
                }
            }
        }
    }    
}


// Host App
import UIKit

class ViewController: UIViewController {

    var urlString = String()

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        let userDefault = UserDefaults.standard
        userDefault.addSuite(named: "group.com.abcd.shareapp")

        if let dict = userDefault.value(forKey: "img") as? NSDictionary{

            let data = dict.value(forKey: "imgData") as! Data
            let str = dict.value(forKey: "name") as! String
            print("Data is :- ", data)
            print("Str is :- ", str)
            userDefault.removeObject(forKey: "img")
            userDefault.synchronize()

            // Here i need to get that URL from Share Extention
        }
    }
}

Error

2019-07-15 22:01:15.045361+0530 LearingAppShare[3183:73775] [User Defaults] Attempt to set a non-property-list object { imgData = "https://m.jagran.com/lite/cricket/headlines-sachin-tendulkar-son-arjun-tendulkar-picked-for-rs-5-lakh-for-t20-mumbai-league-19192257.html"; name = Added; } as an NSUserDefaults/CFPreferences value for key URLKey 2019-07-15 22:01:15.047424+0530 LearingAppShare[3183:73775]


Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object { imgData = "https://m.jagran.com/lite/cricket/headlines-sachin-tendulkar-son-arjun-tendulkar-picked-for-rs-5-lakh-for-t20-mumbai-league-19192257.html"; name = Added; } for key URLKey'

1

There are 1 answers

3
G Sreekanth On

I have done answer on own Question.

You can store in dictionary. But UserDefaults can't save dictionary with custom data types like Image or URL . So you need to convert dictionary to Data first before saving in defaults

import UIKit
import Social
import MobileCoreServices

class ShareViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationItem.title = "Picked URL"        
        getURL()
    }

    @IBAction func nextAction(_ sender: Any) {

        self.redirectToHostApp()
    }

    @IBAction func cancelAction(_ sender: Any) {

        self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
    }

    func redirectToHostApp() {

        let url = URL(string: "YourOwnURLscheme:\(sharedKey)")
        var responder = self as UIResponder?
        let selectorOpenURL = sel_registerName("openURL:")
        while (responder != nil) {
            if (responder?.responds(to: selectorOpenURL))! {
                let _ = responder?.perform(selectorOpenURL, with: url)
            }
            responder = responder!.next
        }
        self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
    }

    func getURL() {

        if let item = extensionContext?.inputItems.first as? NSExtensionItem {
            if let itemProvider = item.attachments?.first {
                if itemProvider.hasItemConformingToTypeIdentifier("public.url") {
                    itemProvider.loadItem(forTypeIdentifier: "public.url", options: nil, completionHandler: { (url, error) -> Void in
                        if let error = error {
                            print("error :-", error)
                        }
                        if (url as? NSURL) != nil {
                            // send url to server to share the link
                                                    do {
                            var urlData: Data!
                            if let url = url as? URL{
                                urlData = try Data(contentsOf: url)
                            }
                            let dict: [String : Any] = ["urlData" :  urlData as Any, "name" : self.contentText as Any]
                            print(dict)
                            let userDefault = UserDefaults(suiteName: "group.com.abcd.sharecontent1")
                            userDefault?.set(dict, forKey: "storedURLData")
                            userDefault?.synchronize()
                        }catch let err{
                            print(err)
                        }
                       }
                    })
                }
            }
        }
    }    
}


// Host App
import UIKit

class ViewController: UIViewController {

    @IBOutlet var imgView: UIImageView!
    @IBOutlet var lblText: UILabel!

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        let userDefault = UserDefaults(suiteName: "group.com.abcd.sharecontent1")

        if let dict = userDefault?.value(forKey: "storedURLData") as? NSDictionary{

            let data = dict.value(forKey: "urlData") as! Data
            let str = dict.value(forKey: "name") as! String
            print("Data is :- ", data)
            print("str is :- ", str)

            self.lblText.text = str

            userDefault?.removeObject(forKey: "storedURLData")
            userDefault?.synchronize()
        }
    }
}