Обновление: кажется, что это поведение не разрешено в iOS, несмотря на то, что популярные приложения, такие как CHATGPT, разрешают это делать ... Чтобы обойти это, теперь я просто передаю URL к приложению, когда значок приложения нажимается с общего листа, а затем отправляю уведомление пользователю, которое говорит им, чтобы щелкнуть его, чтобы продолжить. Я думаю, что это юридическое поведение в соответствии с руководящими принципами Apple Dev, но кто знает больше. Когда пользователь делится веб -страницей через общий лист iOS, нажатие на расширение действия моего приложения должно запустить приложение и передать текущий URL -адрес для отображения. Я установил пользовательскую схему URL («MyApp») в своих типах URL. Например, когда я печатаю myApp: // share? Url = example.com в Safari, я получаю подсказку, чтобы открыть свое приложение, и после подтверждения URL -адрес правильно передается и отображается в моем приложении. Например, вот что напечатано:
Расширение действия: сформирована глубокая ссылка: myApp: // share? /> Основное приложение < /strong> < /p>
import SwiftUI
import SwiftData
// You can keep NavigationManager here or move it to its own file.
class NavigationManager: ObservableObject {
static let shared = NavigationManager()
@Published var sharedURL: URL? = nil
func navigateToURL(_ url: URL) {
sharedURL = url
}
}
// The AppDelegate that handles deep linking
import UIKit
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
print("AppDelegate triggered with URL: \(url)")
// (Your URL parsing and handling code follows here)
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true),
components.scheme == "myapp",
components.host == "share",
let queryItem = components.queryItems?.first(where: { $0.name == "url" }),
let sharedURLString = queryItem.value,
let sharedURL = URL(string: sharedURLString) else {
return false
}
NavigationManager.shared.navigateToURL(sharedURL)
return true
}
}
@main
struct MyApp: App {
// Connect your AppDelegate to the SwiftUI lifecycle.
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@StateObject private var navManager = NavigationManager.shared
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(navManager)
.onOpenURL { url in
// Optional fallback if needed; the AppDelegate should already handle it.
handleSharedURL(url)
}
}
}
private func handleSharedURL(_ url: URL) {
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true),
components.scheme == "myapp",
components.host == "share",
let queryItem = components.queryItems?.first(where: { $0.name == "url" }),
let sharedURLString = queryItem.value,
let sharedURL = URL(string: sharedURLString) else {
return
}
navManager.navigateToURL(sharedURL)
}
}
контроллер представления действия
import UIKit
import UniformTypeIdentifiers
class ActionViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Optionally hide the view if you want no visible UI
view.isHidden = true
processInput()
}
private func processInput() {
print("Action Extension: processInput started")
// Get the first input item
guard let inputItem = extensionContext?.inputItems.first as? NSExtensionItem else {
completeRequest()
return
}
// Try to extract a URL from the item
let urlType = UTType.url.identifier
if let attachment = inputItem.attachments?.first,
attachment.hasItemConformingToTypeIdentifier(urlType) {
attachment.loadItem(forTypeIdentifier: urlType, options: nil) { [weak self] data, error in
guard let self = self else { return }
if let url = data as? URL {
self.handleURL(url)
} else {
print("Action Extension: Failed to load URL from attachment")
self.completeRequest()
}
}
} else {
print("Action Extension: No valid attachment found")
completeRequest()
}
}
private func handleURL(_ url: URL) {
// Encode the URL to form a proper deep link
guard let encodedURL = url.absoluteString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
let deepLink = URL(string: "myapp://share?url=\(encodedURL)") else {
print("Action Extension: Error forming deep link")
completeRequest()
return
}
print("Action Extension: Deep Link formed: \(deepLink)")
// Attempt to open the main app with the deep link
extensionContext?.open(deepLink) { success in
if success {
print("Action Extension: Opened main app successfully")
} else {
print("Action Extension: Failed to open main app")
}
self.completeRequest()
}
}
private func completeRequest() {
// Dismiss the extension
extensionContext?.completeRequest(returningItems: nil, completionHandler: nil)
}
}
Плист расширения действия:
LSApplicationQueriesSchemes
myapp
NSExtension
NSExtensionAttributes
NSExtensionActivationRule
TRUEPREDICATE
NSExtensionPointIdentifier
com.apple.ui-services
NSExtensionPrincipalClass
$(PRODUCT_MODULE_NAME).ActionViewController
обработчик запроса действий
import UIKit
import MobileCoreServices
import UniformTypeIdentifiers
class ActionRequestHandler: NSObject, NSExtensionRequestHandling {
var extensionContext: NSExtensionContext?
func beginRequest(with context: NSExtensionContext) {
// Do not call super in an Action extension with no user interface
self.extensionContext = context
var found = false
// Find the item containing the results from the JavaScript preprocessing.
outer:
for item in context.inputItems as! [NSExtensionItem] {
if let attachments = item.attachments {
for itemProvider in attachments {
if itemProvider.hasItemConformingToTypeIdentifier(UTType.propertyList.identifier) {
itemProvider.loadItem(forTypeIdentifier: UTType.propertyList.identifier, options: nil, completionHandler: { (item, error) in
let dictionary = item as! [String: Any]
OperationQueue.main.addOperation {
self.itemLoadCompletedWithPreprocessingResults(dictionary[NSExtensionJavaScriptPreprocessingResultsKey] as! [String: Any]? ?? [:])
}
})
found = true
break outer
}
}
}
}
if !found {
self.doneWithResults(nil)
}
}
func itemLoadCompletedWithPreprocessingResults(_ javaScriptPreprocessingResults: [String: Any]) {
// Here, do something, potentially asynchronously, with the preprocessing
// results.
// In this very simple example, the JavaScript will have passed us the
// current background color style, if there is one. We will construct a
// dictionary to send back with a desired new background color style.
let bgColor: Any? = javaScriptPreprocessingResults["currentBackgroundColor"]
if bgColor == nil || bgColor! as! String == "" {
// No specific background color? Request setting the background to red.
self.doneWithResults(["newBackgroundColor": "red"])
} else {
// Specific background color is set? Request replacing it with green.
self.doneWithResults(["newBackgroundColor": "green"])
}
}
func doneWithResults(_ resultsForJavaScriptFinalizeArg: [String: Any]?) {
if let resultsForJavaScriptFinalize = resultsForJavaScriptFinalizeArg {
// Construct an NSExtensionItem of the appropriate type to return our
// results dictionary in.
// These will be used as the arguments to the JavaScript finalize()
// method.
let resultsDictionary = [NSExtensionJavaScriptFinalizeArgumentKey: resultsForJavaScriptFinalize]
let resultsProvider = NSItemProvider(item: resultsDictionary as NSDictionary, typeIdentifier: UTType.propertyList.identifier)
let resultsItem = NSExtensionItem()
resultsItem.attachments = [resultsProvider]
// Signal that we're complete, returning our results.
self.extensionContext!.completeRequest(returningItems: [resultsItem], completionHandler: nil)
} else {
// We still need to signal that we're done even if we have nothing to
// pass back.
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
// Don't hold on to this after we finished with it.
self.extensionContext = nil
}
}
Основное приложение PLIST:
CFBundleURLTypes
CFBundleTypeRole
Editor
CFBundleURLName
com.elislothower.URLDisplayApp
CFBundleURLSchemes
myapp
LSApplicationQueriesSchemes
Подробнее здесь: https://stackoverflow.com/questions/795 ... hare-sheet
Как передать URL -адрес в приложение для iOS с общего листа? ⇐ IOS
Программируем под IOS
-
Anonymous
1757591998
Anonymous
[b] Обновление: [/b] кажется, что это поведение не разрешено в iOS, несмотря на то, что популярные приложения, такие как CHATGPT, разрешают это делать ... Чтобы обойти это, теперь я просто передаю URL к приложению, когда значок приложения нажимается с общего листа, а затем отправляю уведомление пользователю, которое говорит им, чтобы щелкнуть его, чтобы продолжить. Я думаю, что это юридическое поведение в соответствии с руководящими принципами Apple Dev, но кто знает больше. Когда пользователь делится веб -страницей через общий лист iOS, нажатие на расширение действия моего приложения должно запустить приложение и передать текущий URL -адрес для отображения. Я установил пользовательскую схему URL («MyApp») в своих типах URL. Например, когда я печатаю myApp: // share? Url = example.com в Safari, я получаю подсказку, чтобы открыть свое приложение, и после подтверждения URL -адрес правильно передается и отображается в моем приложении. Например, вот что напечатано:
Расширение действия: сформирована глубокая ссылка: myApp: // share? /> [b] Основное приложение < /strong> < /p>
import SwiftUI
import SwiftData
// You can keep NavigationManager here or move it to its own file.
class NavigationManager: ObservableObject {
static let shared = NavigationManager()
@Published var sharedURL: URL? = nil
func navigateToURL(_ url: URL) {
sharedURL = url
}
}
// The AppDelegate that handles deep linking
import UIKit
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
print("AppDelegate triggered with URL: \(url)")
// (Your URL parsing and handling code follows here)
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true),
components.scheme == "myapp",
components.host == "share",
let queryItem = components.queryItems?.first(where: { $0.name == "url" }),
let sharedURLString = queryItem.value,
let sharedURL = URL(string: sharedURLString) else {
return false
}
NavigationManager.shared.navigateToURL(sharedURL)
return true
}
}
@main
struct MyApp: App {
// Connect your AppDelegate to the SwiftUI lifecycle.
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@StateObject private var navManager = NavigationManager.shared
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(navManager)
.onOpenURL { url in
// Optional fallback if needed; the AppDelegate should already handle it.
handleSharedURL(url)
}
}
}
private func handleSharedURL(_ url: URL) {
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true),
components.scheme == "myapp",
components.host == "share",
let queryItem = components.queryItems?.first(where: { $0.name == "url" }),
let sharedURLString = queryItem.value,
let sharedURL = URL(string: sharedURLString) else {
return
}
navManager.navigateToURL(sharedURL)
}
}
контроллер представления действия [/b]
import UIKit
import UniformTypeIdentifiers
class ActionViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Optionally hide the view if you want no visible UI
view.isHidden = true
processInput()
}
private func processInput() {
print("Action Extension: processInput started")
// Get the first input item
guard let inputItem = extensionContext?.inputItems.first as? NSExtensionItem else {
completeRequest()
return
}
// Try to extract a URL from the item
let urlType = UTType.url.identifier
if let attachment = inputItem.attachments?.first,
attachment.hasItemConformingToTypeIdentifier(urlType) {
attachment.loadItem(forTypeIdentifier: urlType, options: nil) { [weak self] data, error in
guard let self = self else { return }
if let url = data as? URL {
self.handleURL(url)
} else {
print("Action Extension: Failed to load URL from attachment")
self.completeRequest()
}
}
} else {
print("Action Extension: No valid attachment found")
completeRequest()
}
}
private func handleURL(_ url: URL) {
// Encode the URL to form a proper deep link
guard let encodedURL = url.absoluteString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
let deepLink = URL(string: "myapp://share?url=\(encodedURL)") else {
print("Action Extension: Error forming deep link")
completeRequest()
return
}
print("Action Extension: Deep Link formed: \(deepLink)")
// Attempt to open the main app with the deep link
extensionContext?.open(deepLink) { success in
if success {
print("Action Extension: Opened main app successfully")
} else {
print("Action Extension: Failed to open main app")
}
self.completeRequest()
}
}
private func completeRequest() {
// Dismiss the extension
extensionContext?.completeRequest(returningItems: nil, completionHandler: nil)
}
}
[b] Плист расширения действия: [/b]
LSApplicationQueriesSchemes
myapp
NSExtension
NSExtensionAttributes
NSExtensionActivationRule
TRUEPREDICATE
NSExtensionPointIdentifier
com.apple.ui-services
NSExtensionPrincipalClass
$(PRODUCT_MODULE_NAME).ActionViewController
[b] обработчик запроса действий [/b]
import UIKit
import MobileCoreServices
import UniformTypeIdentifiers
class ActionRequestHandler: NSObject, NSExtensionRequestHandling {
var extensionContext: NSExtensionContext?
func beginRequest(with context: NSExtensionContext) {
// Do not call super in an Action extension with no user interface
self.extensionContext = context
var found = false
// Find the item containing the results from the JavaScript preprocessing.
outer:
for item in context.inputItems as! [NSExtensionItem] {
if let attachments = item.attachments {
for itemProvider in attachments {
if itemProvider.hasItemConformingToTypeIdentifier(UTType.propertyList.identifier) {
itemProvider.loadItem(forTypeIdentifier: UTType.propertyList.identifier, options: nil, completionHandler: { (item, error) in
let dictionary = item as! [String: Any]
OperationQueue.main.addOperation {
self.itemLoadCompletedWithPreprocessingResults(dictionary[NSExtensionJavaScriptPreprocessingResultsKey] as! [String: Any]? ?? [:])
}
})
found = true
break outer
}
}
}
}
if !found {
self.doneWithResults(nil)
}
}
func itemLoadCompletedWithPreprocessingResults(_ javaScriptPreprocessingResults: [String: Any]) {
// Here, do something, potentially asynchronously, with the preprocessing
// results.
// In this very simple example, the JavaScript will have passed us the
// current background color style, if there is one. We will construct a
// dictionary to send back with a desired new background color style.
let bgColor: Any? = javaScriptPreprocessingResults["currentBackgroundColor"]
if bgColor == nil || bgColor! as! String == "" {
// No specific background color? Request setting the background to red.
self.doneWithResults(["newBackgroundColor": "red"])
} else {
// Specific background color is set? Request replacing it with green.
self.doneWithResults(["newBackgroundColor": "green"])
}
}
func doneWithResults(_ resultsForJavaScriptFinalizeArg: [String: Any]?) {
if let resultsForJavaScriptFinalize = resultsForJavaScriptFinalizeArg {
// Construct an NSExtensionItem of the appropriate type to return our
// results dictionary in.
// These will be used as the arguments to the JavaScript finalize()
// method.
let resultsDictionary = [NSExtensionJavaScriptFinalizeArgumentKey: resultsForJavaScriptFinalize]
let resultsProvider = NSItemProvider(item: resultsDictionary as NSDictionary, typeIdentifier: UTType.propertyList.identifier)
let resultsItem = NSExtensionItem()
resultsItem.attachments = [resultsProvider]
// Signal that we're complete, returning our results.
self.extensionContext!.completeRequest(returningItems: [resultsItem], completionHandler: nil)
} else {
// We still need to signal that we're done even if we have nothing to
// pass back.
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
// Don't hold on to this after we finished with it.
self.extensionContext = nil
}
}
[b] Основное приложение PLIST: [/b]
CFBundleURLTypes
CFBundleTypeRole
Editor
CFBundleURLName
com.elislothower.URLDisplayApp
CFBundleURLSchemes
myapp
LSApplicationQueriesSchemes
Подробнее здесь: [url]https://stackoverflow.com/questions/79503124/how-to-pass-a-url-to-ios-app-from-share-sheet[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия