2017-01-07 32 views
2

我有一個不穩定的問題,我正在開發一個應用程序。我有一個顯示在表格視圖中的曲目數組。在此表格視圖中,用戶可以向左滑動單個曲目,並出現包含三個項目的菜單。其中之一是刪除操作。這是這個行動,我有一個問題。與tableView.deleteRows崩潰(在:),與:)

該菜單中的UITableViewDelegate方法來實現:

override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? 

檢索到選定的行用以下語句:

selectedTrack = indexPath.row 

然後我就與這個片段刪除操作:

//Delete the selected track 
let deleteAction = UITableViewRowAction(style: .default, title: deleteTitle) { (action, indexPath) -> Void in 

    if self.savedTracks.count > 0 { 
     self.newTrack = self.savedTracks[self.selectedTrack] 
     let albumName = (self.newTrack?.trackName)! + String(describing: (self.newTrack?.trackDate)!) 
     self.savedTracks.remove(at: self.selectedTrack) 
     self.trackOverviewTable.deleteRows(at: [indexPath], with: .fade) 
     self.photoStore.deleteAlbumFromDeletedTrack(with: albumName) 
     self.trackOverviewTable.reloadData() 
     self.saveTracksToDisk() 
    } else { 
     self.trackOverviewTable.reloadData() 
    } 

該程序運行正常,但如果我刪除兩行接一行,th e程序崩潰時發表評論:libC++ abi.dylib:以NSException類型的未捕獲異常終止。

如果我註釋掉(或刪除)行:

self.trackOverviewTable.deleteRows(at: [indexPath], with: .fade) 

該應用程序運行正常,但刪除行的動畫了。有趣的是,應用程序有時可以使用「deleteRows」函數正常運行,但通常不會。我看了幾個評論,但我還沒有找到正確的答案。

表沒有的部分,所以該數據源的方法:

numberOfSections(in: UITableView) 

未實現。 任何人都可以幫助我在正確的方向嗎?

基於Vadian的意見,我試圖將代碼片斷更改爲:

​​

然而,這仍使應用程序崩潰。

應用程序崩潰的問題是我使用了一種複雜而奇怪的方式填充表視圖,這使得應用程序期望不同數量的錶行,然後確實存在。現在工作的代碼如下所示:

/** This method provides the actions when the user swipes a row left. The method first checks what sort of track it is. If the track is an emptyTrack or 
instructionTrack, there will be no action that can be chosen. When the track is a regular recorded track the method will provide the user with the option 
to post the selected track or delete the track. 
*/ 
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? { 

    let faultTitle = NSLocalizedString("No tracks.", comment: "The message in the selection when there are no tracks.") 
    let postTitle = NSLocalizedString("Post track.", comment: "The message in the selection for posting the track on social media.") 
    let deleteTitle = NSLocalizedString("Delete.", comment: "The message in the selection for deleting the track.") 

    selectedTrack = indexPath.row 
    let selectedTrackName = self.savedTracks[selectedTrack].trackName 

    //When the user swiped the empty or instruction track, only provide the fault action. 
    guard (selectedTrackName != self.emptyString) && (selectedTrackName != self.instructionString) else { 
     //The user selected the empty or instruction track, the action cannot be executed. 
     let faultAction = UITableViewRowAction(style: .normal, title: faultTitle, handler: { (action, indexPath) -> Void in 

      self.trackOverviewTable.reloadData() //Simply reload the table view after the action button is hit. 
     }) 

     self.trackOverviewTable.cellForRow(at: indexPath)?.isSelected = false 
     return [faultAction] 
    } 

    //The post action first checks whether the user had bought the fll version. 
    //If the full version is bought the action moves to the posting menu. 
    let postAction = UITableViewRowAction(style: .normal, title: postTitle) { (action, indexPath) -> Void in 

     //The message when the full version has not been bought 
     let alertTitle = NSLocalizedString("Upgrade @Tracker", comment: "The user doesn't have the full capabilities.") 
     let alertMessage = NSLocalizedString("Do you want to upgrade @Tracker to unlock all functionalities?", comment: "Ask the user to buy the functionalities.") 

     //The new track will now be set to be the selected track so it can be transfered to 
     //the posting view controller 
     self.newTrack = self.savedTracks[self.selectedTrack] 

     if FULL_FUNCTIONALITY == true { 
      self.performSegue(withIdentifier: "postTrack", sender: self) 
     } else { 
      //Allow the user to post the track if the full functionality is bought 
      self.alertMessage(title: alertTitle, message: alertMessage, action: "Buy") 
     } 
    } 

    //Delete the selected track 
    let deleteAction = UITableViewRowAction(style: .default, title: deleteTitle) { (action, indexPath) -> Void in 

     //First set the warning message when the user wants to delete the track. 
     let title = NSLocalizedString("Warning", comment: "Ask alert the user that he is going to delete the track.") 
     let message = NSLocalizedString("Are you sure you want to delete the track?", comment: "Ask the user if he's sure.") 
     let alertYes = NSLocalizedString("Yes", comment: "Ja") 
     let alertNo = NSLocalizedString("No", comment: "Nee") 
     let alertMessage = UIAlertController.init(title: title, message: message, preferredStyle: .alert) 

     let okAction = UIAlertAction(title: alertYes, style: .default, handler: { (action) in 
      self.deleteTrackFromTable(at: indexPath) 

      var indexPathSelected = indexPath 
      indexPathSelected.row = 0 
      self.trackOverviewTable.scrollToRow(at: indexPathSelected, at: .none, animated: true) 
      self.presentingViewController?.dismiss(animated: true, completion: nil) 
     }) 
     alertMessage.addAction(okAction) 

     let notOkAction = UIAlertAction(title: alertNo, style: .default, handler: { (action) in 
      self.trackOverviewTable.reloadData() 
      self.presentingViewController?.dismiss(animated: true, completion: nil) 
     }) 
     alertMessage.addAction(notOkAction) 

     self.present(alertMessage, animated: true, completion: nil) 
    } 

    postAction.backgroundColor = MENU_COLOR_1 

    self.trackOverviewTable.cellForRow(at: indexPath)?.isSelected = false 
    return [deleteAction, postAction, analysisAction] 
} 
+0

我在insertRows和deleteRows時處於相同的情況。 – BollMose

+0

嗨BollMose,自從我實施了Vadian的建議以後,我再也沒有問題了。我稍後會發布代碼。 – MacUserT

+0

有趣。我的應用程序在惰性行然後deleteRows時崩潰,但它只運行deleteRows。 – BollMose

回答

4

有兩個重要的規則:

  • ,一定不要調用reloadData()insert/move/deleteRows...之後,插入/移動/刪除操作重新排序表,並做動畫。
  • 致電insert/move/deleteRows...總是更改數據源數組。
+1

嗨Vadian,感謝您的快速回答,但刪除代碼中的reloadData()仍然會導致應用程序崩潰。 – MacUserT

+0

'selectedTrack'的值是否等於索引路徑的行?它應該是。您應該更喜歡使用索引路徑 – vadian

+0

selectedTrack由selectedTrack = indexPath.row獲取。我在問題描述中提到了這一點。與indexPath.row應用程序崩潰仍然。 – MacUserT