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
共享您创建的第一个实例或创建一个单实例。没有法律的帮助是不可能的