2017-01-08 5 views
3

バックグラウンドスレッドでデータをロードし、メインスレッドでtableview/UIを更新したかった。スレファリングについてhereと表示されているところに基づいて、私は以下のコードがそれについてどうやって行くのか疑問に思っていました。私はユーザーが特定のインデックスにスクロールし、スレッドが原因でUIがフリーズしていないことを確認したいときに、より多くのデータをロードしようとしています。ありがとうございました!ここにあなたのコードサンプルでSwift 3メインスレッドからのUIの更新

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

このコードを実行して、実際にUIがフリーズするかどうかを確認するにはどうすればよいですか?それはあなたに確かな答えを与えるでしょう:) –

+0

は、あなたがメインキュー内で 'reloadData'を行うように思えます。バックグラウンドスレッドに入れたいものはすべて置く必要があります。これを置かないとメインスレッドに残ります。たとえば、ネットワークはデフォルトでバックグラウンドスレッドで実行されますが、あなたの場合はそうではありません。 –

+0

@ TungFam私はそれを実行しようとしていると、特定のインデックスでより多くのデータを読み込むと、UIがフリーズしているようです。そのため、問題がスレッド化しているかどうかを正確に突き止めようとしていたのです。私は以前、私はバックグラウンドスレッドでUIを更新していると言われました。 – mir

答えて

3

、あなたがメインキューにreloadDataを派遣しています。しかし、それは不要です。responseJSONのクロージャが既にメインキューで実行されているため、何もディスパッチする必要はありません。したがって、reloadDataのディスパッチをメインキューに削除する必要があります。

さて、あなたはURLSessionを、使用していた場合はそのバックグラウンドキューにクロージャを実行しているか、あなたが明示的にresponseJSONqueueパラメータとして、バックグラウンドキューを提供した場合、その後、はい、あなたがメインキューにreloadDataを派遣したいデフォルト。しかし、モデルの更新とHUDの更新がメインキューで実行されるため、メインキューに確実にディスパッチする必要があるだけではありません。しかし、このresponseJSONは既にメインキューでその完了ハンドラを実行しているので、それは疑問です。

a previous questionのように、このすべてをバックグラウンドキューにディスパッチする必要があるかどうかをコメントで後で尋ねます(メインキューをブロックしたくないという意図があると思われますキュー)。

補完ハンドラresponseJSONの応答処理がメインキューで実行されている間に、ネットワーク要求自体が非同期に実行されるため、これは必ずしも必要ではないことが判明しました。クロージャで計算的に集中的な処理を行っていた場合は、完了ハンドラコードをバックグラウンドキューにディスパッチするだけです(または、バックグラウンドキューをパラメータとしてresponseJSONに指定します)。しかし、メインキューをブロックするネットワーク要求について心配する必要はありません。

ボトムラインAlamofireはこれを簡単にしています。要求を非同期で実行しますが、メインキューでその完了ハンドラを実行します。これは、URLSessionを使用するときに混乱させる多くの手動GCDコードを排除します。

関連する問題