如何向 URL 中插入一个值以向 YQL 发出请求

How to insert a value into a URL to make a request to YQL

当我尝试向 YQL 请求股票数据时,我 运行 遇到了问题,而要查找的代码 (newCompanyStockSymbol) 是用户输入的。我在这个函数中获取股票:

func handleSave() {

    // Fetch stock price from symbol provided by user for new company
    guard let newCompanyStockSymbol = stockTextField.text else {
        print("error getting text from field")
        return
    }
    var newCompanyStockPrice = ""

    let url = URL(string: "https://query.yahooapis.com/v1/public/yql?q=select%20symbol%2C%20Ask%2C%20YearHigh%2C%20YearLow%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22\(newCompanyStockSymbol)%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys")!
    let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
        if error != nil {
            print(error!)
        } else if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 {
            let json = JSON(data: data!)
            if let quotes = json["query"]["results"]["quote"].array {
                for quote in quotes {
                    let ask = quote["Ask"].stringValue
                    newCompanyStockPrice = ask
                }
            }
            print("new company json: \(json)")
        }
        guard let newCompanyName = self.nameTextField.text else {
            print("error getting text from field")
            return
        }
        guard let newCompanyLogo = self.logoTextField.text else {
            print("error getting text from field")
            return
        }
        print("2: The new commpany stock price is: \(newCompanyStockPrice)")

        // Call save function in view controller to save new company to core data
        self.viewController?.save(name: newCompanyName, logo: newCompanyLogo, stockPrice: newCompanyStockPrice)
        self.viewController?.tableView.reloadData()
    }
    task.resume()

    // Present reloaded view controller with new company added
    let cc = UINavigationController()
    let companyController = CompanyController()
    viewController = companyController
    cc.viewControllers = [companyController]
    present(cc, animated: true, completion: nil)
}

并且我使用字符串插值将\(newCompanyStockSymbol)插入到请求URL中的适当位置。但是我在那条线上遇到了崩溃和错误,因为它返回了 nil,我预计是因为它在其中逐字使用 URL 和 \(newCompanyStockSymbol),而不是实际插入值。

还有其他方法吗?

编辑

以及从上面的 handleSave() 调用的视图控制器中的 save 函数(如果有帮助的话):

func save(name: String, logo: String, stockPrice: String) {

    guard let appDelegate =
        UIApplication.shared.delegate as? AppDelegate else {
            return
    }

    let managedContext =
        appDelegate.persistentContainer.viewContext

    let entity =
        NSEntityDescription.entity(forEntityName: "Company",
                                   in: managedContext)!
    let company = NSManagedObject(entity: entity,
                                  insertInto: managedContext)


    company.setValue(stockPrice, forKey: "stockPrice")
    company.setValue(name, forKey: "name")
    company.setValue(logo, forKey: "logo")


    do {
        try managedContext.save()
        companies.append(company)
    } catch let error as NSError {
        print("Could not save. \(error), \(error.userInfo)")
    }

    tableView.reloadData()
}

假设您在 stockTextField 中输入 AAPL,只需使用:

    let newCompanyStockSymbol = stockTextField.text

导致 newCompanyStockSymbol 为:

    Optional("AAPL")

这不是您想要的 URL 字符串。关键部分最终是这样的:

    (%22Optional("AAPL")%22)

而是使用 guard 从文本字段中获取值:

    guard let newCompanyStockSymbol = stockTextField.text else {
        // handle the error how you see fit
        print("error getting text from field") 
        return
    }

现在你的 URL 应该被正确解析了。

--- 附加信息 ---

我不完全确定这里 'continued conversation' 的规则,但希望编辑它是可以接受的...无论如何...

确保您遵循以下流程:

func handleSave() {

    let newCompanyName = nameTextField.text
    let newCompanyStockSymbol = stockTextField.text
    let newCompanyLogo = logoTextField.text

    var newCompanyStockPrice = ""

    // Fetch stock price from symbol provided by user for new company
    let url = URL(string: "https://query.yahooapis.com/v1/public/yql?q=select%20symbol%2C%20Ask%2C%20YearHigh%2C%20YearLow%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22\(newCompanyStockSymbol)%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys")!
    let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
        if error != nil {
            print(error!)
        } else if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 {
            let json = JSON(data: data!)
            if let quotes = json["query"]["results"]["quote"].array {
                for quote in quotes {
                    let ask = quote["Ask"].stringValue
                    newCompanyStockPrice = ask

                    // task completed, we've parsed the return data, 
                    // so NOW we can finish the save process and 
                    // update the UI

                    viewController?.save(name: newCompanyName!, logo: newCompanyLogo!, stockPrice: newCompanyStockPrice)

                }
            }
        }
    }
    task.resume()        
}

我没有测试这个,所以它可能需要调整,你的 .save() 函数可能需要强制到主线程(因为它正在做 UI 更新)。但也许这样更清楚一些。