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).
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. I currently have 12 objects in my database so imagine with 100+ objects.
In 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
Couple of suggestion :
Don't show the data at cellForRowAtIndexPath: method 'cause at this time cell is not displayed yet. Try to use tableView:willDisplayCell:forRowAtIndexPath: method in the delegate of UITableView.
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. 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).
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. Going through this Ray Wenderlich tutorial should give you a good foundation.
Then it's probably a good idea to learn about URLSession which is used for performing asynchronous network requests in iOS apps. Again Ray Wenderlich has a great starter tutorial .
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:
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()
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.