2017-01-08 3 views
3

Я хотел загрузить данные в фоновый поток и обновить tableview/UI в основной теме. Основываясь на том, что указано here про потокование, мне было интересно, является ли нижеприведенный ниже код. Я пытаюсь загрузить больше данных в виде пользовательских прокруток до определенного индекса и хотел бы убедиться, что пользовательский интерфейс не замерзает из-за потоковой передачи. Спасибо!Swift 3- Обновление пользовательского интерфейса из основной темы

func loadMore() { 
    guard !self.reachedEndOfItems else { 
     return 
    } 

    self.offset = self.offset! + 10 
    print("load more offset: \(self.offset)") 

    var start = 0 
    var end = 0 


    isPullToRefresh = false 

    let userCreds = UserDefaults.standard 

    var getReqString = "" 


    if userCreds.bool(forKey: "client_journal") == true || userCreds.bool(forKey: "user_journal") == true { 

     var pageNum = "" 
     if let pgNum = currentPgNum { 
      print(pgNum) 
      pageNum = String(pgNum) 
     } 
     var filterEntryType = "" 
     if let entryTypeStr = filtEntryType { 
      filterEntryType = entryTypeStr 
     } 

     var filterUserId = "" 
     if let userId = filtUserId { 
      filterUserId = userId 

     } 

     getReqString = "https://gethealthie.com/selected_entries.json?page=\(pageNum)&user_id=\(filterUserId)&entry_type=\(filterEntryType)&entry_filter=" 


    } else { 

     if let pgNum = currentPgNum { 
      print(pgNum) 

      getReqString = "https://gethealthie.com/entries.json?page=\(pgNum)" 
     } 

    } 


     BXProgressHUD.showHUDAddedTo(self.view) 
     let request = Alamofire.request(getReqString, method: .get, headers: [ 
      "access-token": userCreds.object(forKey: "access-token")! as! String, 
      "client": userCreds.object(forKey: "client")! as! String, 
      "token-type": userCreds.object(forKey: "token-type")! as! String, 
      "uid": userCreds.object(forKey: "uid")! as! String, 
      "expiry": userCreds.object(forKey: "expiry")! as! String 
      ]).responseJSON { (response:DataResponse<Any>) in 
       print(response.response) 

       let json = JSON(data: response.data!) 
       print(json) 

       print("yes") 
       print(json.count) 


       if userCreds.bool(forKey: "client_journal") == true || userCreds.bool(forKey: "user_journal") == true { 
        self.totalEntries = json["entries"].count 

        let totalEntryCount = json["entries"].count 
        start = 0 
        end = totalEntryCount 
       } else { 
        self.totalEntries = json["entries"].count 

        let totalEntryCount = json["entries"].count 
        start = 0 
        end = totalEntryCount 
       } 

       if self.totalEntries == 0 { 
        BXProgressHUD.hideHUDForView(self.view); 

       } else if end <= self.totalEntries { 
        var jourIdx = 0 

        let newPatient = Patient() 
        let newDietitian = Dietitian() 


        for i in start ..< end { 


         let allEntries = json["entries"] 
         print(allEntries) 
         print("Entry count in loadMore is \(allEntries.count)") 

         let entry = allEntries[i] 
         print(entry) 

         let category = entry["category"] 
         print(category) 


         let name = entry["entry_comments"] 
         let k = name["id"] 


         var indexStr = String(i) 

         //entry attributes 
         self.jsonIdx.add(indexStr) 

         self.type.add(entry["type"].stringValue) 
         self.desc.add(entry["description"].stringValue) 
         self.category.add(entry["category"].stringValue) 
         //food cell- metric stat == healthy int 
         self.metric_stat.add(entry["metric_stat"].stringValue) 
         self.dateCreate.add(entry["created_at"].stringValue) 
         self.viewed.add(entry["viewed"].stringValue) 
         self.seenStatusArr.add(entry["viewed"].stringValue) 
         self.comments.add(entry["entry_comments"].rawValue) 
         self.entryType.add(entry["category"].stringValue) 
         // "category" : entryType as AnyObject] 

         let posterInfo = entry["poster"] 
         let first = posterInfo["first_name"].stringValue 
         let last = posterInfo["last_name"].stringValue 
         let full = first + " " + last 
         self.captionName.add(full) 


         //food cell subcat 
         self.hungerInt.add(entry["percieved_hungriness"].stringValue) 
         self.prehunger.add(entry["ed_prehunger_string"].stringValue) 
         self.posthunger.add(entry["ed_posthunger_string"].stringValue) 
         self.emotions.add(entry["emotions_string"].stringValue) 
         self.reflection.add(entry["reflection"].stringValue) 


         print(self.comments) 
         self.id.add(entry["id"].stringValue) 
         self.entryImages.add(entry["image_url"].stringValue) 


         if i == end - 1 { 
          userCreds.set(json.count, forKey: "oldJsonCount") 

           BXProgressHUD.hideHUDForView(self.view) 

          DispatchQueue.main.async { 
           self.tableView.reloadData() 

          } 
        } 


       } else { 
        var reachedEndOfItems = true 
        BXProgressHUD.hideHUDForView(self.view); 
        print("reached the end") 
       } 

    } 
+0

как насчет запуска этого кода и посмотреть, действительно ли он делает или не замораживает пользовательский интерфейс? он даст вам верный ответ :) –

+0

похоже, что вы только делаете «reloadData» в главной очереди. вам также нужно поместить все, что вы хотите, в фоновый поток, поскольку, если вы его не поместите, он все равно будет в основном потоке. хотя, например, сеть по умолчанию работает в фоновом потоке, но в вашем случае это не так. –

+0

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

ответ

3

В вашем примере кода здесь, вы диспетчеризацию reloadData в основную очередь. Но это не нужно, потому что закрытие responseJSON уже запущено в основной очереди, поэтому нет необходимости отправлять что-либо. Таким образом, вы должны удалить эту отправку reloadData в основную очередь.

Теперь, если вы использовали URLSession, который по умолчанию работают закрытия на фоне очереди или если явно предусмотрена фоновую очередь в качестве параметра responseJSONqueue, то да, вы бы направить reloadData в основную очередь. Но это не единственное, что вам нужно для отправки в основную очередь, так как обновления вашей модели и обновления HUD также должны выполняться в главной очереди. Но это спорный вопрос, потому что это responseJSON уже работает его обработчик завершения на главной очереди.

Затем, в комментариях, вы позже спрашиваете, все ли это работает в главной очереди, следует ли отправлять все это в фоновый режим, как и в a previous question (предположительно, с намерением избежать блокировки основной очередь).

Оказалось, что это необязательно (и не желательно), потому что, пока обработка ответа в обработчике завершения responseJSON выполняется в основной очереди, сам сетевой запрос выполняется асинхронно. Вы отправили бы код обработчика завершения в фоновую очередь (или укажите фоновую очередь в качестве параметра на responseJSON), если вы делали что-то вычислительно интенсивное в закрытии. Но вам не нужно беспокоиться о том, что сетевой запрос блокирует основную очередь.

Нижняя линия, Alamofire делает это просто для вас, она выполняет запрос асинхронно, но запускает обработчики завершения в основной очереди. Он устраняет большую часть ручного кода GCD, с которым вы сталкиваетесь при использовании URLSession.

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