- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以我有一个 UICollectionView,一旦用户在搜索栏中输入一些文本,它就会显示图像。第一次效果很好,但是一旦您尝试再次搜索某些内容,您会得到:
无法解码:dataCorrupted(Swift.DecodingError.Context(codingPath:[],debugDescription:“给定的数据不是有效的 JSON。”,underlyingError:可选(Error Domain = NSCocoaErrorDomain Code = 3840“JSON 文本未以数组或对象开头,且未设置允许片段的选项。"UserInfo={NSDebugDescription=JSON 文本未以数组或对象开头,且未设置允许片段的选项。})))
我检查了从请求发送的路径,它完全符合预期。看起来和第一个一模一样。我不明白这是怎么回事......
模型类
import Foundation
struct Image{
let name: String?
let imageUrl: String?
init(name: String? = nil, imageUrl: String? = nil) {
self.name = name
self.imageUrl = imageUrl
}
}
struct ImageObject: Codable {
let value: [Value]?
let queryExpansions: [QueryExpansions]?
let pivotSuggestions: [PivotSuggestions]?
let similarTerms: [SimilarTerms]?
let relatedSearches: [RelatedSearches]?
}
struct Value: Codable {
let name: String?
let contentUrl: String?
let imageId: String?
let thumbnailUrl: String?
}
struct QueryExpansions: Codable {
let text: String?
let thumbnail: ThumbnailWithUrl?
}
struct PivotSuggestions: Codable {
let suggestions: [Suggestions]?
}
struct Suggestions: Codable {
let text: String?
let thumbnail: ThumbnailWithUrl?
}
struct SimilarTerms: Codable {
let text: String?
let thumbnail: Thumbnail?
}
struct RelatedSearches: Codable {
let text: String?
let thumbnail: ThumbnailWithUrl?
}
struct Thumbnail: Codable {
let url: String?
}
struct ThumbnailWithUrl: Codable {
let thumbnailUrl: String?
}
API_Service 类
class API_Service{
static let sharedAPIService = API_Service()
func fetchImagesFromSearch(request: String ,completionHandler:@escaping(ImageObject?) ->()){
var path = "https://api.cognitive.microsoft.com/bing/v7.0/images/search"
let searchRequest = "q=" + request
let array = [
// Request parameters
searchRequest,
//"count=10",
//"offset=0",
"mkt=en-us",
"safeSearch=Moderate",
]
let string = array.joined(separator: "&")
path = path + "?" + string
guard let url = URL(string: path) else { return }
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "GET"
urlRequest.setValue("KeyGoesHere", forHTTPHeaderField: "Ocp-Apim-Subscription-Key")
urlRequest.httpBody = path.data(using: .utf8)
URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if(error != nil){
print("Error: \(error!)")
completionHandler(nil)
}
guard let data = data else { return }
do{
let results = try JSONDecoder().decode(ImageObject.self, from: data)
completionHandler(results)
} catch let decodeError {
// Decode error, what should we show to the user?
print("Failed to decode: ", decodeError)
completionHandler(nil)
}
}.resume()
}
}
ViewController类
import UIKit
class mainViewController: UIViewController, UICollectionViewDelegate,
UICollectionViewDataSource, UISearchBarDelegate {
@IBOutlet weak var mainCollectionView: UICollectionView!
var images = [Image]()
let mainCollectionViewCellReusableIdentifier = "mainCollectionViewCell"
let searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
setupLayout()
setupSearchController()
title = "Search something!"
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
navigationItem.hidesSearchBarWhenScrolling = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func fetchImagesOf(searchText: String){
API_Service.sharedAPIService.fetchImagesFromSearch(request: searchText) { (data) in
if let results = data{
if let values = results.value{
self.collectImagesFromValue(using: values)
}
if let queryExpansions = results.queryExpansions{
self.collectImagesFromQueryExpansions(using: queryExpansions)
}
if let pivotSuggestions = results.pivotSuggestions{
self.collectImagesFromPivotSuggestions(using: pivotSuggestions)
}
if let similarTerms = results.similarTerms{
self.collectImagesFromSimilarTerms(using: similarTerms)
}
if let relatedSearches = results.relatedSearches{
self.collectImagesFromRelatedSearches(using: relatedSearches)
}
DispatchQueue.main.async {
self.mainCollectionView.reloadData()
}
}
}
}
func collectImagesFromValue(using results: [Value]){
for image in results{
if let url = image.thumbnailUrl{
let name = image.name ?? ""
let image = Image(name: name, imageUrl: url)
self.images.append(image)
}else{ continue }
}
}
func collectImagesFromQueryExpansions(using results: [QueryExpansions]){
for image in results{
if let thumbnail = image.thumbnail{
if let thumbnailUrl = thumbnail.thumbnailUrl{
let name = image.text ?? ""
let image = Image(name: name, imageUrl: thumbnailUrl)
self.images.append(image)
}else { continue }
}else{ continue }
}
}
func collectImagesFromPivotSuggestions(using results: [PivotSuggestions]){
for image in results{
if let suggestions = image.suggestions{
for suggestion in suggestions{
let name = suggestion.text ?? ""
if let thumbnail = suggestion.thumbnail{
if let thumbnailUrl = thumbnail.thumbnailUrl{
let image = Image(name: name, imageUrl: thumbnailUrl)
self.images.append(image)
}
}else { continue }
}
}else{ continue }
}
}
func collectImagesFromSimilarTerms(using results: [SimilarTerms]){
for image in results{
if let thumbnail = image.thumbnail{
if let thumbnailUrl = thumbnail.url{
let name = image.text ?? ""
let image = Image(name: name, imageUrl: thumbnailUrl)
self.images.append(image)
}else { continue }
}else{ continue }
}
}
func collectImagesFromRelatedSearches(using results: [RelatedSearches]){
for image in results{
if let thumbnail = image.thumbnail{
if let thumbnailUrl = thumbnail.thumbnailUrl{
let name = image.text ?? ""
let image = Image(name: name, imageUrl: thumbnailUrl)
self.images.append(image)
}else { continue }
}else{ continue }
}
}
func setupLayout(){
let layout = UICollectionViewFlowLayout()
let cellHeight = view.frame.size.width / 3
let cellWidth = cellHeight
let cellSize = CGSize(width: cellWidth, height: cellHeight)
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.itemSize = cellSize
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0
mainCollectionView.collectionViewLayout = layout
}
func setupSearchController(){
searchController.searchBar.delegate = self
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search for images"
navigationItem.searchController = searchController
definesPresentationContext = true
navigationItem.hidesSearchBarWhenScrolling = false
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
fetchImagesOf(searchText: searchBar.text!)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count > 0 ? images.count : 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: mainCollectionViewCellReusableIdentifier, for: indexPath) as! MainCollectionViewControllerCell
if images.count > 0{
cell.image = images[indexPath.row]
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let imageViewController = storyBoard.instantiateViewController(withIdentifier: "imageViewController") as! ImageViewController
imageViewController.image = images[indexPath.item]
navigationController?.pushViewController(imageViewController, animated: true)
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
JSON
{
"_type": "Images",
"instrumentation": {
"_type": "ResponseInstrumentation"
},
"readLink": "https://api.cognitive.microsoft.com/api/v7/images/search?
q=cats",
"webSearchUrl": "https://www.bing.com/images/search?q=cats&FORM=OIIARP",
"totalEstimatedMatches": 955,
"nextOffset": 5,
"value": [
{
"webSearchUrl": "https://www.bing.com/images/search? view=detailv2&FORM=OIIRPO&q=cats&id=6B6E51236064B16189141D1916C6F188AB1D8FD1&simid=608039789623643813",
"name": "Cute Cats #5 - Pets Cute and Docile",
"thumbnailUrl": "https://tse2.mm.bing.net/th?id=OIP.U5GJh9jyKpFuhBIt_EEZvAHaE9&pid=Api",
"datePublished": "2018-06-19T21:32:00.0000000Z",
"contentUrl": "http://4.bp.blogspot.com/-o5XBs5uRifo/UIUQeuyqoMI/AAAAAAAAHm0/h-XH1IR3l6Y/s1600/cats_animals_cat_desktop_3872x2592_hd-wallpaper-863122.jpeg",
"hostPageUrl": "http://dark-horse-adaptations.blogspot.com/2012/10/cute-cats-5.html",
"contentSize": "127935 B",
"encodingFormat": "jpeg",
"hostPageDisplayUrl": "dark-horse-adaptations.blogspot.com/2012/10/cute-cats-5.html",
"width": 1600,
"height": 1071,
"thumbnail": {
"width": 474,
"height": 317
},
"imageInsightsToken": "ccid_U5GJh9jy*mid_6B6E51236064B16189141D1916C6F188AB1D8FD1*simid_608039789623643813*thid_OIP.U5GJh9jyKpFuhBIt!_EEZvAHaE9",
"insightsMetadata": {
"recipeSourcesCount": 0,
"bestRepresentativeQuery": {
"text": "Crazy Cats Kittens Wallpaper",
"displayText": "Crazy Cats Kittens Wallpaper",
"webSearchUrl": "https://www.bing.com/images/search?q=Crazy+Cats+Kittens+Wallpaper&id=6B6E51236064B16189141D1916C6F188AB1D8FD1&FORM=IDBQDM"
},
"pagesIncludingCount": 32,
"availableSizesCount": 16
},
"imageId": "6B6E51236064B16189141D1916C6F188AB1D8FD1",
"accentColor": "666666"
},
{
"webSearchUrl": "https://www.bing.com/images/search?view=detailv2&FORM=OIIRPO&q=cats&id=F42DAAA598B5E0E1383CED35C292387266EB9A9F&simid=608030899010537949",
"name": "A Cat’s Tale: Meowing for the right kind of food - Zee ...",
"thumbnailUrl": "https://tse4.mm.bing.net/th?id=OIP.qtkOFD3PTouGYLHxi3xypwHaFj&pid=Api",
"datePublished": "2017-06-12T03:21:00.0000000Z",
"contentUrl": "http://zeelifestylecebu.com/wp-content/uploads/2015/03/cat3.jpg",
"hostPageUrl": "http://zeelifestylecebu.com/a-cats-tale-meowing-for-the-right-kind-of-food/",
"contentSize": "414235 B",
"encodingFormat": "jpeg",
"hostPageDisplayUrl": "zeelifestylecebu.com/a-cats-tale-meowing-for-the-right-kind-of-food",
"width": 1600,
"height": 1200,
"thumbnail": {
"width": 474,
"height": 355
},
"imageInsightsToken": "ccid_qtkOFD3P*mid_F42DAAA598B5E0E1383CED35C292387266EB9A9F*simid_608030899010537949*thid_OIP.qtkOFD3PTouGYLHxi3xypwHaFj",
"insightsMetadata": {
"recipeSourcesCount": 0,
"bestRepresentativeQuery": {
"text": "Cat Kitten",
"displayText": "Cat Kitten",
"webSearchUrl": "https://www.bing.com/images/search?q=Cat+Kitten&id=F42DAAA598B5E0E1383CED35C292387266EB9A9F&FORM=IDBQDM"
},
"pagesIncludingCount": 46,
"availableSizesCount": 20
},
"imageId": "F42DAAA598B5E0E1383CED35C292387266EB9A9F",
"accentColor": "8E553D"
},
{
"webSearchUrl": "https://www.bing.com/images/search?view=detailv2&FORM=OIIRPO&q=cats&id=A0401CF1F0E6DF84114EFA731FAF1CB360B3ED56&simid=607997879302688190",
"name": "cat | installect",
"thumbnailUrl": "https://tse3.mm.bing.net/th?id=OIP.WpkNnHDGdlljW4b1G_cl-QHaF7&pid=Api",
"datePublished": "2017-10-11T15:24:00.0000000Z",
"contentUrl": "https://installect.files.wordpress.com/2013/03/catsincup.jpg",
"hostPageUrl": "https://installect.wordpress.com/tag/cat/",
"contentSize": "274870 B",
"encodingFormat": "jpeg",
"hostPageDisplayUrl": "https://installect.wordpress.com/tag/cat",
"width": 1280,
"height": 1024,
"thumbnail": {
"width": 474,
"height": 379
},
"imageInsightsToken": "ccid_WpkNnHDG*mid_A0401CF1F0E6DF84114EFA731FAF1CB360B3ED56*simid_607997879302688190*thid_OIP.WpkNnHDGdlljW4b1G!_cl-QHaF7",
"insightsMetadata": {
"recipeSourcesCount": 0,
"bestRepresentativeQuery": {
"text": "Cute Good Morning Kitten",
"displayText": "Cute Good Morning Kitten",
"webSearchUrl": "https://www.bing.com/images/search?q=Cute+Good+Morning+Kitten&id=A0401CF1F0E6DF84114EFA731FAF1CB360B3ED56&FORM=IDBQDM"
},
"pagesIncludingCount": 420,
"availableSizesCount": 116
},
"imageId": "A0401CF1F0E6DF84114EFA731FAF1CB360B3ED56",
"accentColor": "72441C"
},
{
"webSearchUrl": "https://www.bing.com/images/search?view=detailv2&FORM=OIIRPO&q=cats&id=8CC6B40382B19534E56CEE711488ED9FDAF52B93&simid=607994756864674280",
"name": "Somali Cats – Jeanne Foguth's Blog",
"thumbnailUrl": "https://tse3.mm.bing.net/th?id=OIP.Csfth4IIGILGI31QVA54HgHaHg&pid=Api",
"datePublished": "2018-01-17T08:20:00.0000000Z",
"contentUrl": "https://foguth.files.wordpress.com/2014/11/19068-chocolate-somali-cat-white-background.jpg",
"hostPageUrl": "https://foguth.wordpress.com/tag/somali-cats/",
"contentSize": "260846 B",
"encodingFormat": "jpeg",
"hostPageDisplayUrl": "https://foguth.wordpress.com/tag/somali-cats",
"width": 1089,
"height": 1104,
"thumbnail": {
"width": 474,
"height": 480
},
"imageInsightsToken": "ccid_Csfth4II*mid_8CC6B40382B19534E56CEE711488ED9FDAF52B93*simid_607994756864674280*thid_OIP.Csfth4IIGILGI31QVA54HgHaHg",
"insightsMetadata": {
"recipeSourcesCount": 0,
"bestRepresentativeQuery": {
"text": "Chocolate Somali Cat",
"displayText": "Chocolate Somali Cat",
"webSearchUrl": "https://www.bing.com/images/search?q=Chocolate+Somali+Cat&id=8CC6B40382B19534E56CEE711488ED9FDAF52B93&FORM=IDBQDM"
},
"pagesIncludingCount": 12,
"availableSizesCount": 4
},
"imageId": "8CC6B40382B19534E56CEE711488ED9FDAF52B93",
"accentColor": "AF501C"
},
{
"webSearchUrl": "https://www.bing.com/images/search?view=detailv2&FORM=OIIRPO&q=cats&id=3FC937888C49B0641BC0A590AAF50FED74AEB93E&simid=608021153747308294",
"name": "Cat Pictures - Photos of Cats | Interesting Stuff",
"thumbnailUrl": "https://tse3.mm.bing.net/th?id=OIP.QjKAHyYfB4sQ9y_kbxEheAHaFA&pid=Api",
"datePublished": "2011-10-29T23:41:00.0000000Z",
"contentUrl": "http://www.cat-world.com.au/images/levi-sma2-big.jpg",
"hostPageUrl": "http://www.cat-world.com.au/cat-photos",
"contentSize": "800317 B",
"encodingFormat": "jpeg",
"hostPageDisplayUrl": "www.cat-world.com.au/cat-photos",
"width": 1590,
"height": 1075,
"thumbnail": {
"width": 474,
"height": 320
},
"imageInsightsToken": "ccid_QjKAHyYf*mid_3FC937888C49B0641BC0A590AAF50FED74AEB93E*simid_608021153747308294*thid_OIP.QjKAHyYfB4sQ9y!_kbxEheAHaFA",
"insightsMetadata": {
"recipeSourcesCount": 0,
"bestRepresentativeQuery": {
"text": "Singapura Cat Breed",
"displayText": "Singapura Cat Breed",
"webSearchUrl": "https://www.bing.com/images/search?q=Singapura+Cat+Breed&id=3FC937888C49B0641BC0A590AAF50FED74AEB93E&FORM=IDBQDM"
},
"pagesIncludingCount": 24,
"availableSizesCount": 12
},
"imageId": "3FC937888C49B0641BC0A590AAF50FED74AEB93E",
"accentColor": "614B3D"
}
],
最佳答案
这段代码就是您的问题所在。
urlRequest.httpMethod = "GET"
urlRequest.setValue("KeyGoesHere", forHTTPHeaderField: "Ocp-Apim-Subscription-Key")
urlRequest.httpBody = path.data(using: .utf8)
您的httpMethod
值为GET
。
但是,您可以在下面两行分配一个 httpBody
值。
执行 GET
请求时不会使用该字段。它通常用于在向 API 服务器发出 POST
请求期间发送表单数据等内容。
删除设置正文的行,请求应该可以正常工作。
关于ios - 给定数据不是有效的 JSON - 第二次搜索后发生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51603181/
IO 设备如何知道属于它的内存中的值在memory mapped IO 中发生了变化? ? 例如,假设内存地址 0 专用于保存 VGA 设备的背景颜色。当我们更改 memory[0] 中的值时,VGA
我目前正在开发一个使用Facebook sdk登录(通过FBLoginView)的iOS应用。 一切正常,除了那些拥有较旧版本的facebook的人。 当他们按下“使用Facebook登录”按钮时,他
假设我有: this - is an - example - with some - dashesNSRange将使用`rangeOfString:@“-”拾取“-”的第一个实例,但是如果我只想要最后
Card.io SDK提供以下详细信息: 卡号,有效期,月份,年份,CVV和邮政编码。 如何从此SDK获取国家名称。 - (void)userDidProvideCreditCardInfo:(Car
iOS 应用程序如何从网络服务下载图片并在安装过程中将它们安装到用户的 iOS 设备上?可能吗? 最佳答案 您无法控制应用在用户设备上的安装,因此无法在安装过程中下载其他数据。 只需在安装后首次启动应
我曾经开发过一款企业版 iOS 产品,我们公司曾将其出售给大型企业,供他们的员工使用。 该应用程序通过 AppStore 提供,企业用户获得了公司特定的配置文件(包含应用程序配置文件)以启用他们有权使
我正在尝试将 Card.io SDK 集成到我的 iOS 应用程序中。我想为 CardIO ui 做一个简单的本地化,如更改取消按钮标题或“在此保留信用卡”提示文本。 我在 github 上找到了这个
我正在使用 CardIOView 和 CardIOViewDelegate 类,没有可以设置为 YES 的 BOOL 来扫描 collectCardholderName。我可以看到它在 CardIOP
我有一个集成了通话工具包的 voip 应用程序。每次我从我的 voip 应用程序调用时,都会在 native 电话应用程序中创建一个新的最近通话记录。我在 voip 应用程序中也有自定义联系人(电话应
iOS 应用程序如何知道应用程序打开时屏幕上是否已经有键盘?应用程序运行后,它可以接收键盘显示/隐藏通知。但是,如果应用程序在分屏模式下作为辅助应用程序打开,而主应用程序已经显示键盘,则辅助应用程序不
我在模拟器中收到以下错误: ImageIO: CGImageReadSessionGetCachedImageBlockData *** CGImageReadSessionGetCachedIm
如 Apple 文档所示,可以通过 EAAccessory Framework 与经过认证的配件(由 Apple 认证)进行通信。但是我有点困惑,因为一些帖子告诉我它也可以通过 CoreBluetoo
尽管现在的调试器已经很不错了,但有时找出应用程序中正在发生的事情的最好方法仍然是古老的 NSLog。当您连接到计算机时,这样做很容易; Xcode 会帮助弹出日志查看器面板,然后就可以了。当您不在办公
在我的 iOS 应用程序中,我定义了一些兴趣点。其中一些有一个 Kontakt.io 信标的名称,它绑定(bind)到一个特定的 PoI(我的意思是通常贴在信标标签上的名称)。现在我想在附近发现信标,
我正在为警报提示创建一个 trigger.io 插件。尝试从警报提示返回数据。这是我的代码: // Prompt + (void)show_prompt:(ForgeTask*)task{
您好,我是 Apple iOS 的新手。我阅读并搜索了很多关于推送通知的文章,但我没有发现任何关于 APNS 从 io4 到 ios 6 的新更新的信息。任何人都可以向我提供 APNS 如何在 ios
UITabBar 的高度似乎在 iOS 7 和 8/9/10/11 之间发生了变化。我发布这个问题是为了让其他人轻松找到答案。 那么:在 iPhone 和 iPad 上的 iOS 8/9/10/11
我想我可以针对不同的 iOS 版本使用不同的 Storyboard。 由于 UI 的差异,我将创建下一个 Storyboard: Main_iPhone.storyboard Main_iPad.st
我正在写一些东西,我将使用设备的 iTunes 库中的一部分音轨来覆盖 2 个视频的组合,例如: AVMutableComposition* mixComposition = [[AVMutableC
我创建了一个简单的 iOS 程序,可以顺利编译并在 iPad 模拟器上运行良好。当我告诉 XCode 4 使用我连接的 iPad 设备时,无法编译相同的程序。问题似乎是当我尝试使用附加的 iPad 时
我是一名优秀的程序员,十分优秀!