我试着在this和this等帖子中寻找解决方案,人们遇到了非常相似的问题:如何从iOS应用程序发送消息到Safari扩展?
我甚至读了this article,作者解释了如何使用SafariExtensionHandler
从浏览器向应用程序发送消息,并在选择上下文菜单后返回浏览器,但这并不是我想要的。
iOS App向Safari扩展发送Token
在应用程序中,用户必须输入电子邮件和密码才能登录他们的帐户。一旦他们登录,我将他们的信息保存在UserDefaults
中,如下所示:
class AuthDataService {
{...}
URLSession.shared.dataTaskPublisher(for: urlRequest)
.tryMap { data, response -> Data in
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200,
let accessToken = httpResponse.value(forHTTPHeaderField: "Access-Token"),
let clientId = httpResponse.value(forHTTPHeaderField: "Client"),
let uid = httpResponse.value(forHTTPHeaderField: "Uid")
else {
throw CustomError.cannotExecuteRequest
}
let sharedDefaults = UserDefaults(suiteName: "group.com.MyCompany.MyProject")
sharedDefaults?.set(accessToken, forKey: "Access-Token")
sharedDefaults?.set(clientId, forKey: "Client")
sharedDefaults?.set(uid, forKey: "Uid")
return data
}
{...}
}
应用群组
根据我对of this article的理解,我需要创建一个App Group,以便在iOS App和Safari Extension之间共享数据。我给这个团体取名:"group.com.MyCompany.MyProject"
(就像UserDefaults
中的suiteName)。
主视图
用户在登录时看到的屏幕是一个SwiftUI视图,其中有一个链接将用户带到Safari,以便他们可以自己打开扩展:
struct HomeView: View {
@EnvironmentObject var viewModel: AuthViewModel
var body: some View {
Link(destination: URL(string: "https://www.apple.com/")!) {
Text("Take me to Safari")
}
}
}
SafariWebExtensionHandler
现在,我读到的所有文章都在谈论如何通过SafariWebExtensionHandler的beginRequest(with:)
将数据从Safari扩展发送到iOS应用程序。但是,我尝试在用户登录应用程序或打开Safari扩展时发送UserDefaults中的令牌。
我试着从UserDefaults
中检索数据,看看我是否至少可以在终端中读取它,但调试器从未到达print
语句:
import SafariServices
import os.log
let SFExtensionMessageKey = "message"
class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
func readData() {
let sharedDefaults = UserDefaults(suiteName: "group.com.lever.clientTokens")
print(sharedDefaults?.object(forKey: "Access-Token")) //<-- This line never gets executed
}
func beginRequest(with context: NSExtensionContext) {
let item = context.inputItems[0] as! NSExtensionItem
let message = item.userInfo?[SFExtensionMessageKey]
os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@", message as! CVarArg)
let response = NSExtensionItem()
response.userInfo = [ SFExtensionMessageKey: [ "Response to": message ] ]
readData()
context.completeRequest(returningItems: [response], completionHandler: nil)
}
}
提问
macOS vs iOS
This documentation from Apple有一个名为Send messages from the app to JavaScript
的部分,这几乎是我想做的。文档甚至提到了SFSafariApplication.dispatchMessage(withName:toExtensionWithIdentifier:userInfo:completionHandler:)
,理论上它会向JavaScript脚本发送消息,但它说它只在macOS中工作:
您无法将消息从包含的iOS应用发送到您的Web扩展的JavaScript脚本。
This excellent Medium article谈到使用openai.com的API将APIKey从应用程序发送到Safari扩展。它似乎也使用SFSafariApplication
与SafariWebExtensionHandler
通信,但看起来它只适用于macOS。
网页Safari扩展
我也读了this other Apple documentation,认为它会有所帮助,但它只谈到从Safari扩展的弹出窗口传递消息到网页。
总结
所以我的问题是
在SafariWebExtensionHandler
中编写代码是将数据从iOS应用程序发送到Safari扩展的正确方法吗?在iOS中可以这样做吗?是否仅适用于macOS?
我读过一些其他的文章,它们讨论了如何使用Resources文件夹中的JavaScript文件来“监听”更改。但是我有点困惑,我如何从我的应用程序发送这些更改,以便Safari扩展来监听它们。
我试图实现的是,用户在iOS应用程序中从HomeView重定向后,已经在Safari扩展中登录,而不必在另一时间登录。
感谢您的时间和帮助!
1条答案
按热度按时间yquaqz181#
虽然应用程序无法启动与扩展的连接,但支持另一个方向。当扩展将数据发送到应用程序时,您可以附加响应并将其发送回扩展。
我不知道为什么你使用
SafariWebExtensionHandler
的例子不起作用。看起来不错问题可能出在JS方面。App
扩展
首先将
"nativeMessaging"
添加到'manifest.json'中的"permissions"
。