【问题标题】:Unable to add parameter to API in swift无法在 swift 中向 API 添加参数
【发布时间】:2020-08-16 16:58:14
【问题描述】:

我正在从其他视图控制器获取参数值,并且我正在完美地获取参数值但我无法将其添加到 API

如果我硬编码eventStatus 那么它就可以工作

还有来自 otherviewcontroller 的 eventStatus 值也很完美,我无法添加到 API 中

如果我像这样硬编码它的工作

var eventType = "Draft"
let string = Constants.GLOBAL_URL + "/get/allevents/?eventstatus=\(self.eventType)"

代码:这里我得到了正确的eventStatus 值,但是当断点控制到其他地方时,为什么?

class EventsViewController: UIViewController {

var eventsListArray = [AnyObject]()
// var eventType = "Draft"
var eventType: String!

var eventList : EventsModel? = nil

@IBOutlet weak var eventsTableView: UITableView!


override func viewDidLoad() {
    super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    getAllEventsList()
}

func getAllEventsList() {
    DispatchQueue.main.async {
    let headers = ["deviceid": deviceId,"userType": "personal","key": personalId]
    DispatchQueue.main.async {
        //let string = Constants.GLOBAL_URL + "/get/allevents/?eventstatus=\(self.eventType)"
    let string = Constants.GLOBAL_URL + "/get/allevents"
    var urlComponents = URLComponents(string: string)

    let eventStatus = self.eventType
        
        print("event status value in API call \(eventStatus)")
    let requestEventType = URLQueryItem(name: "eventstatus", value: eventStatus)

    urlComponents?.queryItems = [requestEventType]
    let urlStr = urlComponents?.url
    
    var request = URLRequest(url: urlStr!, cachePolicy: .useProtocolCachePolicy,timeoutInterval: 10.0)
    request.httpMethod = "POST"
    request.allHTTPHeaderFields = headers as! [String : String]
    let session = URLSession.shared

    let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
        DispatchQueue.main.async {

        if error == nil {

            let httpResponse = response as? HTTPURLResponse
            if httpResponse!.statusCode == 200 {
                do {
                    let jsonObject  = try JSONSerialization.jsonObject(with: data!) as! [String :Any]
                    print("publish event \(jsonObject)")
                    
                    self.eventList = EventsModel.init(fromDictionary: jsonObject)
                    
                    DispatchQueue.main.async {

                    if self.eventList?.events.count != 0 {
                        DispatchQueue.main.async {
                            self.eventsTableView.reloadData()
                        }
                    }
                    
                    else {
                        
                        DispatchQueue.main.async {
                            Constants.showAlertView(alertViewTitle: "", Message: "No Events \(self.eventType)", on: self)
                            self.eventList?.events.removeAll()
                            self.eventsTableView.reloadData()
                        }
                    }
                }
                } catch { print(error.localizedDescription) }
            } else {
                Constants.showAlertView(alertViewTitle: "", Message: "Something went wrong, Please try again", on: self)
            }
    }
    }
    })
        
    dataTask.resume()
        }
}
}
}

我哪里错了,为什么 eventStatus 值没有添加到 API 中......请建议我

【问题讨论】:

  • eventType 从未在控制器中设置,因此它是nil。而且您的代码仍然包含诸如AnyObject(将其替换为Any)、NSMutableURLRequest(将其替换为var ..URLRequest).mutableLeaves(删除options 参数)等不良做法。跨度>
  • @vadian 我已经根据您的建议更改了我的代码.. 我已将 eventType 指定为非可选然后控制转到其他部分.. 我错了
  • 再次在哪里为eventType 赋值?在代码中它已声明但未初始化。
  • @vadian 这里是let requestEventType = URLQueryItem(name: "eventstatus", value: eventStatus)。这里eventStatus 包含eventType
  • @swiftDev vadian 询问您在哪里设置eventType 的值。虽然如果你强行打开它应该会崩溃。

标签: json swift


【解决方案1】:

您似乎有一个 POST 请求,您需要使用请求数据而不是 URL 参数。

HTTP Request in Swift with POST method在这里你可以看到:

let parameters: [String: Any] = [
    "eventstatus": yourValue
]
request.httpBody = parameters.percentEncoded()

您还需要使用 eventStatus 创建参数。并放入

request.httpBody = parameters.percentEncoded()

如果您服务器上的此端点在请求正文中等待此数据,则您无法像 URL 参数一样添加它。

另外,不要忘记示例中的这 2 个扩展

extension Dictionary {
    func percentEncoded() -> Data? {
        return map { key, value in
            let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
            let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
            return escapedKey + "=" + escapedValue
        }
        .joined(separator: "&")
        .data(using: .utf8)
    }
}

extension CharacterSet { 
    static let urlQueryValueAllowed: CharacterSet = {
        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
        let subDelimitersToEncode = "!$&'()*+,;="

        var allowed = CharacterSet.urlQueryAllowed
        allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
        return allowed
    }()
}

【讨论】:

  • 您不需要对 HTTP 正文中的参数进行编码,因为它不是 URL 的一部分,另一方面,URLComponents 确实添加了百分比编码。跨度>
  • 你是对的。是对上面帖子的引用,这里我们需要把数据放到httpBody的Data Type中。
【解决方案2】:

解决方案必须从 cmets 中的讨论中显而易见。尽管您似乎有些困惑,但我添加此内容是为了帮助您。 eventType 的值永远不会分配给一个值,它保持为 nil 除非您在 API 调用之前在代码中的某个点设置它的值。因此,您可以通过以下方法解决此问题:

let string = "https://www.google.com" + "/get/allevents"
var urlComponents = URLComponents(string: string)

let eventStatus = self.eventType ?? "Published" // here value is defaulted to "Published"
let requestEventType = URLQueryItem(name: "eventstatus", value: eventStatus)

urlComponents?.queryItems = [requestEventType]
let urlStr = urlComponents?.url
print(urlStr?.absoluteString)

这里,我们为eventTypenil 的场景设置eventType 的默认值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-27
    • 2017-09-13
    • 1970-01-01
    • 2021-06-01
    • 2016-04-13
    • 2019-12-01
    • 2019-11-11
    • 1970-01-01
    相关资源
    最近更新 更多