首页 > 解决方案 > 获取数据时返回相同的 YouTube 视频

问题描述

当我尝试从 YouTube 获取视频时,我的应用程序出现错误。它变成了相同的视频,因为当您点击它根据查询获取视频数据的项目之一时,我有一个表格视图单元格。这是我的应用程序的外观。

家庭VC

视频VC

当我从不同的单元格中点击时,视频总是返回与我给出的图片相同的内容,这是我在视频控制器中的代码。当我试图知道当我用所需的 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)
    }
}

你能告诉我错误在哪里吗,谢谢你的帮助:)

标签: iosswift

解决方案


很抱歉麻烦帮助我解决这个问题的开发人员,我终于找到了我的问题的答案。问题出在我的 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!
    }

感谢所有试图帮助我快乐编码的人:)


推荐阅读