You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift如何向函数传递参数字典并发起GET请求?

解决方案:动态传递请求参数并安全构建URL

咱们可以通过重构makeRequest函数,让它支持动态传入任意查询参数(包括client_id或无参数),同时用更安全的方式构建URL(避免硬编码和字符编码问题)。以下是具体实现步骤:

1. 重构makeRequest函数,支持动态参数

首先,给函数添加一个可选的queryParameters参数(默认空字典),然后用URLComponents来构建带参数的URL——这种方式能自动处理特殊字符的编码,还能灵活添加参数。同时修复之前token强制解包的崩溃风险:

func makeRequest<T>(endpoint: String, queryParameters: [String: String] = [:], completionHandler: @escaping (ApiContainer<T>?, Error?) -> ()) {
    // 先安全获取token,避免强制解包
    guard let token = DAKeychain.shared["token"] else {
        print("Error: token not found in keychain")
        let error = BackendError.urlError(reason: "Missing authentication token")
        completionHandler(nil, error)
        return
    }
    
    // 用URLComponents构建URL,比直接拼接字符串更安全
    guard var components = URLComponents(string: endpoint) else {
        print("Error: cannot create URL components")
        let error = BackendError.urlError(reason: "Could not create URL components")
        completionHandler(nil, error)
        return
    }
    
    // 初始化查询参数列表,先添加必填的token
    var queryItems = [URLQueryItem(name: "token", value: token)]
    
    // 遍历传入的动态参数,逐个添加到查询列表
    for (key, value) in queryParameters {
        queryItems.append(URLQueryItem(name: key, value: value))
    }
    
    components.queryItems = queryItems
    
    guard let url = components.url else {
        print("Error: cannot create final URL")
        let error = BackendError.urlError(reason: "Could not build final URL")
        completionHandler(nil, error)
        return
    }
    
    print(url)
    
    var urlRequest = URLRequest(url: url)
    let session = URLSession.shared
    urlRequest.httpMethod = "GET"
    urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
    urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
    
    let task = session.dataTask(with: urlRequest) { (data, response, error) in
        guard let responseData = data else {
            print("Error: did not receive data")
            completionHandler(nil, error)
            return
        }
        
        guard error == nil else {
            completionHandler(nil, error!)
            return
        }
        
        do {
            let response = try JSONDecoder().decode(ApiContainer<T>.self, from: responseData)
            completionHandler(response, nil)
        } catch {
            print("error trying to convert data to JSON")
            print(error)
            completionHandler(nil, error)
        }
    }
    task.resume()
}

2. 修改getContacts函数,传递client_id参数

现在你可以在调用makeRequest时,通过queryParameters参数传入client_id(如果需要,后续也能换成动态值,比如从配置或用户输入获取):

func getContacts() {
    // 传入client_id参数,这里保留你原来的测试值60
    makeRequest(endpoint: "http://blog.local:4711/api/contacts/all", queryParameters: ["client_id": "60"]) { (container: ApiContainer<Contact>?, error: Error?) in
        if let error = error {
            print("error calling GET on /api/contacts/all")
            print(error)
            return
        }
        
        // 用可选绑定替代强制解包,避免崩溃
        if let contacts = container?.result {
            self.tableArray = contacts
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        } else {
            print("Error: no contacts data received")
        }
    }
}

3. 其他场景的调用示例

  • 无参数传递:直接省略queryParameters即可,函数会自动只传token:
    makeRequest(endpoint: "http://blog.local:4711/api/user/profile") { (container: ApiContainer<User>?, error: Error?) in
        // 处理结果逻辑
    }
    
  • 多参数传递:比如同时传client_id和分页参数page:
    makeRequest(endpoint: "http://blog.local:4711/api/contacts/all", queryParameters: ["client_id": "60", "page": "1"]) { ... }
    

这样修改后,你的请求函数既保留了GET传token的逻辑,又能灵活传递任意参数(或无参数),还解决了硬编码和URL编码的潜在问题,同时代码更安全稳定。

内容的提问来源于stack exchange,提问作者Renan Aguiar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:43:25