I am using Firebase as my data structure. I use completion handler in my UITableView's refreshControl, in order to stop refreshing when finish loading all data from Firebase.
override func viewDidLoad() {
super.viewDidLoad()
self.refreshControl = UIRefreshControl()
self.refreshControl!.addTarget(self, action: #selector(refreshData),for: .valueChanged)
self.refreshControl!.attributedTitle = NSAttributedString(string: "Update the data")
refreshData{ _ in
self.refreshControl!.endRefreshing()
}
}
And this is my refreshData method
func refreshData(completionHandler:@escaping (Bool)->() ) {
//Remove old data
self.items.removeAll()
//Renew all data
var ref: DatabaseReference!
ref = Database.database().reference(withPath: "tasks")
//Loading local drafts
var drafts : [Task]!
if let local_drafts = NSKeyedUnarchiver.unarchiveObject(withFile: Task.ArchiveURL.path) as? [Task] {
drafts = local_drafts
}
else{
drafts = []
}
//Reloading the database
ref.observe(.value, with: { snapshot in
var newItems: [Task] = []
self.num_of_tasks = Int(snapshot.childrenCount)
for item in snapshot.children {
//let local = item as! DataSnapshot
//let snapshotValue = local.value as! [String: AnyObject]
//print(snapshotValue["main_content"] as! String!)
let taskItem = Task(snapshot: item as! DataSnapshot)
newItems.append(taskItem!)
}
let merged = drafts + newItems
self.items = merged
completionHandler(true) //THIS LINE HAS ERR_BAD_ACCESS
})
}
I think the problem might be the two refreshData in viewDidLoad. But I don't know how to fix it. How could I add refreshData with handler as a selector?
This is not a thread problem. I solve it by wrapping the function call in another function because in this line
self.refreshControl!.addTarget(self, action: #selector(refreshData),for: .valueChanged)
I tried to use refreshData as a selector, but actually, selector doesn't have any completion handler by itself, so that caused the memory error whenever the user tried to renew by drag the scene down. So by wrapping the function call in another function
func refresh(){
refreshData{ [weak self] _ in
if let _ = self {
self?.refreshControl!.endRefreshing()
}
}
}
and use this function in the selector, it will deliver the right completion handler, and thus solve the problem.