Closed Nightbl927 closed 1 month ago
attached what I believe to be the error is:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Share_Extension.ShareViewController openURL:]: unrecognized selector sent to instance 0x10201f400'
FROM
private func redirectToHostApp() {
// ids may not loaded yet so we need loadIds here too
loadIds()
let url = URL(string: "\(kSchemePrefix)-\(hostAppBundleIdentifier):share")
var responder = self as UIResponder?
let selectorOpenURL = sel_registerName("openURL:")
while (responder != nil) {
if (responder?.responds(to: selectorOpenURL))! {
_ = responder?.perform(selectorOpenURL, with: url)
}
responder = responder!.next
}
extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
I have the same issue; file sharing in iOS 18 is unresponsive and doesn't show any error messages, but it works fine in iOS 16 and 17.
Any news? I'm having the same issue. @Nightbl927
Any news? I'm having the same issue. @Nightbl927
No news. I haven't found any way to resolve this. Unfortunately, I am not too familiar with Swift to troubleshoot it myself. I was able to pinpoint the issue to let selectorOpenURL = sel_registerName("openURL:")
. I believe this no longer works in iOS 18.
I think i found the solution here: This is an external link ](https://stackoverflow.com/questions/27506413/share-extension-to-open-containing-app/78975759#78975759) doing more testing right now....
@objc @discardableResult private func openURL(_ url: URL) -> Bool {
var responder: UIResponder? = self
while responder != nil {
if let application = responder as? UIApplication {
if #available(iOS 18.0, *) {
application.open(url, options: [:], completionHandler: nil)
return true
} else {
return application.perform(#selector(openURL(_:)), with: url) != nil
}
}
responder = responder?.next
}
return false
}
I think i found the solution here: This is an external link ](https://stackoverflow.com/questions/27506413/share-extension-to-open-containing-app/78975759#78975759) doing more testing right now....
@objc @discardableResult private func openURL(_ url: URL) -> Bool { var responder: UIResponder? = self while responder != nil { if let application = responder as? UIApplication { if #available(iOS 18.0, *) { application.open(url, options: [:], completionHandler: nil) return true } else { return application.perform(#selector(openURL(_:)), with: url) != nil } } responder = responder?.next } return false }
How did your testing go? @sstadtl?
it works in ip14 iOS18, Sim ip15 iOS 17.5.1.
this is my new code in ShareViewController.swift:
private func redirectToHostApp(type: RedirectType) {
let url = URL(string: "ShareMedia-\(hostAppBundleIdentifier)://dataUrl=\(sharedKey)#\(type)")
var responder = self as UIResponder?
// https://stackoverflow.com/questions/27506413/share-extension-to-open-containing-app/78975759#78975759
// https://github.com/KasemJaffer/receive_sharing_intent/issues/324
if #available(iOS 18.0, *) {
while responder != nil {
if let application = responder as? UIApplication {
application.open(url!, options: [:], completionHandler: nil)
}
responder = responder?.next
}
} else {
let selectorOpenURL = sel_registerName("openURL:")
while (responder != nil) {
if (responder?.responds(to: selectorOpenURL))! {
let _ = responder?.perform(selectorOpenURL, with: url)
}
responder = responder!.next
}
extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
}
But for historic reasons i use a very custom "ShareViewController.swift:". so i am unsure this works by just overwriting this single function for everyone.
as "redirectToHostApp" is private i think there is more to do...
Thank you @sstadtl , I will see if this works for me.
is there any update on this ? @sstadtl
Yes application will not be in scope with the code as is. However, changing application.open(url!, options: [:], completionHandler: nil)
to UIApplication.shared.open(url!, options: [:], completionHandler: nil)
should work
Yes application will not be in scope with the code as is. However, changing
application.open(url!, options: [:], completionHandler: nil)
toUIApplication.shared.open(url!, options: [:], completionHandler: nil)
should work
Not working for me
i am still not able to receive files from ios 18 iphone to my flutter app
Yes application will not be in scope with the code as is. However, changing
application.open(url!, options: [:], completionHandler: nil)
toUIApplication.shared.open(url!, options: [:], completionHandler: nil)
should workNot working for me
i am still not able to receive files from ios 18 iphone to my flutter app
I am using it to receive shared links and text from Safari and have not tested with files yet. Could you see if that works for you?
It works for me! Thank you!
completeRequest
may need to be called outside of the if statement.
import receive_sharing_intent
import UIKit
import MobileCoreServices
import Photos
@available(swift, introduced: 5.0)
open class ShareViewController: UIViewController {
var hostAppBundleIdentifier = ""
var appGroupId = ""
open override func viewDidLoad() {
super.viewDidLoad()
loadIds()
}
open override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
guard
let content = extensionContext!.inputItems[0] as? NSExtensionItem,
let attachments = content.attachments,
let attachment = attachments.first
else { return }
if !attachment.hasItemConformingToTypeIdentifier(UTType.fileURL.identifier) { return }
attachment.loadItem(forTypeIdentifier: UTType.fileURL.identifier) { [weak self] (data, error) in
guard let s = self, let url = data as? URL else { return }
s.handleMedia(forFile: url)
}
}
private func loadIds() {
let shareExtensionAppBundleIdentifier = Bundle.main.bundleIdentifier!
let lastIndexOfPoint = shareExtensionAppBundleIdentifier.lastIndex(of: ".")
hostAppBundleIdentifier = String(shareExtensionAppBundleIdentifier[..<lastIndexOfPoint!])
let defaultAppGroupId = "group.\(hostAppBundleIdentifier)"
let customAppGroupId = Bundle.main.object(forInfoDictionaryKey: kAppGroupIdKey) as? String
appGroupId = customAppGroupId ?? defaultAppGroupId
}
private func handleMedia(forFile url: URL) {
let fileName = url.lastPathComponent
let newPath = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupId)!.appendingPathComponent(fileName)
if !copyFile(at: url, to: newPath) { return }
let newPathDecoded = newPath.absoluteString.removingPercentEncoding!;
saveAndRedirect(data: SharedMediaFile(
path: newPathDecoded,
mimeType: url.mimeType(),
type: .file
))
}
private func saveAndRedirect(data: SharedMediaFile) {
let userDefaults = UserDefaults(suiteName: appGroupId)
userDefaults?.set(toData(data: [data]), forKey: kUserDefaultsKey)
userDefaults?.set(nil, forKey: kUserDefaultsMessageKey)
userDefaults?.synchronize()
redirectToHostApp()
}
private func redirectToHostApp() {
loadIds()
let url = URL(string: "\(kSchemePrefix)-\(hostAppBundleIdentifier):share")
var responder = self as UIResponder?
if #available(iOS 18.0, *) {
while responder != nil {
if let application = responder as? UIApplication {
application.open(url!, options: [:], completionHandler: nil)
}
responder = responder?.next
}
} else {
let selectorOpenURL = sel_registerName("openURL:")
while (responder != nil) {
if (responder?.responds(to: selectorOpenURL))! {
_ = responder?.perform(selectorOpenURL, with: url)
}
responder = responder!.next
}
}
extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
private func copyFile(at srcURL: URL, to dstURL: URL) -> Bool {
do {
if FileManager.default.fileExists(atPath: dstURL.path) {
try FileManager.default.removeItem(at: dstURL)
}
try FileManager.default.copyItem(at: srcURL, to: dstURL)
} catch (let error) {
print("Cannot copy item at \(srcURL) to \(dstURL): \(error)")
return false
}
return true
}
private func toData(data: [SharedMediaFile]) -> Data {
let encodedData = try? JSONEncoder().encode(data)
return encodedData!
}
}
extension URL {
public func mimeType() -> String {
if #available(iOS 14.0, *) {
if let mimeType = UTType(filenameExtension: self.pathExtension)?.preferredMIMEType {
return mimeType
}
} else {
if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, self.pathExtension as NSString, nil)?.takeRetainedValue() {
if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() {
return mimetype as String
}
}
}
return "application/octet-stream"
}
}
I use the share extension for sharing files and text in my application. I've been struggling with the problem for a few days but still haven't found a solution. I've tried similar suggestions as above but without success. My ShareViewController is as it is currently used in the package. Does anyone have a different update for this situation?
@aleynaak have you updated the ShareViewController as suggested by @malt03 above? I have not yet updated and forked the code but if someone is willing to do that who has gotten it to work, that could also help.
@Nightbl927 I've updated the controller. Please merge https://github.com/KasemJaffer/receive_sharing_intent/pull/328
@Nightbl927 I've updated the controller. Please merge #328
Unfortunately, I am unable to merge it. I was hoping for someone to fork and have @aleynaak pull from that repo.
Thank you for your support. I solved the problem. It was a problem with my URLShemes. When I fixed it, the problem disappeared. @Nightbl927 @dmitry-kotorov
Thank you for your support. I solved the problem. It was a problem with my URLShemes. When I fixed it, the problem disappeared. @Nightbl927 @dmitry-kotorov
Good to hear!
We have tested current master with PR https://github.com/KasemJaffer/receive_sharing_intent/pull/328 and it seems to work correct ✅. Pls consider releasing new version
Release a new version, please :)
I just published PR https://github.com/KasemJaffer/receive_sharing_intent/pull/328 under version 1.8.1
Thank you all and sorry for the delay
Is anyone else having issues sharing on an iOS 18 device? I still get the icon to share to the app, and it appears to be fine on the app that is doing the sharing but it seems like the app that is receiving the sharing never opens and receives the shared data.