2017-07-20 25 views
1

我正在使用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

回答

1

這不是一個線程問題。我因爲在這一行

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

我試圖用refreshData作爲一個選擇,但實際上,選擇不具有本身的任何完成處理器通過包裝在另一個函數的函數調用解決它,這樣導致內存每當用戶通過拖動場景來嘗試更新時發生錯誤。因此,通過在另一個函數

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

包裝函數調用,並在選擇使用此功能,它將提供正確完成處理,從而解決問題。