SwiftUI:如何使用可选字符串解包 URL?

SwiftUI: How can I unwrap URL with optional String?

我是 SwiftUI 的新手,正在开发并尝试制作一款药物搜索应用 我正在制作一个搜索文本字段,其中显示了药物名称建议列表

这是结构中的数据数组和文本字段。

@State var drugNameSearch = [DrugNameSearch]()

TextField("Insert Drug Name" , text: $drugName, onEditingChanged: { isEdited in
                      self.isEdited = isEdited
                      self.isDrugSearched = isEdited
                      
              })
                  .frame(height:geometry.size.height/35)
                  .onChange(of: drugName, perform: { value in
                      self.fetchData()
                  })
              
              if isDrugSearched == true {                    
                  ForEach(drugNameSearch.filter({drugName.isEmpty ? false : [=11=].name.contains(drugName) }), id: \.self) { item in
                  HStack{
                      HStack{
                       Image(systemName: "magnifyingglass")
                       Text(item.name)
                      }
                      .onTapGesture{self.drugName = item.name}
                    Spacer()
                  }
                }
                  
              }
              else{}

下面是有问题的方法。 如果没有“&item_name=(drugName)”,该应用程序可以正常启动,但只能处理有限的数据。 使用下面的代码,应用程序会因 URL 展开问题而崩溃。 请多多指教...

 private func fetchData() {
   
    print("Drug Name Search Attempted!")

       let url = URL(string: "http://apis.data.go.kr/1471000/DrugPrdtPrmsnInfoService/getDrugPrdtPrmsnDtlInq?serviceKey=SERVICEKEY&item_name=\(drugName)&numOfRows=10&type=json")  
    
    URLSession.shared.dataTask(with: url!){(data, response, error) in
        do {
            if let drugNameData = data {
              let decodedData = try JSONDecoder().decode(DrugFetch.self, from: drugNameData)
                DispatchQueue.main.async {
                        self.drugNameSearch = decodedData.body.items
                }
            } else {
                print("No Data for drugNameSearch")
            }
        }
        catch {
            print("drugNameSearch Fetching Error: \(error)")
        }
        
    }//URLSession
    .resume()
    
}

您需要对 URL 查询字符串进行编码,因为并非所有字符都允许出现在 URL 中。您可以通过在查询 String.

上调用 addingPercentEncoding 来完成此操作
let baseUrl = "http://apis.data.go.kr/1471000/DrugPrdtPrmsnInfoService/getDrugPrdtPrmsnDtlInq"
let urlQuery = "?serviceKey=SERVICEKEY&item_name=\(drugName)&numOfRows=10&type=json"
guard let sanitisedUrl = urlQuery.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
    let url = URL(string:  baseUrl + urlQuery) else { return }

或者,您可以使用 URLComponents 并将查询设置为 query 属性,这将自动清理 String

guard var urlComponents = URLComponents(string: "http://apis.data.go.kr/1471000/DrugPrdtPrmsnInfoService/getDrugPrdtPrmsnDtlInq") else { return }
urlComponents.query = "serviceKey=SERVICEKEY&item_name=\(drugName)&numOfRows=10&type=json"
guard let url = urlComponents.url else { return }

尝试在你的 dataTask 之前添加一个守卫

let url = "http://apis.data.go.kr/1471000/DrugPrdtPrmsnInfoService/getDrugPrdtPrmsnDtlInq?serviceKey=SERVICEKEY&item_name=\(drugName)&numOfRows=10&type=json"

guard let url = URL(string: urlString)?.absoluteURL else {
   return // a custom error, like NetworkError.badURL
}