[英]Swift: How to refresh tableview without lag (UIRefreshControl)
Filling my table view with objects from a MYSQL database using PHP and JSON to Swift 3. I have a pull down to refresh function but when I'm pulling down to refresh it lags mid way for a second and then continues (like the wheel won't spin for a second). 使用PHP和JSON从Swift到MYSQL数据库中的对象填充表视图到Swift3。我有一个下拉刷新功能,但是当我下拉刷新时,它会滞后一秒钟,然后继续执行(就像滚轮一样)不会旋转一秒钟)。
How can I update my tableview smoother because I'm guessing as I add more content to the database in the future the bigger the lag. 我如何才能更平滑地更新tableview,因为我猜测随着日后向数据库中添加更多内容的滞后时间变大。 I currently have 12 objects in my database so imagine with 100+ objects.
我的数据库中目前有12个对象,因此可以想象有100多个对象。
In viewDidLoad 在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")
}
Then pull to refresh function 然后拉刷新功能
// 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()
}
Refer to the apple sample code at the following location: 请参阅以下位置的苹果示例代码:
http://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html http://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html
Couple of suggestion : 几个建议:
Don't show the data at cellForRowAtIndexPath: method 'cause at this time cell is not displayed yet. 不要在cellForRowAtIndexPath处显示数据:方法“因为此时尚未显示单元格。 Try to use tableView:willDisplayCell:forRowAtIndexPath: method in the delegate of UITableView.
尝试在UITableView的委托中使用tableView:willDisplayCell:forRowAtIndexPath:方法。
Re-Use single instance of cell/header/footer even if you need to show more. 重新使用单元格/页眉/页脚的单个实例,即使您需要显示更多。
Let me know if anything specific is needed. 让我知道是否需要任何具体说明。
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
}
}
My guess is that your retrieveDataFromServer() is blocking the main thread, and therefore causing the lag. 我的猜测是您的retrieveDataFromServer()阻塞了主线程,因此导致了延迟。 Try wrapping it in an async block
尝试将其包装在异步块中
// 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?()
}
I imagine the lag you're experiencing is due to the network request being executed synchronously on the main thread: 我想象您遇到的滞后是由于网络请求在主线程上同步执行:
let data: Data = try Data(contentsOf: url as URL)
Network requests are slow and should almost certainly be done off the main thread. 网络请求很慢,几乎可以肯定应该在主线程之外完成。 The solution here is to move the networking call to a background thread so the main (UI) thread doesn't get blocked (lag).
此处的解决方案是将网络调用移至后台线程,以使主(UI)线程不会被阻塞(滞后)。
So how do you do that? 那你怎么做呢? Well that is a large question with many different answers.
嗯,这是一个很大的问题,有许多不同的答案。
I highly recommend you spend some time learning about multi-threaded programming (also known as concurrency) in Swift. 我强烈建议您花一些时间来学习Swift中的多线程编程(也称为并发)。 Going through this Ray Wenderlich tutorial should give you a good foundation.
通过本Ray Wenderlich教程应该会为您奠定良好的基础。
Then it's probably a good idea to learn about URLSession which is used for performing asynchronous network requests in iOS apps. 那么了解URLSession可能是一个好主意,URLSession用于在iOS应用中执行异步网络请求。 Again Ray Wenderlich has a great starter tutorial .
雷·温德利奇(Ray Wenderlich)再次提供了很棒的入门教程 。
Finally... here is a quick and dirty solution for you. 最后...这是为您准备的快速而肮脏的解决方案。 It's "hacky" and you probably shouldn't use it, but it will probably fix your lag issue:
它是“ hacky”的,您可能不应该使用它,但是它可能会解决滞后问题:
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()
}
}
}
}
Try this: 尝试这个:
@objc func handleRefresh(_ refreshControl: UIRefreshControl) {
refreshControl.endRefreshing()
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
retrieveDataFromServer()
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.