【问题标题】:Two loops on nested functions cause index to go beyond range嵌套函数上的两个循环导致索引超出范围
【发布时间】:2016-04-30 14:27:02
【问题描述】:

我有一个调用 Parse.com 的函数,它通过循环返回一个包含 10 个 ID 的数组,然后对于每个 ID,它都会在 youtube 的 API 中找到它的数据,也带有一个循环。

我收到“索引超出范围”的错误,因为由于某种原因,索引不会在第二个循环中重新开始,而是从第一个循环停止时开始。有人能指出我做错了什么吗?

func recomendedQuery(completion: (result: String)->()) {
    let query = PFQuery(className: "VideosInfo")
    query.whereKeyExists("Rating")
    query.limit = 10
    query.orderByDescending("Rating")
    query.findObjectsInBackgroundWithBlock {
        (objects: [PFObject]?, error: NSError?) -> Void in
        if error == nil {
            for var i=0; i<10; i++ {
                let id = objects![i]["Video_ID"] as! String
                print(id) //No problems here
                self.recomQuery.append(id)
            }
            defaults.setObject(self.recomQuery, forKey: "recomQuery")
        } else {
            print(error?.description)
        }
    completion(result:"done")
    }
}

func getRecom(completion: (result:String)->()) {
    let array = defaults.arrayForKey("recomQuery")
    print(array![0])

    for var i=0; i<10; i++  {
    let videoURL = "https://www.googleapis.com/youtube/v3/videos?part=contentDetails%2C+snippet&id=\(array![i])&maxResults=10&key=\(apiKey)"

    Alamofire.request(.GET, videoURL).validate().responseJSON { response in
        switch response.result {
        case .Success:
            if let value = response.result.value {
                let json = JSON(value)
                let videoTitle = json["items"][i]["snippet"]["title"].stringValue
                let thumbPath = String(json["items"][i]["snippet"]["thumbnails"]["default"]["url"])
                print(videoTitle)
                print(thumbPath)
                print(i) //ERROR: PRINTS 10 AND ITS OUT OF BOUNDS
                let image = UIImage(data: NSData(contentsOfURL: NSURL(string: thumbPath)!)!)!
                let newImage: NSData = UIImagePNGRepresentation(image)!
                self.recomTitles.append(videoTitle)
                self.recomThumbs.append(newImage)
                defaults.setBool(true, forKey: "gotRecom")
                completion(result: "done")
            }
        case .Failure(let error):
            print(error)
            completion(result: "done")
            }
        }
    }
defaults.setObject(recomThumbs, forKey: "recomThumbs")
defaults.setObject(recomTitles, forKey: "recomTitles")
}

    recomendedQuery { (result:String) -> () in //Call functions
        //CHANGE TO ONLY IF SUCCESS
            Networking().getRecom() { (result:String) -> () in
            self.recomView.reloadData()
        }
    }

【问题讨论】:

  • 尝试使用for-in 循环,这样您就不会遇到这个问题。下次尝试缩小代码范围并仅显示相关信息,以便我们更轻松地为您提供帮助(通常到那时您也会发现问题)。
  • 谢谢!我试过了,但没有用..我也尝试过深入我的代码。我的问题是我不知道我的问题在哪里!
  • 我在 JavaScript 中看到过类似的问题——基本上在循环中创建闭包可能不会像你想象的那样表现。 i 将被闭包捕获,但如果它是通过引用捕获的,则 i 的值可以改变。有关详细信息,请参阅this issue
  • 这里有一个more detailed article 解释为什么使用for in 循环可以避免这个问题

标签: ios swift parse-platform youtube-api


【解决方案1】:

试试这样。这可能会对您有所帮助。

func getRecom(completion: (result:String)->()) {

    let array = defaults.arrayForKey("recomQuery")
    print(array![0])

    for (index, object) in enumerate(array) {

        let videoURL = "https://www.googleapis.com/youtube/v3/videos?part=contentDetails%2C+snippet&id=\(object)&maxResults=10&key=\(apiKey)"

        Alamofire.request(.GET, videoURL).validate().responseJSON { response in
            switch response.result {

            case .Success:
                if let value = response.result.value {
                    let json = JSON(value)
                    let videoTitle = json["items"][index]["snippet"]["title"].stringValue
                    let thumbPath = String(json["items"][index]["snippet"]["thumbnails"]["default"]["url"])
                    print(videoTitle)
                    print(thumbPath)
                    print(index)
                    let image = UIImage(data: NSData(contentsOfURL: NSURL(string: thumbPath)!)!)!
                    let newImage: NSData = UIImagePNGRepresentation(image)!
                    self.recomTitles.append(videoTitle)
                    self.recomThumbs.append(newImage)
                    defaults.setBool(true, forKey: "gotRecom")
                    completion(result: "done")
                }
            case .Failure(let error):
                print(error)
                completion(result: "done")
            }
        }
    }

    defaults.setObject(recomThumbs, forKey: "recomThumbs")
    defaults.setObject(recomTitles, forKey: "recomTitles")
}

recomendedQuery { (result:String) -> () in //Call functions
//CHANGE TO ONLY IF SUCCESS
Networking().getRecom() { (result:String) -> () in
self.recomView.reloadData()
}
}

【讨论】:

  • 什么是参与者?我收到一个“未声明”的错误。
  • 我的错,你必须使用你的数组。答案已编辑。立即尝试。谢谢
猜你喜欢
  • 2013-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-22
  • 2021-12-15
  • 1970-01-01
  • 2022-06-13
  • 1970-01-01
相关资源
最近更新 更多