【问题标题】:How to display a playlist of a YouTube channel using YouTube API in Swift3如何在 Swift3 中使用 YouTube API 显示 YouTube 频道的播放列表
【发布时间】:2017-07-10 03:20:13
【问题描述】:

问题 1:

我正在使用 YouTube API 在 UITableView 中显示视频播放列表,但它不起作用。当我为单个视频制作它时效果很好,一个视频出现在UITableView中。

如何显示任何 YouTube 频道的播放列表?我在UITableView 中使用此代码。

我的UITableView 代码:

 import UIKit
 import AVFoundation

 class YTViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, AVAudioPlayerDelegate {

@IBOutlet weak var txtSearch: UITextField!
@IBOutlet weak var searchResultTableView: UITableView!

// Set up a network session
let session = URLSession.shared

// ReST GET static String parts
let BASE_URL: String = "https://www.googleapis.com/youtube/v3/"
let SEARCH_VIDEO: String = "channels?part=snippet&q="
let VIDEO_TYPE: String = "&id=UCJIc9yX_3iHE2CfmUqoeJKQ&key="
let API_KEY: String = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

@IBAction func btnSearchClicked(_ sender: UIButton) {

}

func getVideoList() {

    let methodArguments: [String: AnyObject] = [
        "query": txtSearch.text! as AnyObject
    ]

    // Format the search string (video title) for http request
    let videoTitle: String = escapedParameters(methodArguments)

    // Make the query url
    // sample: https://www.googleapis.com/youtube/v3/search?part=snippet&q=werewolf&type=video&key=AIzaSyDDqTGpVR7jxeozoOEjH6SLaRdw0YY-HPQ

    let searchVideoByTitle = BASE_URL + SEARCH_VIDEO + videoTitle + VIDEO_TYPE + API_KEY

    print("#####################\(searchVideoByTitle)")
    if let url = URL(string: searchVideoByTitle) {
        let request = URLRequest(url: url)
        // Initialise the task for getting the data
        initialiseTaskForGettingData(request, element: "items")
    }
}

// Array to store all the desired values dictionaries
var videosArray: Array<Dictionary<String, AnyObject>> = [[String: AnyObject]]()

func initialiseTaskForGettingData(_ request: URLRequest, element: String) {

    // Initialize task for getting data
    // Refer to http://www.appcoda.com/youtube-api-ios-tutorial/

    let task = session.dataTask(with: request, completionHandler: {(data, HTTPStatusCode, error) in


        // Handler in the case of an error
        if error != nil {
            print(error as Any)
            return
        }
        else {
            // Parse that data received from the service
            let resultDict: [String: AnyObject]!
            do {
                // Convert the JSON data to a dictionary
                resultDict = try JSONSerialization.jsonObject(with: data! as Data, options: .allowFragments) as! [String: AnyObject]

                 print("***************************\(resultDict)")

                // Get the first item from the returned items
                if let itemsArray = (resultDict as AnyObject).value(forKey: element) as? NSArray {

                    // Remove all existing video data
                    self.videosArray.removeAll()

                    for index in 0..<itemsArray.count {

                        // Append the desiredVaules dictionary to the videos array
                        self.videosArray.append(self.unwrapYoutubeJson(arrayToBeUnwrapped: itemsArray, index: index))

                    }

                    // Asynchronously reload the data and display on the tableview
                    DispatchQueue.main.async {
                        // Reload the tableview
                        self.searchResultTableView.reloadData()
                    }
                }

            } catch let jsonError {
                print(jsonError)
            }
        }
    })
    // Execute the task
    task.resume()
}

func unwrapYoutubeJson(arrayToBeUnwrapped: NSArray, index: Int) -> [String: AnyObject]{

    let firstItemDict = arrayToBeUnwrapped[index] as! [String: AnyObject]

    // Get the snippet dictionary that contains the desired data
    let snippetDict = firstItemDict["snippet"] as! [String: AnyObject]

    // Dictionary to store desired video contents for display on tableview
    // desired values - "Title", "Description", "Thumbnail"
    var desiredValuesDict = [String: AnyObject]()

    desiredValuesDict["title"] = snippetDict["title"]
    desiredValuesDict["description"] = snippetDict["description"]

    // Further unwrap to get the Thumbnail default URL
    let thumbnailDict: [String: AnyObject]
    thumbnailDict = snippetDict["thumbnails"] as! [String: AnyObject]
    let defaultThumbnailDict = thumbnailDict["default"] as! [String: AnyObject]

    desiredValuesDict["thumbnail"] = defaultThumbnailDict["url"]

    //Get the id dictionary that contains videoId
    let idDict = firstItemDict["id"] as? [String: AnyObject]
    desiredValuesDict["videoId"] = idDict?["videoId"] 

    return desiredValuesDict
}

// Helper function: Given a dictionary of parameters, convert to a string for a url
func escapedParameters(_ parameters: [String : AnyObject]) -> String {

    var urlVars = [String]()

    for (key, value) in parameters {

        // Make sure that it is a string value
        let stringValue = "\(value)"

        // Escape it
        let escapedValue = stringValue.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)

        //Append it
        urlVars += [key + "=" + "\(escapedValue!)"]
    }

    return (!urlVars.isEmpty ? "" : "") + urlVars.joined(separator: "&")
}

