Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift Firebase getIDToken以及如何在API调用中使用它_Swift_Firebase_Swiftui - Fatal编程技术网

Swift Firebase getIDToken以及如何在API调用中使用它

Swift Firebase getIDToken以及如何在API调用中使用它,swift,firebase,swiftui,Swift,Firebase,Swiftui,我有一个获取json的API调用,但需要令牌身份验证。tokenauth工作得很好,但是当我尝试将Token传递给API函数时,它返回为nil。我相信这是因为Auth.Auth().currentUser!。getIDToken(…)尚未实际完成。相关代码如下。。。如何将其修改为 class SessionData : ObservableObject { ... func token() -> String? { var result: String? =

我有一个获取json的API调用,但需要令牌身份验证。tokenauth工作得很好,但是当我尝试将Token传递给API函数时,它返回为nil。我相信这是因为
Auth.Auth().currentUser!。getIDToken(…)
尚未实际完成。相关代码如下。。。如何将其修改为

class SessionData : ObservableObject {
    ...
    func token() -> String? {
        var result: String? = nil
        Auth.auth().currentUser!.getIDToken(completion: { (res, err) in
            if err != nil {
                print("*** TOKEN() ERROR: \(err!)")
            } else {
                print("*** TOKEN() SUCCESS: \(err!)")
                result = res!
            }
        })
       return result
    }
...
}

class FetchPosts: ObservableObject {
    @Published var posts = [Post]()
    
    func load(api: Bool, session: SessionData) {
        
        if api {
            let url = URL(string: MyAPI.getAddress(token: session.token()!))!
            URLSession.shared.dataTask(with: url) {(data, response, error) in
                do {
                    if let postsData = data {
                        // 3.
                        let decodedData = try JSONDecoder().decode(Response.self, from: postsData)
                        DispatchQueue.main.async {
                            self.posts = decodedData.result
                            if decodedData.error != nil {
                                print("ERROR: \(decodedData.error!)")
                                session.json_error(error: decodedData.error!)
                            }
                        }
                    } else {
                        print("No data. Connection error.")
                        DispatchQueue.main.async {
                            session.json_error(error: "Could not connect to server, please try again!")
                        }
                    }
                } catch {
                    print("* Error: \(error)")
                }
            }.resume()
            
        } else {
            let url = Bundle.main.url(forResource: "test", withExtension: "json")!
            let data = try! Data(contentsOf: url)
            let decoder = JSONDecoder()
            if let products = try? decoder.decode([Post].self, from: data) {
                self.posts = products
            }
        }
    }
}
这就是.load函数的调用方式:

UserViewer(fetch: posts)
                    .transition(AnyTransition.slide)
                    .animation(.default)
                    .onAppear {
                    
                        withAnimation{
                            posts.load(api: true, session: session)
                        }
                    }
                    .environmentObject(session)

因为
getIDToken
异步执行并返回,所以不能直接从它返回。相反,您需要使用回调函数

以下是对函数的修改:

func token(_ completion: @escaping (String?) -> ()) {
            guard let user = Auth.auth().currentUser else {
                //handle error
                return
            }
            user.getIDToken(completion: { (res, err) in
                if err != nil {
                    print("*** TOKEN() ERROR: \(err!)")
                    //handle error
                } else {
                    print("*** TOKEN() SUCCESS: \(err!)")
                    completion(res)
                }
            })
        }
然后,您可以在以后使用它:

.onAppear {
  session.token { token in 
    guard let token = token else {
       //handle nil
       return 
    }
    withAnimation{
      posts.load(api: true, session: session, token: token)
    }
  }
}
修改
加载
以获取
令牌
参数:

func load(api: Bool, session: SessionData, token: String) {
        
        if api {
            guard let url = URL(string: MyAPI.getAddress(token: token)) else {
  //handle bad URL
  return
}

此外,正如您在我的代码示例中所看到的,我将尝试摆脱使用
的习惯强制展开选项。如果可选项为
nil
,并且您使用
,您的程序将崩溃。相反,要熟悉
guard let
if let
,并学会以不会导致崩溃的方式处理可选项——这是Swift的最大好处之一。

您必须使用所谓的“回调函数”,因为它是异步完成的。