ios - 获取数据时返回相同的 YouTube 视频
问题描述
当我尝试从 YouTube 获取视频时,我的应用程序出现错误。它变成了相同的视频,因为当您点击它根据查询获取视频数据的项目之一时,我有一个表格视图单元格。这是我的应用程序的外观。
当我从不同的单元格中点击时,视频总是返回与我给出的图片相同的内容,这是我在视频控制器中的代码。当我试图知道当我用所需的 init 回击时会发生什么时,当我尝试打印tausiyah.name 时它崩溃说致命错误意外发现 nil ?“”但如果我改变tausiyah?.name ?? ” “崩溃消失。
var store: TausiyahStore!
var tausiyah: TausiyahItem! {
didSet {
navigationItem.title = tausiyah.name
}
}
override func viewDidLoad() {
super.viewDidLoad()
store.fetchSearchVideos(matching: tausiyah.name ?? "") { (videoResult) in
switch videoResult {
case let .success(videos):
print("Successfully found \(videos.count) video")
self.videoDataSource.videos = videos
case let .failure(error):
print("Error fetching search video: \(error)")
self.videoDataSource.videos.removeAll()
}
self.tableView.reloadSections(IndexSet(integer: 0), with: .automatic)
}
}
required init?(coder: NSCoder) {
print(tausiyah.name ?? "")
super.init(coder: coder)
}
deinit {
print(tausiyah.name ?? "")
}
这是我在视频控制器中实现的 tausiyahStore 中的获取图像
class TausiyahStore {
let imageStore = ImageStore()
func fetchSearchVideos(matching query: String, completion: @escaping (VideoResults) -> ()) {
let parameters = ["q": query]
let url = YoutubeAPI.youtubeURL(parameters: parameters)
let request = URLRequest(url: url)
let task = sessions.dataTask(with: request) { (data, response, error) in
let result = self.processVideoRequest(data: data, error: error)
OperationQueue.main.addOperation {
completion(result)
}
}
task.resume()
}
private func processVideoRequest(data: Data?, error: Error?) -> VideoResults {
guard let jsonData = data else {
return .failure(error!)
}
return YoutubeAPI.videos(fromJSON: jsonData)
func fetchImage(for video: Video, completion: @escaping (ImagesResult) -> ()) {
guard let videoKey = video.videoID else {
preconditionFailure("Video expected to have a video id")
}
if let image = imageStore.image(forKey: videoKey) {
OperationQueue.main.addOperation {
completion(.success(image))
}
return
}
guard let videoURL = video.url else {
preconditionFailure("Video expected to have video url")
}
let request = URLRequest(url: videoURL)
let task = sessions.dataTask(with: request) { (data, response, error) in
let result = self.processImageRequest(data: data, error: error)
print(result)
if case let .success(image) = result {
self.imageStore.setImage(image, forKey: videoKey)
}
OperationQueue.main.addOperation {
completion(result)
}
}
task.resume()
}
private func processImageRequest(data: Data?, error: Error?) -> ImagesResult {
guard
let imageData = data,
let image = UIImage(data: imageData) else {
if data == nil {
return .failure(error!)
} else {
return .failure(ThumbnailError.thumbnailCreationError)
}
}
return .success(image)
}
}
这是我的 imageStore 类,用于从 YoutubeAPI 创建缓存图像
class ImageStore {
// Create cache image in imageStore
let cache = NSCache<NSString, UIImage>()
// MARK: Set image to store the image in the imageStore for the item's key
func setImage(_ image: UIImage, forKey key: String) {
cache.setObject(image, forKey: key as NSString)
// To-Do: Get the URL and save the image as data
// Create full URL for image
let url = imageURL(forKey: key)
// Turn image into JPEG data
if let data = image.jpegData(compressionQuality: 0.5) {
// Write it to full URL
let _ = try? data.write(to: url, options: [.atomic])
}
}
// MARK: Return image data from the existing disk with key, and return it into an image
func image(forKey key: String) -> UIImage? {
if let existingImage = cache.object(forKey: key as NSString) {
return existingImage
}
let url = imageURL(forKey: key)
guard let imageFromDisk = UIImage(contentsOfFile: url.path) else { return nil }
cache.setObject(imageFromDisk, forKey: key as NSString)
return imageFromDisk
}
// MARK: Delete image from disk with key
func deleteImage(forKey key: String) {
cache.removeObject(forKey: key as NSString)
let url = imageURL(forKey: key)
do {
try FileManager.default.removeItem(at: url)
} catch let deleteError {
print("Error removing the image from disk: \(deleteError)")
}
}
// MARK: Store image in document directory
private func imageURL(forKey key: String) -> URL {
let documentsDirectories = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentDirectory = documentsDirectories.first!
return documentDirectory.appendingPathComponent(key)
}
}
你能告诉我错误在哪里吗,谢谢你的帮助:)
解决方案
很抱歉麻烦帮助我解决这个问题的开发人员,我终于找到了我的问题的答案。问题出在我的 YoutubeAPI 结构中的 YoutubeURL 函数中,问题是我的函数添加了一个参数,该参数试图替换我的 baseParams 中的现有参数。我现在才知道您无法替换已经存在的查询,因为我尝试使用参数添加其他查询但它失败了。
这是我之前的 YoutubeURL 功能
static func youtubeURL(parameters: [String: String]?) -> URL {
var components = URLComponents(string: baseURLString)!
var queryItems = [URLQueryItem]()
let baseParams = [
"part": "snippet",
"key": apiKey,
"q": "tausiyah"
]
for (key, value) in baseParams {
queryItems.append(URLQueryItem(name: key, value: value))
}
if let additionalParams = parameters {
for (key, value) in additionalParams {
queryItems.append(URLQueryItem(name: key, value: value))
}
}
components.queryItems = queryItems
return components.url!
}
这是我的解决方案我仍然不知道这是正确的解决方案,但它确实有效
static func youtubeURL(withAdditionalQuery query: String) -> URL {
var components = URLComponents(string: baseURLString)!
var queryItems = [URLQueryItem]()
let baseParams = [
"part": "snippet",
"key": apiKey,
"q": "tausiyah \(query)"
]
for (key, value) in baseParams {
queryItems.append(URLQueryItem(name: key, value: value))
}
components.queryItems = queryItems
components.percentEncodedQuery = components.percentEncodedQuery?.replacingOccurrences(of: "%20", with: "+")
return components.url!
}
感谢所有试图帮助我快乐编码的人:)