1

I want to add swipe actions to my list for show some actions.

All I want is add some actions for swipe left gesture on list row like mail application of ios.

I found this @michał-ziobro Swipe Actions Modifier solution but it is not working :/

Some parts of that code gave me errors and I fixed them with some extensions, I thought maybe that is the reason why it is not working.

struct TableViewConfigurator: UIViewControllerRepresentable {

    var configure: (UITableView) -> Void = { _ in }

    func makeUIViewController(context: UIViewControllerRepresentableContext<TableViewConfigurator>) -> UIViewController {

        UIViewController()
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<TableViewConfigurator>) {

        let tableViews = UIApplication.nonModalTopViewController()?.navigationController?.topViewController?.view.allSubViewsOf(type: UITableView.self) ?? [UITableView]()

        for tableView in tableViews {
            self.configure(tableView)
        }
    }
}

struct ListSwipeActions: ViewModifier {

    @ObservedObject var coordinator = Coordinator()

    func body(content: Content) -> some View {

        return content
            .background(TableViewConfigurator(configure: { tableView in
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                    tableView.delegate = self.coordinator
                }
            }))
    }

    class Coordinator: NSObject, ObservableObject, UITableViewDelegate {

        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            print("Scrolling ....!!!")
        }

        func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
            return .delete
        }

        func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {

            let isArchived = false
            let title = isArchived ? "Unarchive" : "Archive"

            let archiveAction = UIContextualAction(style: .normal, title: title, handler: {
                (action, view, completionHandler) in

                // update data source
                completionHandler(true)
            })
            archiveAction.title = title
            archiveAction.image = UIImage(systemName: "archivebox")!
            archiveAction.backgroundColor = .systemYellow

            let configuration = UISwipeActionsConfiguration(actions: [archiveAction])

            return configuration
        }
    }
}

extension List {

    func swipeActions() -> some View {
        return self.modifier(ListSwipeActions())
    }
}

and here is my list view :

struct NotificationsTab: View {

    @ObservedObject var viewModel = NotificationsVM()

    func delete(at offsets: IndexSet) {
        viewModel.notifications.remove(atOffsets: offsets)
    }

    var body: some View {
        NavigationView {
            Group{
                if viewModel.notifications.count > 0 {
                    List{
                        ForEach(self.viewModel.notifications, id: \.id){ notification in
                            HStack(spacing: 15){
                                WebImage(url: URL(string: notification.sender!.avatar!.userAvatarPathSmall()))
                                    .resizable()
                                    .indicator(.activity)
                                    .aspectRatio(contentMode: .fill)
                                    .animation(.easeInOut(duration: 0.5))
                                    .transition(.fade)
                                    .frame(width: 48, height: 48)
                                    .cornerRadius(24)
                                Text(notification.sender!.name!).fontWeight(.bold) + Text(notification.message!)
                            }.padding(.vertical)
                        }.onDelete(perform: delete)
                    }.swipeActions()
                }else{
                    LoadingView()
                }
            }
            .navigationBarTitle("Notifications")
        }.onAppear(){
            self.viewModel.getNotifications()
        }
    }
}

struct NotificationsTab_Previews: PreviewProvider {
    static var previews: some View {
        NotificationsTab()
    }
}
  • Not sure if my thought will help, but consider things from a user perspective. Swipe left, particularly in a table view, usually brings up the "delete row" action. Now *maybe* that's what you are trying to do - in which case you simply need to simply use `setEditing` to `true` and then tap into the table view's `editingStyle:1` delegate method properly. Again, if your intent is to "swipe left" on a table view and then do something a user of any other app isn't expecting - I'd strongly advise not doing it. –  May 02 '20 at 23:55
  • Apologies for not noticing the [swiftui] tag. To be honest, it's still (I think) valid. Sure, you can *use* the `onDelete` modifier, but it's even worse than `UIKit` with it's flexibility compared to SwiftUI. But if you *really* wish to upset user expectations by changing what iOS does with swiping left on a list or table view, maybe you can drop into a representable - at least that allows you more control than SwiftUI currently gives you. –  May 03 '20 at 00:07
  • thanks for the answer mate. I think user expectations and experience are suitable for swipe left gesture(also what I want to do) because they have that UX habit from mail application. Apple does not want that developers use these actions anymore but they're still using for core applications lol. @dfd – Halil İbrahim YÜCE May 03 '20 at 00:55
  • this is OS limitation, so there is no work around for this unless you are using uitableview inside the swiftUI, my recommendation is to use actionsheet – steven lee May 03 '20 at 15:46

0 Answers0