简体   繁体   English

异步加载图像不断导致图像闪烁?

[英]Asynchronously Loading Image constantly causes image to flicker?

I have a header view for every UITableViewCell . 我为每个UITableViewCell都有一个标题视图。 In this header view, I load a picture of an individual via an asynchronous function in the Facebook API. 在此标头视图中,我通过Facebook API中的异步函数加载个人的图片。 However, because the function is asynchronous, I believe the function is called multiple times over and over again, causing the image to flicker constantly. 但是,由于该函数是异步的,因此我相信该函数会被多次调用,从而导致图像不断闪烁。 I would imagine a fix to this issue would be to load the images in viewDidLoad in an array first, then display the array contents in the header view of the UITableViewCell . 我想解决此问题的方法是先将图像加载到viewDidLoad中的数组中,然后在UITableViewCell的标题视图中显示数组的内容。 However, I am having trouble implementing this because of the asynchronous nature of the function: I can't seem to grab every photo, and then continue on with my program. 但是,由于该函数的异步特性,我在实现它时遇到了麻烦:我似乎无法抓住每张照片,然后继续执行我的程序。 Here is my attempt: 这是我的尝试:

    //Function to get a user's profile picture
    func getProfilePicture(completion: (result: Bool, image: UIImage?) -> Void){
        // Get user profile pic
        let url = NSURL(string: "https://graph.facebook.com/1234567890/picture?type=large")
        let urlRequest = NSURLRequest(URL: url!)
        //Asynchronous request to display image
        NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue()) { (response:NSURLResponse!, data:NSData!, error:NSError!) -> Void in
            if error != nil{
                println("Error: \(error)")
            }
            // Display the image
            let image = UIImage(data: data)
            if(image != nil){
                completion(result: true, image: image)
            }
        }
    }
    override func viewDidLoad() {
      self.getProfilePicture { (result, image) -> Void in
          if(result == true){
              println("Loading Photo")
              self.creatorImages.append(image!)
          }
          else{
              println("False")
          }
      }
    }

    func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
      //Show section header cell with image
      var cellIdentifier = "SectionHeaderCell"
      var headerView = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as! SectionHeaderCell
      headerView.headerImage.image = self.creatorImages[section]
      headerView.headerImage.clipsToBounds = true
      headerView.headerImage.layer.cornerRadius = headerView.headerImage.frame.size.width / 2
      return headerView
    }

As seen by the program above, I the global array that I created called self.creatorImages which holds the array of images I grab from the Facebook API is always empty and I need to "wait" for all the pictures to populate the array before actually using it. 如上面的程序所示,我创建的名为self.creatorImages的全局数组保存着从Facebook API抓取的图像数组,始终为空,我需要“等待”所有图片,然后才能实际填充该数组使用它。 I'm not sure how to accomplish this because I did try a completion handler in my getProfilePicture function but that didn't seem to help and that is one way I have learned to deal with asynchronous functions. 我不确定如何完成此操作,因为我确实在getProfilePicture函数中尝试了完成处理程序,但这似乎无济于事,这是我学会处理异步函数的一种方法。 Any other ideas? 还有其他想法吗? Thanks! 谢谢!

I had the same problem but mine was in Objective-C Well, the structure is not that different, what i did was adding condition with: headerView.headerImage.image 我遇到了同样的问题,但是我的问题在Objective-C中,结构没什么不同,我所做的只是添加条件: headerView.headerImage.image

Here's an improved solution that i think suits your implementation.. since you placed self.getProfilePicture inside viewDidLoad it will only be called once section ==0 will only contain an image, 这是一个改进的解决方案,我认为适合您的实现。.由于您将self.getProfilePicture放置在viewDidLoad ,因此只有在section == 0时仅包含图像,它才会被调用,

the code below will request for addition image if self.creatorImages 's index is out of range/bounds 如果self.creatorImages的索引超出范围/界限,则下面的代码将请求添加图像

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
      //Show section header cell with image
      var cellIdentifier = "SectionHeaderCell"
      var headerView = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as! SectionHeaderCell


      if (section < self.creatorImages.count) // validate self.creatorImages index to prevent 'Array index out of range' error
      {
          if (headerView.headerImage.image == nil) // prevents the blinks
          {
              headerView.headerImage.image = self.creatorImages[section];
          }
      }
      else // requests for additional image at section
      {
          // this will be called more than expected because of tableView.reloadData()
          println("Loading Photo")

          self.getProfilePicture { (result, image) -> Void in
              if(result == true) {
                  //simply appending will do the work but i suggest something like:

                  if (self.creatorImages.count <= section)
                  {
                      self.creatorImages.append(image!)

                      tableView.reloadData()

                      println("self.creatorImages.count \(self.creatorImages.count)")
                  }
                 //that will prevent appending excessively to data source
              }
              else{
                  println("Error loading image")
              }
          }
      }

      headerView.headerImage.clipsToBounds = true
      headerView.headerImage.layer.cornerRadius = headerView.headerImage.frame.size.width / 2
      return headerView
    }

You sure have different implementation from what i have in mind, but codes in edit history is not in vain, right?.. hahahaha.. ;) Hope i've helped you.. Cheers! 您确定的实现方式与我的想法有所不同,但是编辑历史记录中的代码没有白费,对吧?..哈哈哈哈..;)希望我对您有所帮助..干杯!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM