使用 Alamofire 在 tableview 中操作 YouTube 播放列表 API
Posted
技术标签:
【中文标题】使用 Alamofire 在 tableview 中操作 YouTube 播放列表 API【英文标题】:Manipulate YouTube Playlist API in tableview using Alamofire 【发布时间】:2017-01-30 18:43:33 【问题描述】:我四处寻找我的问题的答案,但我没有运气。我是编码新手,尤其是 Swift 3.0。
我正在尝试在我的项目中使用 Alamofire 可可豆荚在表格视图中动态解析 YouTube 播放列表。我的项目包含:一个名为“videosViewController”的视图控制器,它包含 tableview,一个名为“Video”的类,它包含我从 youtube API 解析的项目,另一个名为“VideoModel”的类包含削减这些项目的方法。当我运行我的项目时,控制台成功解析了项目,但随后项目在代码行崩溃:
for video in (data["items"] as? NSDictionary)!
带有“无法将 '__NSArrayI' (0x10d2ebd88) 类型的值转换为 'NSDictionary' (0x10d2ec288)。”错误如下图
Project crash
Console details
这里是我使用的代码的 sn-p:
videosViewController:
import UIKit
class videosViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
@IBOutlet var tableView: UITableView!
var videos:[Video] = [Video]()
var selectedVideo: Video?
override func viewDidLoad()
super.viewDidLoad()
// Do any additional setup after loading the view.
let model = VideoModel()
model.fetchVideos()
self.tableView.dataSource = self
self.tableView.delegate = self
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
return (self.view.frame.size.width / 320) * 180
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return videos.count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "BasicCell")!
let videoTitle = videos[indexPath.row].videoTitle
let label = cell.viewWithTag(2) as! UILabel
label.text = videoTitle
let videoThumbnailUrlString = "https://i1.ytimg.com/vi/" + videos[indexPath.row].videoId + "/maxresdefault.jpg"
let videoThumbnailUrl = NSURL(string: videoThumbnailUrlString)
if videoThumbnailUrl != nil
let request = URLRequest(url: videoThumbnailUrl! as URL)
let session = URLSession.shared
let task = session.dataTask(with: request,
completionHandler: (data:Data?,
response:URLResponse?,
error:Error?) -> Void in
DispatchQueue.main.async
let imageView = cell.viewWithTag(1) as! UIImageView
imageView.image = UIImage(data: data!)
)
task.resume()
return cell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
self.selectedVideo = self.videos[indexPath.row]
self.performSegue(withIdentifier: "goToDetail", sender: self)
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
let detailView = segue.destination as! videoDetailViewController
detailView.selectedVideo = self.selectedVideo
视频类:
import UIKit
class Video: NSObject
var videoId:String = ""
var videoTitle:String = ""
var videoDescription:String = ""
var videoThumbnailURL = ""
还有 VideoModel 类:
import UIKit
import Alamofire
class VideoModel: NSObject
let parameters: Parameters = ["part":"snippet","playlistId":"PLMRqhzcHGw1ZRUB86rmNqG15Sr5jV-2NU","key":"AIzaSyDdNXhz3H7ifXB-qfOVakz0Xps2Y-kP0R0"]
var videoArray = [Video]()
func fetchVideos()
Alamofire.request("https://www.googleapis.com/youtube/v3/playlistItems", method: .get, parameters: parameters, encoding: URLEncoding.default, headers: nil).responseJSON (response:DataResponse<Any>) in
switch(response.result)
case .success(let JSON):
print("Success with JSON: \(JSON)")
if let data = response.result.value as? [String: AnyObject]
// print(response.result.value)
var arrayOfVideos = [Video]()
for video in (data["items"] as? NSDictionary)!
let videoObj = Video()
videoObj.videoId = (video.value as? NSDictionary)?["snippet.resourceId.videoId"] as? String ?? ""
videoObj.videoTitle = (video.value as? NSDictionary)?["snippet.title"] as? String ?? ""
videoObj.videoDescription = (video.value as? NSDictionary)?["snippet.description"] as? String ?? ""
videoObj.videoThumbnailURL = (video.value as? NSDictionary)?["snippet.thumbnails.maxres.url"] as? String ?? ""
print(video)
// You need to parse the items into the video data
arrayOfVideos.append(videoObj)
self.videoArray = arrayOfVideos
//
case .failure(let error):
print("Request failed with error: \(error)")
【问题讨论】:
错误告诉您data["items"]
是一个数组,但您将其作为字典抓取。我不确切知道返回的数据是什么样的,但我猜它的items
键可能包含一个字典数组。 (data["items"] as? NSArray)
可能会起作用。
感谢您的帮助,但是当我遵循您的建议时,我收到了一些错误,如下所示:'NSFastEnumerationIterator.Element' 类型的值(又名'Any')没有成员'值''跨度>
如何重写这个数组中的项目?
您期望video
是什么?你可能需要告诉它会发生什么。我会尝试使用guard let videoAsType = video as? <ExpectedClassOfVideo> else // handle error case
(或类似的if let
),然后从videoAsType
而不是video
读取video.value
。
【参考方案1】:
替换
as? NSDictionary
与
as? [String:Any]
在
for video in (data["items"] as? NSDictionary)!
Bcs:您必须将类型 Any 转换为 Swift 字典类型 [String:Any]。
if let JSON = response.result.value as? [String : Any]
if let items = JSON["items"] as? [[String : Any]]
for video in items
//Other code
【讨论】:
以上是关于使用 Alamofire 在 tableview 中操作 YouTube 播放列表 API的主要内容,如果未能解决你的问题,请参考以下文章
使用 Alamofire 在 tableview 中操作 YouTube 播放列表 API
通过 Alamofire,想获取数据并将其插入 TableView,但在完成插入之前,TableView 已加载
Swift 3 / Alamofire 4:在 TableView 上使用 ID 获取数据
在使用两个嵌套的 alamofire 请求滚动之前,TableView 不显示数据