【问题标题】:Swift 3 parsing youtube videos doesn't show results and keeps loading - IOS 10Swift 3 解析 youtube 视频不显示结果并继续加载 - IOS 10
【发布时间】:2016-12-10 00:57:36
【问题描述】:

我正在尝试通过 json 解析来获取 youtube 频道和视频,而且我是 Swift 3 的新手。但是,加载图标并没有消失,也没有显示任何结果,日志中没有错误。

这是我的代码:

1/ func getVideosForChannelAtIndex :

func getVideosForChannelAtIndex(_ index: Int!) {

    let playlistID = channelsDataArray[index]["playlistID"] as! String
    let urlString = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=\(playlistID)&key=\(apiKey)"
    let targetURL = URL(string: urlString)
    var url = URLRequest(url: targetURL!)
    url.httpMethod = "GET"
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        let httpStatus = response as? HTTPURLResponse

        if httpStatus!.statusCode == 200 && error != nil {



            do {
                let resultsDict = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! Dictionary<String, AnyObject>

                let items: Array<Dictionary<String, AnyObject>> = resultsDict["items"] as! Array<Dictionary<String, AnyObject>>

                for i in 0 ..< items.count {
                    let playlistSnippetDict = (items[i] as Dictionary<String, AnyObject>)["snippet"] as! Dictionary<String, AnyObject>

                    var desiredPlaylistItemDataDict = Dictionary<String, AnyObject>()

                    desiredPlaylistItemDataDict["title"] = playlistSnippetDict["title"]
                    desiredPlaylistItemDataDict["thumbnail"] = ((playlistSnippetDict["thumbnails"] as! Dictionary<String, AnyObject>)["default"] as! Dictionary<String, AnyObject>)["url"]
                    desiredPlaylistItemDataDict["videoID"] = (playlistSnippetDict["resourceId"] as! Dictionary<String, AnyObject>)["videoId"]

                    self.videosArray.append(desiredPlaylistItemDataDict)

                    self.tableView.reloadData()
                }
            } catch {
                print(error)
            }
        }
        else {
            print("Error while loading channel videos: \(error)")
        }

        self.activityView.isHidden = true
    }



        }

2/ func getChannelDetails :

func getChannelDetails(_ useChannelIDParam: Bool) {

    var urlString: String!

    if !useChannelIDParam {
        urlString = "https://www.googleapis.com/youtube/v3/channels?part=contentDetails,snippet&forUsername=\(desiredChannelsArray[channelIndex])&key=\(apiKey)"
    }
    else {
        urlString = "https://www.googleapis.com/youtube/v3/channels?part=contentDetails,snippet&id=\(desiredChannelsArray[channelIndex])&key=\(apiKey)"
    }

    let targetURL = URL(string: urlString)
    var request = URLRequest(url: targetURL!)
    request.httpMethod = "GET"
    URLSession.shared.dataTask(with: request) { (data, response, error) in
        let httpStatus = response as? HTTPURLResponse

        if httpStatus!.statusCode == 200 && error != nil {



            do {
                let resultsDict = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! Dictionary<String, AnyObject>

                let items: AnyObject! = resultsDict["items"] as AnyObject!
                let firstItemDict = (items as! Array<AnyObject>)[0] as! Dictionary<String, AnyObject>

                let snippetDict = firstItemDict["snippet"] as! Dictionary<String, AnyObject>

                var desiredValuesDict: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>()
                desiredValuesDict["title"] = snippetDict["title"]
                desiredValuesDict["description"] = snippetDict["description"]
                desiredValuesDict["thumbnail"] = ((snippetDict["thumbnails"] as! Dictionary<String, AnyObject>)["default"] as! Dictionary<String, AnyObject>)["url"]

                desiredValuesDict["playlistID"] = ((firstItemDict["contentDetails"] as! Dictionary<String, AnyObject>)["relatedPlaylists"] as! Dictionary<String, AnyObject>)["uploads"]


                self.channelsDataArray.append(desiredValuesDict)


                self.tableView.reloadData()

                self.channelIndex += 1
                if self.channelIndex < self.desiredChannelsArray.count {
                    self.getChannelDetails(useChannelIDParam)
                }
                else {
                    self.activityView.isHidden = true
                }
            } catch {
                print(error)
            }

        } else {
            print("Error while loading channel details: \(error)")
        }
    }



    }


    }

