我正在开发的应用程序存在一个不稳定的问题.我有一个在表视图中显示的轨道数组.在此表格视图中,用户可以向左滑动单个曲目,并显示包含三个项目的菜单.其中一个是删除操作.通过这个动作我遇到了问题.
该菜单在UITableViewDelegate方法中实现:
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?
Run Code Online (Sandbox Code Playgroud)
我使用以下语句检索所选行:
selectedTrack = indexPath.row
Run Code Online (Sandbox Code Playgroud)
然后我使用此代码段进行删除操作:
//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()
}
Run Code Online (Sandbox Code Playgroud)
该程序运行正常,但如果我一个接一个地删除两行,程序崩溃与注释:libc ++ abi.dylib:终止与NSException类型的未捕获异常.
如果我注释掉(或删除)该行:
self.trackOverviewTable.deleteRows(at: [indexPath], with: .fade)
Run Code Online (Sandbox Code Playgroud)
应用程序运行正常,但删除行的动画消失了.有趣的是,应用程序有时可以使用"deleteRows"功能正常运行,但通常不会.我看过几条评论,但我还没有找到正确的答案.
该表没有部分,因此数据源方法:
numberOfSections(in: UITableView)
Run Code Online (Sandbox Code Playgroud)
没有实施.谁能帮助我朝正确的方向发展?
根据Vadian的建议,我尝试将代码段更改为:
//Delete the selected track
let deleteAction = UITableViewRowAction(style: .default, title: deleteTitle) { (action, indexPath) -> Void in
self.trackOverviewTable.beginUpdates()
self.newTrack = self.savedTracks[self.selectedTrack]
let albumName = (self.newTrack?.trackName)! + String(describing: (self.newTrack?.trackDate)!)
self.savedTracks.remove(at: indexPath.row)
self.photoStore.deleteAlbumFromDeletedTrack(with: albumName)
self.saveTracksToDisk()
self.trackOverviewTable.deleteRows(at: [indexPath], with: .fade)
self.trackOverviewTable.endUpdates()
}
Run Code Online (Sandbox Code Playgroud)
但是,这仍然会导致应用程序崩溃.
应用程序崩溃的问题在于我使用了一种复杂而奇怪的方式来填充表视图,这使得应用程序期望获得不同数量的表行.现在运行的代码如下所示:
/** 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]
}
Run Code Online (Sandbox Code Playgroud)
vad*_*ian 13
有两个重要规则:
reloadData()在之后调用insert/move/deleteRows...,插入/移动/删除操作重新排序表并执行动画.insert/move/deleteRows...始终调用.| 归档时间: |
|
| 查看次数: |
3284 次 |
| 最近记录: |