refreshControl中的完成处理程序有EXC_BAD_ACCESS错误

问题描述:

我正在使用Firebase作为我的数据结构。我在我的UITableView的refreshControl中使用完成处理程序,以便在完成加载Firebase中的所有数据时停止刷新。refreshControl中的完成处理程序有EXC_BAD_ACCESS错误

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() 
    } 
} 

这是我refreshData方法

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 
    }) 
} 

我想问题可能是在viewDidLoad中两个refreshData。但我不知道如何解决它。我怎样才能添加refreshData与处理程序作为选择器?

+1

您是否知道何时开始与关闭主(UI)线程?任何时候你输入一个闭包,确保你在你需要的线程中 - 要操纵一个UI控件,你必须在UI线程中,并且我怀疑你没有费力去安排它。 – BaseZen

+0

@BaseZen对不起,我不太明白你的意思。我在completionHandler中注释掉了refresherControl并添加了一个print语句,但我仍然得到这个错误。 –

+1

如果您不知道线程上下文和UI操作的基本规则:它必须位于主UI线程上 - 这就是问题所在。看看iOS中这些主题的背景阅读是否有帮助。 – BaseZen

这不是一个线程问题。我因为在这一行

self.refreshControl!.addTarget(self, action: #selector(refreshData),for: .valueChanged) 

我试图用refreshData作为一个选择,但实际上,选择不具有本身的任何完成处理器通过包装在另一个函数的函数调用解决它,这样导致内存每当用户通过拖动场景来尝试更新时发生错误。因此,通过在另一个函数

func refresh(){ 
     refreshData{ [weak self] _ in 
      if let _ = self { 
       self?.refreshControl!.endRefreshing() 
      } 
     } 
    } 

包装函数调用,并在选择使用此功能,它将提供正确完成处理,从而解决问题。