2016-06-25 2 views
0

Я понимаю, что есть несколько подобных вопросов к этому, и я действительно проверил их много. Тем не менее, те, которые я проверил, были либо на неправильном языке, либо не на том, что я искал, поэтому я задаю новый вопрос. Для справки, я использую XCode 7.3.1 в Swift 2.UITableView отстает при прокрутке

Есть одна особенность моего нового приложения iOS, которое будет искать в Интернете данные и отображать результаты, заполняя UITableView. Моя проблема в том, что он отображает изображения в каждой ячейке, что делает прокрутку очень раздражающей.

Мое идеальное решение состояло бы в том, чтобы иметь дисплей изображения по умолчанию, и, позволяя пользователю продолжать прокрутку, он будет загружен в фоновом режиме. Затем, как только он его получит, он заменит значение по умолчанию. Я видел несколько предыдущих ответов о том, как это сделать, но никто не работал для меня.

P.S. Если вы видите еще один вопрос, который решает эту проблему WITH SWIFT, опубликуйте URL-адрес, и я удалю его.

Вот код, я использую в настоящее время (с запаздыванием):

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { // Creates each cell, by parsing through the data received from the Employees array which we returned from the database 
    if (Employees.count == 0) 
    { 
     let cell = self.ResultsTable.dequeueReusableCellWithIdentifier("NORESULT", forIndexPath: indexPath) as! TruckSearchNRTableViewCell 

     return cell 
    } 

    else { 
     let cell = self.ResultsTable.dequeueReusableCellWithIdentifier("RESULT", forIndexPath: indexPath) as! TruckSearchTableViewCell 

      cell.companyLabel.text = Employees[indexPath.row]["CompanyName"] as? String 
      cell.nameLabel.text = Employees[indexPath.row]["EmployeeName"] as? String 
     if let mobile = Employees[indexPath.row]["PhoneNumber"] as? String { 
      if (mobile == "") 
      { 
       cell.mobileLabel.hidden = true 
       cell.mobileTitle.hidden = true 
      } else { 
       cell.mobileTitle.hidden = false 
       cell.mobileLabel.hidden = false 
      } 
      let phonenumber = mobile.stringByReplacingOccurrencesOfString("[^0-9]", withString: "", options: NSStringCompareOptions.RegularExpressionSearch, range:nil); 
      cell.phoneNumber.text = phonenumber 
     } 
      cell.titleLabel.text = Employees[indexPath.row]["JobTitle"] as? String 
      cell.truckLabel.text = Employees[indexPath.row]["TruckNumber"] as? String 
      cell.supervisorLabel.text = Employees[indexPath.row]["SupervisorName"] as? String 
     if (Employees[indexPath.row]["Synced"] as? Int) == 0 { 
      turnRed(cell) 
     } else { 
      turnBlack(cell) 
     } 
     if let ePhoto = Employees[indexPath.row]["PicLocation"] as? String { // Save complete URL of picture location, and save it to the table 

      let url = NSURL(string: "https://exampleurl.com/\(ePhoto)")! 
      if let data = NSData(contentsOfURL: url){ 
       let myImage = UIImage(data: data) 
       cell.employeePhoto.image = myImage 
      } 
      else 
      { 
       cell.employeePhoto.image = UIImage(named: "person-generic") 
      } 

     } 

     return cell 
    } 
} 
+1

Пожалуйста, обратите внимание на [это] (http://stackoverflow.com/ a/26147814/1611876). Это в ObjC, но перевод его на Swift должен быть тривиальной задачей. Также вы хотели бы иметь механизм кеша, чтобы избежать загрузки каждого изображения каждый раз. [SDWebImage] (https://github.com/rs/SDWebImage) - это хорошее решение для того, чего вы хотите достичь, и вы будете готовы к использованию ** background downloading/caching/placeholder image **. – vhristoskov

+0

Я посмотрю, когда я получу шанс, спасибо! –

ответ

2

Проблема заключается в том, что вы запрашиваете изображение на главном потоке, который блокирует его. Все операции с пользовательским интерфейсом, включая прокрутку, выполняются по основному потоку, поэтому на данный момент он изменчив.

Чтобы решить эту проблему, вместо того, чтобы:

if let data = NSData(contentsOfURL: url){ 

    let myImage = UIImage(data: data) 
    cell.employeePhoto.image = myImage 

} else { 

    cell.employeePhoto.image = UIImage(named: "person-generic") 

} 

Поместить запрос изображения в фоновом потоке, а затем установить изображение на основной поток снова.

Например

let qos = QOS_CLASS_USER_INITIATED 

dispatch_async(dispatch_get_global_queue(qos, 0), { 

    if let data = NSData(contentsOfURL: url){ 

     let myImage = UIImage(data: data) 

     dispatch_async(dispatch_get_main_queue(), { 
      cell.employeePhoto.image = myImage 
     }) 

    } else { 

     dispatch_async(dispatch_get_main_queue(), { 
      cell.employeePhoto.image = UIImage(named: "person-generic") 
     }) 

    } 

}) 

в качестве альтернативы вы можете использовать асинхронную сессии URL-адрес, чтобы получить данные, как так:

let request: NSURLRequest = NSURLRequest(URL: url) 
let mainQueue = NSOperationQueue.mainQueue() 

NSURLConnection.sendAsynchronousRequest(request, queue: mainQueue, completionHandler: { (response, data, error) -> Void in 

    if error == nil { 

     let myImage = UIImage(data: data) 

     dispatch_async(dispatch_get_main_queue(), { 
      cell.employeePhoto.image = myImage 
     }) 

    } else { 

     dispatch_async(dispatch_get_main_queue(), { 
      cell.employeePhoto.image = UIImage(named: "person-generic") 
     }) 

    } 

}) 
+0

Это все еще довольно нервный, не может ли он быстро вернуться в камеру? –

+0

жаль, что я писал это на своем телефоне, пропустил заявление else. попробуйте мой отредактированный код и скажите, работает ли это. судя по вашему коду, это не должно быть проблемой скорости обработки. –

+0

Вам также нужно получить доступ к 'image.CGImage' в фоновом потоке, чтобы избежать декодирования данных изображения в основном потоке. Кроме того, поскольку ячейки будут повторно использоваться, этот ответ заставит некорректные изображения появляться на мгновение. –

Смежные вопросы