2017-07-06 82 views
0

使用PHP和JSON填充我的表視圖與來自MYSQL數據庫的對象Swift 3.我有一個拉下來刷新功能,但當我拉下來刷新它在中途停留一秒鐘,然後繼續(如輪子不會旋轉一秒鐘)。Swift:如何刷新tableview沒有滯後(UIRefreshControl)

如何更新我的tableview更平滑,因爲我猜測,因爲我將更多的內容添加到數據庫中,未來滯後更大。我目前在我的數據庫中有12個對象,所以想象100個對象。

在viewDidLoad中

// Pull to Refresh 
    let refreshControl = UIRefreshControl() 
    refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged) 
    if #available(iOS 10.0, *) { 
     myTableView.refreshControl = refreshControl 
     print("iOS 10") 
    } else { 
     myTableView.addSubview(refreshControl) 
     print("iOS 9 or iOS 8") 
    } 

然後拉刷新功能

// Pull to Refresh 
func handleRefresh(refreshControl: UIRefreshControl) { 

    // Fetching Data for TableView 
    retrieveDataFromServer() 

    // Stop Refreshing 
    refreshControl.endRefreshing() 
} 

// Retrieving Data from Server 
func retrieveDataFromServer() { 

    // Loading Data from File Manager 
    loadData() 

    let getDataURL = "http://example.com/receiving.php" 
    let url: NSURL = NSURL(string: getDataURL)! 

    do { 
     let data: Data = try Data(contentsOf: url as URL) 
     let jsonArray = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSMutableArray 

     // Clear the arrays 
     self.followedArray = [Blog]() 
     self.mainArray = [Blog]() 

     // Looping through jsonArray 
     for jsonObject in jsonArray { 

      if let blog = Blog(jsonObject:jsonObject as! [String : Any]) { 

       // Check if Identifiers Match 
       if followedIdentifiers.contains(blog.blogID) { 
        self.followedArray.append(blog) 
       } else { 
        self.mainArray.append(blog) 
       } 
      } 
     } 
    } catch { 
     print("Error: (Retrieving Data)") 
    } 
    myTableView.reloadData() 
} 
+0

您呼叫的retrieveDataFromServer loaddata()()嘗試調用loadData()和API機制在後臺排隊。 。因爲它需要幾秒鐘才能加載loadData()和Api機制的所有參數 –

+0

@iOSGeek,即使我評論'// loadData()'它仍然滯後於 – BroSimple

+0

不要評論只是使用異步機制並嘗試使用,因爲for我這總是工作我應該評論基本的異步機制? –

回答

1
Spinner.isHidden = false 
    Spinner.startAnimating() 
    DispatchQueue.global(qos: .background).async { 
     loadData() 

    let getDataURL = "http://example.com/receiving.php" 
    let url: NSURL = NSURL(string: getDataURL)! 

    do { 
     let data: Data = try Data(contentsOf: url as URL) 
     let jsonArray = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSMutableArray 

     // Clear the arrays 
     self.followedArray = [Blog]() 
     self.mainArray = [Blog]() 

     // Looping through jsonArray 
     for jsonObject in jsonArray { 

      if let blog = Blog(jsonObject:jsonObject as! [String : Any]) { 

       // Check if Identifiers Match 
       if followedIdentifiers.contains(blog.blogID) { 
        self.followedArray.append(blog) 
       } else { 
        self.mainArray.append(blog) 
       } 
      } 
     } 
    } catch { 
     print("Error: (Retrieving Data)") 
    } 

     DispatchQueue.main.async 
     { 

      myTableView.reloadData() 
      self.Spinner.startAnimating() 
      self.Spinner.isHidden = true 
     } 
    } 
+0

我的API機制將'retrieveDataFromServer ()'代碼? – BroSimple

+0

我更新了請檢查 –

+0

給我一個崩潰說'這個應用程序正在從主線程訪問引擎後從後臺線程修改自動佈局引擎。 ' – BroSimple

1

參考蘋果樣本代碼在以下位置:

http://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html

夫婦建議的:

