首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >UITableView允许使用滑动手势删除某些类型的请求

UITableView允许使用滑动手势删除某些类型的请求
EN

Code Review用户
提问于 2019-08-03 06:44:34
回答 1查看 147关注 0票数 3

我有一个表视图,它显示了一个名为请求的对象列表。它有三个部分。即接受、接收和发送。每个段的对象为3个数组。

我希望只为已接受和发送的段启用删除行(依次为对象)。

这是我目前的实现。

代码语言:javascript
复制
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {

    var deleteAction: UIContextualAction?

    switch currentShowingStatus {
    case .accepted:
        deleteAction = UIContextualAction(style: .destructive, title: "Delete") { action, view, completionHandler in
            let request = self.acceptedRequests[indexPath.row]
            completionHandler(true)
        }
    case .sent:
        deleteAction = UIContextualAction(style: .destructive, title: "Delete") { action, view, completionHandler in
            let request = self.sentRequests[indexPath.row]
            completionHandler(true)
        }
    default:
        break
    }


    if let deleteAction = deleteAction {
        let configuration = UISwipeActionsConfiguration(actions: [deleteAction])
        configuration.performsFirstActionWithFullSwipe = false
        return configuration
    } else {
        return UISwipeActionsConfiguration(actions: [])
    }
}

正如您所看到的,有相当多的重复代码。而且我无法提取出UIContextualAction声明部分,因为它是完成处理程序。选择要删除的对象就发生在那里。

我也不能将UISwipeActionsConfiguration定义为局部变量,并且由于必须使用UIContextualAction实例初始化类,所以减少了它的重复。

注意:为了不显示单元格中的滑动操作,您必须将一个空操作数组传递给UISwipeActionsConfiguration。返回nil并不能做到这一点。

所以所有这些都产生了一段丑陋的代码。我想知道是否有更好的方法来重构这个。

替代方法

我没有先检查段,然后再添加多个删除操作,而是将段部件检查放在一个完成处理程序中,如下所示。

代码语言:javascript
复制
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    var actions = [UIContextualAction]()

    let deleteAction = UIContextualAction(style: .destructive, title: "Delete") { action, view, completionHandler in
        switch self.currentShowingStatus {
        case .accepted:
            let request = self.acceptedRequests[indexPath.row]
            self.deleteClientRequest(request)
        case .sent:
            let request = self.sentRequests[indexPath.row]
            self.deleteClientRequest(request)
        default:
            break
        }
        completionHandler(true)
    }

    switch currentShowingStatus {
    case .accepted, .sent:
        actions.append(deleteAction)
    case .received:
        actions.removeAll()
    }

    let configuration = UISwipeActionsConfiguration(actions: actions)
    configuration.performsFirstActionWithFullSwipe = false
    return configuration
}

缺点是,我仍然必须再次检查段,以显示只接受和发送段的滑动动作。

EN

回答 1

Code Review用户

回答已采纳

发布于 2019-08-04 17:11:34

在第一个实现中,如果在开关语句的所有情况下对deleteAction进行初始化,则可以使它成为常量:

代码语言:javascript
复制
    let deleteAction: UIContextualAction?
    switch currentShowingStatus {
    case .accepted:
        deleteAction = UIContextualAction(...)
    case .sent:
        deleteAction = UIContextualAction(...)
    case .received:
        deleteAction = nil
    }

这就清楚地表明,变量在使用之前精确地初始化了一次。我还会用显式的default:代替case received:。这对读者来说是显而易见的,在这种情况下,不配置swipe操作(不查找枚举定义),如果添加了更多的情况,则强制您更新代码。

可以通过初始化操作数组来避免UISwipeActionsConfiguration的双重定义:

代码语言:javascript
复制
    let actions: [UIContextualAction]
    switch currentShowingStatus {
    case .accepted:
        actions = [UIContextualAction(...)]
    case .sent:
        actions = [UIContextualAction(...)]
    default:
        actions = []
    }

    let configuration = UISwipeActionsConfiguration(actions: actions)
    configuration.performsFirstActionWithFullSwipe = false
    return configuration

不过,它仍然是UIContextualAction的代码复制。

在您的替代方法中,您可以从actions数组中追加或删除元素。但是这个数组最初是空的。与上面类似,您可以将其简化为

代码语言:javascript
复制
    let deleteAction = ...

    let actions: [UIContextualAction]
    switch currentShowingStatus {
    case .accepted, .sent:
        actions = [deleteAction]
    case .received:
        actions = []
    }

但是- as,您注意到,- you不得不再次评估闭包中的self.currentShowingStatus。由于另一个原因,我会避免这样做:您所依赖的事实是,在执行闭包时,状态并没有改变。

如果首先初始化请求,则可以避免UIContextualAction的代码重复:

代码语言:javascript
复制
   let request: Request?
   switch currentShowingStatus {
   case .accepted:
       request = self.acceptedRequests[indexPath.row]
   case .sent:
       request = self.sentRequests[indexPath.row]
   case .received:
       request = nil
   }

   if let request = request {
       let deleteAction = UIContextualAction(style: .destructive, title: "Delete") {
           _, _, completionHandler in
           self.deleteClientRequest(request)
           completionHandler(true)
       }
       let configuration = UISwipeActionsConfiguration(actions: [deleteAction])
       configuration.performsFirstActionWithFullSwipe = false
       return configuration
   } else {
       return UISwipeActionsConfiguration(actions: [])
   }

还请注意,未使用的闭包参数可以被通配符参数_替换。

我可能会这样做,但你当然可以把这些技巧结合起来:

代码语言:javascript
复制
    let request: Request?
    switch currentShowingStatus {
    case .accepted:
        request = self.acceptedRequests[indexPath.row]
    case .sent:
        request = self.sentRequests[indexPath.row]
    case .received:
        request = nil
    }

    let actions: [UIContextualAction]
    if let request = request {
        actions = [UIContextualAction(style: .destructive, title: "Delete") {
            _, _, completionHandler in
            self.deleteClientRequest(request)
            completionHandler(true)
            }]
    } else {
        actions = []
    }

    let configuration = UISwipeActionsConfiguration(actions: actions)
    configuration.performsFirstActionWithFullSwipe = false
    return configuration
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/225447

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档