// MARK: UITableView method implementation

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! SearchResultTableViewCell

    let videoSelected = videosArray[indexPath.row]
    cell.updateIU(video: videoSelected)

     cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator

    let id = videosArray[indexPath.row]["videoId"] as? String

    print("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\(id)")
     return cell
 }

  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return videosArray.count
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destination = segue.destination as? playerViewController {
        if let selectedRowIndexPath = searchResultTableView.indexPathForSelectedRow?.row {
            destination.mytitle = videosArray[selectedRowIndexPath]["title"] as! String
            destination.mydescript = videosArray[selectedRowIndexPath]["description"] as! String
            destination.myvideoId = videosArray[selectedRowIndexPath] ["videoId"] as? String
        }
    }
  }

override func viewDidLoad() {
    super.viewDidLoad()

     getVideoList()

    searchResultTableView.dataSource = self
    searchResultTableView.delegate = self
}


}

问题 2:

当我尝试使用 YTPlayerHelper 播放视频时,它不起作用: fatal error: unexpectedly found nil while unwrapping an Optional value,视频 ID 显示为 nil。

如何使用YTPlayerHelper 播放视频?这就是我播放视频的方式:

import UIKit
import youtube_ios_player_helper

class playerViewController: UIViewController {


@IBOutlet weak var MyPlayer: YTPlayerView!
@IBOutlet weak var txtTitle: UITextView!
@IBOutlet weak var txtDescript: UITextView!

var mytitle: String!
var mydescript: String!
var myvideoId : String!

override func viewDidLoad() {
    super.viewDidLoad()

    print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\(myvideoId)")

    MyPlayer.load(withVideoId: myvideoId!)

    txtTitle.text = mytitle
    txtDescript.text = mydescript

}
}

【问题讨论】:

    标签: ios swift3 youtube-api ytplayerview


    【解决方案1】:

    这是我的 Alamofire 实现;您必须调整名称以匹配您的名称:

    func callAlamo(url : String) {
        Alamofire.request(url).responseJSON(completionHandler: {
            response in
            self.parseData(JSONData: response.data!)
        })
    }
    
     func parseData(JSONData : Data) {
        do {
            var readableJSON = try JSONSerialization.jsonObject(with: JSONData, options: .mutableContainers) as! JSONStandard
            pageToken = readableJSON["nextPageToken"] as! String
            if previousPageButton.isEnabled {
                previousPageToken = readableJSON["prevPageToken"] as? String
            }
            if previousPageToken == nil {
                previousPageButton.isEnabled = false
            }
                    if let items = readableJSON["items"] as? [JSONStandard] {
                        for i in 0..<items.count  {
                            let item = items[i]
                            var name = String()
                            var previewURL1 = String()
                            if let id = item["id"] as? JSONStandard {
                                let url = id["videoId"] as! String
                                previewURL1 = url
                            }
                            let previewURL = previewURL1
                            if let snippet = item["snippet"] as? JSONStandard {
                                let title = snippet["title"] as! String
                                name = title
                                if let thumbnails = snippet["thumbnails"] as? JSONStandard {
                                    if let images = thumbnails["high"] as? JSONStandard {
                                        let mainImageURL = URL(string: images["url"] as! String)
                                        imageURL = images["url"] as! String
                                        let mainImageData = NSData(contentsOf: mainImageURL!)
    
                                        let mainImage = UIImage(data: mainImageData! as Data)
    
                                        posts.append(post.init(mainImage: mainImage, name: name, previewURL: previewURL, imageURL: imageURL))
                                        self.tableView.reloadData()
                                        nextPageButton.isEnabled = true
                                    }
                                }
                            }
                        }
                    }
        } catch {
            print(error)
        }
    }
    

    然后使用callAlamo(url: yourURL) 发出请求,将yourURL 替换为实际的URL。

    关于第二个问题,你有一个很棒的教程:http://www.appcoda.com/youtube-api-ios-tutorial/

    教程中是另一种使用 YouTube 视频更新 UITableView 的方法,但我个人更喜欢 Alamofire 方法,因为它更快更容易编写。我建议只查看正在播放的视频部分。

    【讨论】:

    • 我会支持你分享你自己的代码来解决这个离题的问题。
    • 谢谢!为什么跑题了?
    • 我不认为这是一个特定的问题,因为您看到您必须共享整个实现才能回答一半的问题。这不应该是一个教程网站“我如何显示播放列表......”无论如何,我赞成你对社区有帮助。 :)
    • 哦,我明白了。谢谢!
    • @user6603599 感谢您的回答,我的代码正在运行,但仅针对一个视频,如何才能使其在频道的播放列表中运行。
    猜你喜欢
    • 2017-11-11
    • 2018-02-19
    • 2013-02-23
    • 1970-01-01
    • 2011-02-12
    • 2018-10-31
    • 1970-01-01
    • 2011-04-05
    • 2011-07-04
    相关资源
    最近更新 更多