不要在cellForRowAtIndexPath:method中顯示數據,因爲此時單元格尚未顯示。嘗試在UITableView的委託中使用tableView:willDisplayCell:forRowAtIndexPath:方法。

即使您需要顯示更多,也可重複使用單元/頁眉/頁腳的單個實例。

讓我知道是否需要任何具體的東西。

1

我的猜測是你的retrieveDataFromServer()阻塞了主線程,因此造成了滯後。嘗試在一個異步塊

// Pull to Refresh 
func handleRefresh(refreshControl: UIRefreshControl) { 

    // Fetching Data for TableView 
    retrieveDataFromServer { [weak refreshControl] in 
     // This block will run once retrieveDataFromServer() is completed 

     // Reload data 
     myTableView.reloadData() 

     // Stop Refreshing 
     refreshControl?.endRefreshing() 
    } 
} 

// Retrieving Data from Server 
func retrieveDataFromServer(completion: (() -> Void)?) { 

    // Loading Data from File Manager 
    loadData() 

    let getDataURL = "http://example.com/receiving.php" 
    let url: NSURL = NSURL(string: getDataURL)! 

    do { 
     let data: Data = try Data(contentsOf: url as URL) 
     let jsonArray = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSMutableArray 

     // Clear the arrays 
     self.followedArray = [Blog]() 
     self.mainArray = [Blog]() 

     // Looping through jsonArray 
     for jsonObject in jsonArray { 

      if let blog = Blog(jsonObject:jsonObject as! [String : Any]) { 

       // Check if Identifiers Match 
       if followedIdentifiers.contains(blog.blogID) { 
        self.followedArray.append(blog) 
       } else { 
        self.mainArray.append(blog) 
       } 
      } 
     } 
    } catch { 
     print("Error: (Retrieving Data)") 
    } 

    // Calls completion block when finished 
    completion?() 
} 
1

包裝它,我設想在主線程同步執行您遇到的滯後是由於網絡請求:

let data: Data = try Data(contentsOf: url as URL) 

網絡請求是緩慢的,應該差不多了當然要完成主線程。這裏的解決方案是將網絡調用移動到後臺線程,以便主線程(UI)不會被阻塞(延遲)。

那麼你怎麼做到這一點?那麼這是一個有很多不同答案的大問題。

我強烈建議你花一些時間在Swift中學習多線程編程(也稱爲併發)。通過這個Ray Wenderlich tutorial應該給你一個很好的基礎。

然後,瞭解用於在iOS應用中執行異步網絡請求的URLSession可能是個好主意。雷文德里赫又一次很棒starter tutorial

終於...這是一個快速和骯髒的解決方案。這是「哈克」,你可能不應該使用它,但它可能會解決您的滯後問題:

func retrieveDataFromServer() { 

    // Loading Data from File Manager 
    loadData() 

    let getDataURL = "http://example.com/receiving.php" 
    let url: NSURL = NSURL(string: getDataURL)! 

    // Move to a background queue to fetch and process data from network. 
    DispatchQueue.global().async { 

     // Don't touch anything related to the UI here. 
     do { 
      let data: Data = try Data(contentsOf: url as URL) 
      let jsonArray = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSMutableArray 

      // Create new temp arrays to process json 
      var tempFollowedArray = [Blog]() 
      var tempMainArray = [Blog]() 

      // Looping through jsonArray 
      for jsonObject in jsonArray { 

       if let blog = Blog(jsonObject:jsonObject as! [String : Any]) { 

        // Check if Identifiers Match 
        if self.followedIdentifiers.contains(blog.blogID) { 
         tempFollowedArray.append(blog) 
        } else { 
         tempMainArray.append(blog) 
        } 
       } 
      } 

      // Jump back to main (UI) thread to update results 
      DispatchQueue.main.async { 
       print("success") 
       self.followedArray = tempFollowedArray 
       self.mainArray = tempMainArray 

       self.myTableView.reloadData() 
      } 
     } catch { 
      DispatchQueue.main.async { 
       print("Error: (Retrieving Data)") 
       // This reload is probably not necessary, but it was 
       // in your original code so I included it. 
       self.myTableView.reloadData() 
      } 
     } 
    } 
}