Nic*_*elo 8 safari-extension ios swift
我尝试在诸如此和此之类的帖子中寻找解决方案,其中人们遇到了非常相似的问题:How to send a message from iOS App to a Safari Extension?
\n我什至阅读了这篇文章,其中作者解释了如何使用SafariExtensionHandler从浏览器向应用程序发送消息,并在选择上下文菜单后返回浏览器,但这并不完全是我想要的。
在应用程序中,用户必须输入电子邮件和密码才能登录其帐户。一旦他们登录,我就会UserDefaults像这样保存他们的信息:
class AuthDataService {\n{...}\n URLSession.shared.dataTaskPublisher(for: urlRequest)\n .tryMap { data, response -> Data in\n guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200,\n let accessToken = httpResponse.value(forHTTPHeaderField: "Access-Token"),\n let clientId = httpResponse.value(forHTTPHeaderField: "Client"),\n let uid = httpResponse.value(forHTTPHeaderField: "Uid")\n else {\n throw CustomError.cannotExecuteRequest\n }\n \n let sharedDefaults = UserDefaults(suiteName: "group.com.MyCompany.MyProject")\n sharedDefaults?.set(accessToken, forKey: "Access-Token")\n sharedDefaults?.set(clientId, forKey: "Client")\n sharedDefaults?.set(uid, forKey: "Uid")\n\n return data\n }\n{...}\n}\nRun Code Online (Sandbox Code Playgroud)\n根据我对本文的理解,我需要创建一个应用程序组,以便在 iOS 应用程序和 Safari 扩展之间共享数据。我将该组命名为:("group.com.MyCompany.MyProject"就像 中的 suiteName 一样UserDefaults)。
用户登录时看到的屏幕是一个 SwiftUI 视图,其中有一个链接,可将用户带到 Safari,以便他们可以自己打开扩展:
\nstruct HomeView: View {\n @EnvironmentObject var viewModel: AuthViewModel\n var body: some View {\n Link(destination: URL(string: "https://www.apple.com/")!) {\n Text("Take me to Safari")\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n现在,我读到的所有文章都在讨论如何通过 SafariWebExtensionHandler 将数据从 Safari 扩展发送到 iOS 应用程序beginRequest(with:)。\n但是,我尝试在用户登录时发送 UserDefaults 中的令牌。应用程序,或者当他们打开 Safari 扩展时。
我尝试从中检索数据,UserDefaults看看是否至少可以在终端中读取它,但调试器永远不会到达print:
import SafariServices\nimport os.log\n\nlet SFExtensionMessageKey = "message"\n\nclass SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {\n\n func readData() {\n let sharedDefaults = UserDefaults(suiteName: "group.com.lever.clientTokens")\n print(sharedDefaults?.object(forKey: "Access-Token")) //<-- This line never gets executed\n }\n \n func beginRequest(with context: NSExtensionContext) {\n let item = context.inputItems[0] as! NSExtensionItem\n let message = item.userInfo?[SFExtensionMessageKey]\n os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@", message as! CVarArg)\n\n let response = NSExtensionItem()\n response.userInfo = [ SFExtensionMessageKey: [ "Response to": message ] ]\n\n readData()\n \n context.completeRequest(returningItems: [response], completionHandler: nil)\n }\n\n}\nRun Code Online (Sandbox Code Playgroud)\nApple 的这份文档中有一个名为Send messages from the app to JavaScript“这正是我想要做的”的部分。文档甚至提到SFSafariApplication.dispatchMessage(withName:toExtensionWithIdentifier:userInfo:completionHandler:)理论上它会向 JavaScript 脚本发送一条消息,但它说它仅适用于 macOS:
\n\n您可以\xe2\x80\x99t 将消息从包含的 iOS 应用程序发送到您的 Web\nextension\xe2\x80\x99s JavaScript 脚本。
\n
这篇优秀的 Medium 文章讨论了使用 openai.com 的 API 将 APIKey 从应用程序发送到 Safari 扩展。看来它也是用来SFSafariApplication沟通的SafariWebExtensionHandler,但它看起来又只适用于 macOS。
我还阅读了其他 Apple 文档认为它会有所帮助,但它只讨论了将消息从 Safari 扩展的弹出窗口传递到网页。
\n所以我的问题是:
\n是否以正确的方式编写代码SafariWebExtensionHandler将数据从 iOS 应用程序发送到我的 Safari 扩展?这可以在 iOS 中完成吗?还是仅适用于 macOS?
我读过一些其他文章,讨论如何使用 Resources 文件夹中的 JavaScript 文件来“监听”更改。但我有点困惑如何从我的应用程序发送这些更改以便 Safari 扩展能够监听它们。
\n我想要实现的是,用户从 iOS 应用程序中的 HomeView 重定向后已经登录到 Safari 扩展中,而不必再次登录。
\n感谢您的时间和帮助!
\n虽然应用程序无法发起与分机的连接,但支持另一个方向。当扩展程序将数据发送到应用程序时,您可以附加响应并将其发送回扩展程序。
我不确定为什么你的使用示例SafariWebExtensionHandler不起作用。看起来不错。也许问题出在 JS 方面。
import SafariServices
import os.log
extension String: Error {}
let SFExtensionMessageKey = "message"
class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
func beginRequest(with context: NSExtensionContext) {
let item = context.inputItems[0] as! NSExtensionItem
let data = item.userInfo?[SFExtensionMessageKey] as AnyObject?
guard let key = data?["key"] as? String else {
return
}
let response: [String: Any]
do {
switch(key) {
case "getToken":
os_log(.default, "handling getToken")
guard let sharedDefault = UserDefaults(suiteName: "group.com.lever.clientTokens") else {
throw "UserDefaults not found"
}
guard let tokenData = sharedDefault.data(forKey: "Access-Token") else {
throw "Access-Token not found"
}
guard let tokenString = String(data: tokenData, encoding: .utf8) else {
throw "tokenData could not be converted into string";
}
response = ["success": true, "resp": tokenString]
default:
throw "Invalid key"
}
} catch {
os_log(.error, "Error: %s", String(reflecting: error))
response = ["success": false, "resp": ["message": error.localizedDescription]]
}
let resp = NSExtensionItem()
resp.userInfo = [SFExtensionMessageKey: response]
context.completeRequest(returningItems: [resp], completionHandler: nil)
}
}
Run Code Online (Sandbox Code Playgroud)
首先添加"nativeMessaging"到'manifest.json'中。"permissions"
async function getToken() {
const resp = await browser.runtime.sendNativeMessage("_", {
key: "getToken"
});
if (resp.success) {
return resp.resp
} else {
throw new Error(resp.message)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
863 次 |
| 最近记录: |