2017-02-08 7 views
0

Ниже у меня есть существующие загрузки запросов и ячейка для кода строки таблицы ...Slow CloudKit прокрутка таблицы - изменение существующего кода?

publicDB.perform(query, inZoneWith: nil) 
    { 
     (results, error) -> Void in 
     if (error != nil) 
     { 
      self.present(alert, animated: true, completion: nil) 
     } 
     else 
     { 
      for result in results! 
      { 
       self.restaurantArray.append(result) 
      } 
      OperationQueue.main.addOperation({() -> Void in 
       self.tableView.reloadData() 
      }) } }} 
downloadRestaurants() 
} 

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "restaurantcell") as? RestaurantTableCell 
    let restaurant: CKRecord = restaurantArray[indexPath.row] 
    cell?.name?.text = restaurant.value(forKey: "Name") as? String 
    let asset = restaurant.value(forKey: "Picture") as! CKAsset 
    let data = try! Data(contentsOf: asset.fileURL) 
    _ = UIImage(data: data) 
    cell?.picture?.image = UIImage(data: data) 
    return cell! 
} 

Когда я запускаю этот код, приложение остается функциональным, но прокрутка ячеек таблицы 10 или так невероятно изменчивые. Я не уверен, что вызывает это - все записи, каждый из которых содержит изображение, загружаются во время загрузки запроса верхней функции. Тем не менее, проблема или концепция, которую я пропускаю, когда-либо присутствовали во время выполнения. Что мне здесь не хватает? Ленивая загрузка? кэш? что-то другое? На данный момент не уверен, поэтому любая помощь будет невероятно полезна.

Update 1:

Я обновил мой код с большим спасибо вы собираетесь Пирс. Мне пришлось немного обновить мой код из его ответа, чтобы сохранить массив ckrecord, чтобы перейти к другому контроллеру через - restaurantArray, но также создать новый массив для класса NSObject - tablerestaurantarray, который будет отображаться в текущем контроллере таблицы.

var restaurantArray: Array<CKRecord> = [] 
    var tablerestaurantarray: [Restaurant] = [] 

for result in results! 
      { 
       let tablerestaurant = Restaurant() 

       if let name = result.value(forKey: "Name") as! String? { 
        tablerestaurant.name = name 
       } 
       // Do same for image 
       if let imageAsset = result.object(forKey: "Picture") as! CKAsset? { 

        if let data = try? Data(contentsOf: imageAsset.fileURL) { 
         tablerestaurant.image = UIImage(data: data) 
        } 
       } 
       self.tablerestaurantarray.append(tablerestaurant) 

       self.restaurantArray.append(result) 
      } 
      OperationQueue.main.addOperation({() -> Void in 
       self.tableView.reloadData()  
      }) 
     } 
    } 
} 
downloadRestaurants() 
} 
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    return restaurantArray.count 
} 
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "restaurantcell") as? RestaurantTableCell 

    let restaurant: Restaurant = tablerestaurantarray[indexPath.row] 
    cell?.name?.text = restaurant.name 

    cell?.picture?.image = restaurant.image 
    return cell! 
} 
+1

Каждый раз, когда вы прокручиваете таблицу TableView, ваше приложение должно конвертировать 'CKAsset' в' Data', а затем конвертировать его в 'UIImage'.Я бы рекомендовал создать какой-то «NSObject», называемый «Ресторан» или что-то в этом роде, затем, когда вы выполняете свой запрос, возьмите каждую запись из массива «CKRecords» и проанализируйте ее в «Ресторане», который имеет 'UIImage' затем используйте изображения из этих объектов для заполнения ячеек. Таким образом, он просто должен захватить UIImage, а не конвертировать его каждый раз. – Pierce

+0

Можете ли вы предоставить образец кода, Пирс? Мне никогда не приходилось работать с NSObjects в моих проектах, поэтому я немного отстаю от этого. – Jon

+0

см. Мой ответ ниже – Pierce

ответ

1

Путь ваш код установки, всякий раз, когда вы перечисляете в вашем UITableView, ваша программа преобразования CKAsset в Data, а затем преобразовать, что в UIImage, и это в каждой клетке! Это довольно неэффективный процесс, поэтому попробуйте создать NSObject, назвав что-то вроде Restaurant, у которого есть свойство изображения, и когда вы просматриваете все записи, возвращаемые с вашего CKQuery, проанализируйте каждую запись в новом объекте Restaurant. Чтобы создать новый NSObject, перейдите в меню Файл -> Новый -> Файл -> выберите 'Swift File' и добавить что-то вроде этого:

import UIKit 

class Restaurant: NSObject { 

    // Create a UIImage property 
    var image: UIImage? 

    // Add any other properties, i.e. name, address, etc. 
    var name: String = "" 
} 

Теперь для вашего запроса:

// Create an empty array of Restaurant objects 
var restaurantArray: [Restaurant] = [] 

publicDB.perform(query, inZoneWith: nil) { (results, error) -> Void in 
    if (error != nil) { 
     self.present(alert, animated: true, completion: nil) 
    } else { 
     for result in results! { 

      // Create a new instance of Restaurant 
      let restaurant = Restaurant() 

      // Use optional binding to check if value exists 
      if let name = result.value(forKey: "Name") as! String? { 
       restaurant.name = name 
      } 
      // Do same for image 
      if let imageAsset = result.object(forKey: "Picture") as! CKAsset? { 

       if let data = try? Data(contentsOf: imageAsset.fileURL) { 
        restaurant.image = UIImage(data: data) 
       } 
      } 

      // Append the new Restaurant to the Restaurants array (which is now an array of Restaurant objects, NOT CKRecords) 
      self.restaurantArray.append(restaurant) 
     } 
     OperationQueue.main.addOperation({() -> Void in 
      self.tableView.reloadData() 
     }) 
    } 
} 

Теперь ваша клетка установка гораздо проще:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

    let cell = tableView.dequeueReusableCell(withIdentifier: "restaurantcell") as? RestaurantTableCell 

    let restaurant: Restaurant = restaurantArray[indexPath.row] 
    cell?.name?.text = restaurant.name 

    cell?.picture?.image = restaurant.image 
    return cell! 
} 
0

Вы должны использовать CKQueryOperation, чтобы реализующие пагинации для UITableView.

Вы должны установить resultLimit свойство числа равна количеству клеток visiable в одно время на вас столе плюс 3 или 4

Set recordFetchedBlock собственности, где вы должны реализовать код, который будет применяться к одному CKRecord

queryCompletionBlock Недвижимость. Это самая важная часть вашего кода разбивки на страницы, потому что это закрытие получает необязательный параметр CKQueryCursor.

Если этот CKQueryCursor имеет значение nil, то вы дойдете до последней записи, доступной для вашего запроса, но если это значение, отличное от нуля, у вас есть больше записей, которые будут извлекаться с использованием этого CKQueryCursor в качестве индикатора для следующей выборки.

Когда пользователь просматривает ваш TableView и достигает последнего элемента, вы должны выполнить другую выборку с помощью CKQueryCursor.

Другие рекомендации по эффективности: CKAssets следует обрабатывать в отдельных очередях выполнения.

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