Ios 在OnOpenUrl视图修改器中调用api后刷新视图
在我的一个观点中,我有一段非常基本的代码:Ios 在OnOpenUrl视图修改器中调用api后刷新视图,ios,swift,swiftui,foundation,Ios,Swift,Swiftui,Foundation,在我的一个观点中,我有一段非常基本的代码: .onOpenURL(perform: { url in avm.handleRedirect(viewContext,url: url) }) 其中avm定义为 @ObservedObject var avm = AccountsViewModel.makeAccountsViewModel() avm具有以下基本属性: @Published var isLoading = true 设置后,我的视
.onOpenURL(perform: { url in
avm.handleRedirect(viewContext,url: url) })
其中avm
定义为
@ObservedObject var avm = AccountsViewModel.makeAccountsViewModel()
avm
具有以下基本属性:
@Published var isLoading = true
设置后,我的视图将侦听并显示加载微调器。除下文概述的情况外,这适用于所有其他情况
HandlerRedirect函数如下所示:
func handleRedirect(_ context: NSManagedObjectContext, url: URL) {
debugPrint("Handling redirect")
let url = URLComponents(string: url.absoluteString)!
let code = url.queryItems?.first(where: { $0.name == "code" })?.value
trueLayerClient.getAccessToken(code: code!) { res in
if res == nil {
debugPrint("accessTokenResponse was nil")
}
self.api.storeTokens(
str: API.StoreTokensRequest(
userID: "***",
authToken: res!.accessToken,
refreshToken: res!.refreshToken,
apiKey: "***"
), finished: { success in
if success{
debugPrint("was successful")
DispatchQueue.main.async{
self.isLoading = false
}
} else {
debugPrint("store token failed")
}
})
}
}
我正在使用我设置的通用链接触发此onOpenUrl
当我点击链接时,我的应用程序从后台打开,我看到以下日志:
Handling Redirect
Was successful
但是,应用程序从未进入加载状态。此外,用户界面变得“阻塞”,我必须硬杀死应用程序才能按下任何按钮
一旦我重新打开应用程序,新状态(我通过api获取并存储在CoreData中)将反映在视图中
起初,我认为我的API响应太快,但我在其中放置了5秒钟的睡眠,我仍然看到UI被阻塞,但日志相同(只是相隔更远)
如果能在这方面得到任何帮助,我将不胜感激
如果有帮助,我的storeTokens API调用如下所示:
func storeTokens(str: StoreTokensRequest , finished: @escaping (Bool)->Void) {
let u = URL(string:"\(self.baseURL)/\(storeTokenPath)")!
var req = URLRequest(url: u)
req.addValue("application/json", forHTTPHeaderField: "Content-Type")
req.httpMethod = "POST"
let reqBody = str
debugPrint("req bodyed")
guard let encoded = try? JSONEncoder().encode(reqBody) else {
debugPrint("failed to encode req")
finished(false)
return
}
req.httpBody = encoded
debugPrint("encoded")
let task = URLSession.shared.dataTask(with: req) { data, response, error in
guard let httpResponse = response as? HTTPURLResponse else {
debugPrint("wasnt http rep")
finished(false)
return
}
debugPrint("status code is: \(httpResponse.statusCode)")
if httpResponse.statusCode < 299 {
debugPrint("About to call true")
finished(true)
return
}
}
task.resume()
}
}
func存储令牌(str:StoreTokensRequest,finished:@escaping(Bool)->Void){
让u=URL(字符串:“\(self.baseURL)/\(storeTokenPath)”!
var req=url请求(url:u)
req.addValue(“应用程序/json”,用于HttpHeaderField:“内容类型”)
req.httpMethod=“POST”
让reqBody=str
调试打印(“请求正文”)
guard let encoded=try?JSONEncoder().encode(reqBody)else{
debugPrint(“未能对请求进行编码”)
已完成(错误)
返回
}
req.httpBody=编码
调试打印(“编码”)
让task=URLSession.shared.dataTask(with:req){data,response,中的错误
guard let httpResponse=响应为?HTTPURLResponse else{
调试打印(“wasnt http rep”)
已完成(错误)
返回
}
debugPrint(“状态代码为:\(httpResponse.statusCode)”)
如果httpResponse.statusCode<299{
debugPrint(“即将调用true”)
完成(真)
返回
}
}
task.resume()
}
}
我在我的输出中也看到了这个函数中的所有日志,为了简洁起见,我将它们省略了。我尝试了一个类似于您的实现。我的“onOpenUrl()”方法正在唤醒(如果需要)我的应用程序,并将url传递给我的应用程序,应用程序正在正确更新其状态 基本检查 暂时忘记“onOpenUrl”。在视图内部实现此方法:
.onAppear {
viewModel.onAppear()
}
在视图模型中使用“isLoading”属性的位置。比如说,
func onAppear(){
self.isLoading = true
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
print("- loading complete")
self.isLoading = false
}
}
视图是否相应地更新(活动加载器)?请先尝试此操作。对于
avm
,ObservedObject通常(或永远不应该)在声明为ObservedObject的同一行上初始化。这样做是不安全的,因为视图是不断重新创建的(没有视图代码,但它可能在视图中)。将其更改为@StateObject
或在视图外部对其进行初始化,并将其作为声明为@ObservedObject
的参数传递给视图。谢谢。我将其更改为stateObject,但没有任何明显的更改。请尝试在主队列中执行此“avm.handleRedirect(viewContext,url:url)”。@raja感谢您的建议。我试过了,没什么不同。不管怎样,视图中的所有代码都会在主队列中处理(如果您尝试在后台队列中更改UI状态,Xcode会发出警告)您调用makeAccountsViewModel()
多少次?你的应用程序中的任何地方?如果您多次创建多个实例,其中一个实例不知道另一个实例在做什么,则应使用@EnvironmentObject
共享您创建的第一个实例或创建一个单实例。没有法律的帮助是不可能的