3/ func textFieldShouldReturn:

func textFieldShouldReturn(_ textField: UITextField) -> Bool {

    textField.resignFirstResponder()
    activityView.isHidden = false

    var type = "channel"
    if segmentDisplay.selectedSegmentIndex == 1 {

    type = "video"
        videosArray.removeAll(keepingCapacity: false)

    }
    var urlString = "https://www.googleapis.com/youtube/v3/search?part=snippet&q=\(textField.text)&type=\(type)&key=\(apiKey)"

    urlString = urlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!



    let targetURL = URL(string: urlString)

    var request = URLRequest(url: targetURL!)
    request.httpMethod = "GET"

URLSession.shared.dataTask(with: request) { (data, response, error) in
let httpStatus = response as? HTTPURLResponse
if httpStatus!.statusCode == 200 && error != nil {


    do {
        let resultsDict = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! Dictionary<String, AnyObject>

        let items: Array<Dictionary<String, AnyObject>> = resultsDict["items"] as! Array<Dictionary<String, AnyObject>>

        for i in 0 ..< items.count {
            let snippetDict = items[i]["snippet"] as! Dictionary<String, AnyObject>

            if self.segmentDisplay.selectedSegmentIndex == 0 {
                self.desiredChannelsArray.append(snippetDict["channelId"] as! String)
            }
            else {
                var videoDetailsDict = Dictionary<String, AnyObject>()
                videoDetailsDict["title"] = snippetDict["title"]
                videoDetailsDict["thumbnail"] = ((snippetDict["thumbnails"] as! Dictionary<String, AnyObject>)["default"] as! Dictionary<String, AnyObject>)["url"]
                videoDetailsDict["videoID"] = (items[i]["id"] as! Dictionary<String, AnyObject>)["videoId"]

                self.videosArray.append(videoDetailsDict)

                self.tableView.reloadData()
            }
        }
    } catch {
        print(error)
    }

    if self.segmentDisplay.selectedSegmentIndex == 0 {
        self.getChannelDetails(true)
    }

}
else {
    print("Error while loading channel videos: \(error)")
}

self.activityView.isHidden = true
    }


    return true


}

【问题讨论】:

  • 你在哪里调用 resume() ?您需要将 .resume() 添加到 dataTask 右花括号
  • 那是很多代码,至少你应该在发布它们之前修复缩进。
  • 我通过添加其他方法更新了代码,但找不到我应该插入您指定的 .resume() 的位置。如果代码和/或问题似乎很麻烦,我深表歉意,但我对 IOS 和 Stackoverflow 都是新手。谢谢狮子座;)。
  • 会做 Yuchen :) 我有缩进的问题,但会解决它。我是 Stackoverflow 的新手,对此感到抱歉。

标签: ios swift swift3 ios10


【解决方案1】:

正如 cmets 中提到的,您必须在每个任务上调用 resume(),因为默认情况下 URLSession 的所有任务都被挂起。

以这种方式使用你的单线:

URLSession.shared.dataTask(with: request) { (data, response, error) in

  ...

}.resume()

或者

let task = URLSession.shared.dataTask(with: request) { (data, response, error) in

  ...

}
task.resume()

顺便说一句,URLRequestinstances 根本不需要。 GET 是默认的 HTTP 方法。

注意:确保所有嵌入在带有字符串插值的 URL 中的可选值都已解包,否则您将得到文字 Optional("Foo") 字符串。例如第三个代码中的textField.text sn -p 绝对是可选的。

【讨论】:

  • 谢谢 Vadian :) 你能解释一下 .resume 的目的吗
  • 使用它,但获取的数据返回为 nil (null),我不知道似乎是什么问题。
  • 我怀疑这是否正确,但这是解开可选 textField.text 的方法:/* fetch an optional */ let textField.text = fetchOptionalString()/* now unwrap it */ if let unwrapped = textField.text { print(unwrapped) }
  • 是的,可选绑定 (if let) 是安全展开可选选项的推荐方法。
  • 仍然不起作用,我真的很困惑可能是什么原因没有返回结果,我确定这不是 403 授权错误,除了我很困惑。
猜你喜欢
  • 1970-01-01
  • 2013-07-27
  • 2016-11-15
  • 1970-01-01
  • 2012-04-05
  • 2021-07-26
  • 1970-01-01
  • 2012-02-03
  • 2017-02-15
相关资源
最近更新 更多