Ячейка табличного представления с возможностью прокрутки в iOS 9

83

Я хочу, чтобы в моем списке таблиц было меню с возможностью прокрутки, как в iOS 8 (впервые появилось в iOS 7).

Снимок экрана кнопок действий ячейки табличного представления

Я нашел руководство Рэя Вендерлиха, в котором ясно, как это сделать, но оно было написано год и 4 месяца назад, а код написан на Objective-C.

Включили ли наконец iOS 8 или грядущую iOS 9 эту функцию в Apple SDK? Я знаю, что они сделали встроенную функцию «смахивание, чтобы открыть функцию удаления» много лет назад. Я не хочу тратить свое время на реализацию исправленного кода, имитирующего почтовую функцию iOS 8, если новая iOS от Apple собирается передать его мне в аккуратно упакованном пакете.

Дэйв Джи
источник
2
Кто-нибудь нашел решение для свайпа слева направо в Swift? Справа налево, кажется, хорошо задокументирована и обсуждается, но не слева направо.
Atticus

Ответы:

159

Попробуй это. (Обновлено для Swift 3.0) ( Документы разработчика )

override func tableView(_ tableView: UITableView, editActionsForRowAt: IndexPath) -> [UITableViewRowAction]? {
    let more = UITableViewRowAction(style: .normal, title: "More") { action, index in
        print("more button tapped")
    }
    more.backgroundColor = .lightGray

    let favorite = UITableViewRowAction(style: .normal, title: "Favorite") { action, index in
        print("favorite button tapped")
    }
    favorite.backgroundColor = .orange

    let share = UITableViewRowAction(style: .normal, title: "Share") { action, index in
        print("share button tapped")
    }
    share.backgroundColor = .blue

    return [share, favorite, more]
}

Также реализуйте это: (Вы можете сделать это условным, но здесь все доступно для редактирования)

override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return true
}

(Старая версия)

func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
        let more = UITableViewRowAction(style: .Normal, title: "More") { action, index in
            print("more button tapped")
        }
        more.backgroundColor = UIColor.lightGrayColor()

        let favorite = UITableViewRowAction(style: .Normal, title: "Favorite") { action, index in
            print("favorite button tapped")
        }
        favorite.backgroundColor = UIColor.orangeColor()

        let share = UITableViewRowAction(style: .Normal, title: "Share") { action, index in
            print("share button tapped")
        }
        share.backgroundColor = UIColor.blueColor()

        return [share, favorite, more]
    }

    func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // the cells you would like the actions to appear needs to be editable
        return true
    }
jose920405
источник
11
Это не отвечает на вопрос. Мы пытаемся найти выход влево, используя Swift. Это не так
Сому,
Благодаря! Очевидно, что это не касается свайпа влево-вправо, но я все равно решил отказаться от этой функции. Единственное, что неясно, - это как заставить таблицу автоматически обновляться после нажатия кнопки, которая может перемещать / удалять ячейку из таблицы?
Dave G
1
Не знаю, имеете ли вы в виду tableview.reloadRowsAtIndexPaths ([indexpath] withRowAnimation: UITableViewRowAnimation.Automatic)и для удаленияtableview.deleteRowsAtIndexPaths([indexpath], withRowAnimation: UITableViewRowAnimation.Automatic)
jose920405 07
2
Можно ли открыть действие редактирования, коснувшись ячейки, а не проведя по ней?
Heysem Katibi
1
Определение функции Swift 3override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?
Дэвид Корбин
28

Этот код работает для меня в swift4.

введите описание изображения здесь

Ответ на приведенный выше экран: -

 func tableView(_ tableView: UITableView,
                   trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
    {
        // Write action code for the trash
        let TrashAction = UIContextualAction(style: .normal, title:  "Trash", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
            print("Update action ...")
            success(true)
        })
        TrashAction.backgroundColor = .red

        // Write action code for the Flag
        let FlagAction = UIContextualAction(style: .normal, title:  "Flag", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
            print("Update action ...")
            success(true)
        })
        FlagAction.backgroundColor = .orange

        // Write action code for the More
        let MoreAction = UIContextualAction(style: .normal, title:  "More", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
            print("Update action ...")
            success(true)
        })
        MoreAction.backgroundColor = .gray


        return UISwipeActionsConfiguration(actions: [TrashAction,FlagAction,MoreAction])
    }

введите описание изображения здесь

Ответ на приведенный выше экран: -

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

        let closeAction = UIContextualAction(style: .normal, title:  "Mark as Read", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
            print("CloseAction ...")
            success(true)
        })
        closeAction.backgroundColor = .blue
        return UISwipeActionsConfiguration(actions: [closeAction])

    }

Аналогично напишите метод делегата tableview: -

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return arrPerson.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        let personName = arrPerson[indexPath.row]
        cell.textLabel?.text = personName.personName
        return cell

    }

И в viewDidLoad

override func viewDidLoad() {
    super.viewDidLoad()

    tblView.delegate = self
    tblView.dataSource = self

    let person1 = personData(personName: "Jonny", personAge: 30)
    let person2 = personData(personName: "Chandan", personAge: 20)
    let person3 = personData(personName: "Gopal", personAge: 28)

   arrPerson.append(person1)
   arrPerson.append(person2)
   arrPerson.append(person3)

}
Нирадж Пол
источник
7
На это ушло всего 3 года :) Спасибо за ответ
Рон Сребро
2
Это для iOS 11+
cdub
21

Вы можете использовать метод делегата UITableView, чтобы запросить эти действия. Реализуйте этот метод следующим образом:

- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
     UITableViewRowAction *modifyAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Modify" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
         // Respond to the action.
     }];
     modifyAction.backgroundColor = [UIColor blueColor];
     return @[modifyAction];
}

Конечно, вы можете вернуть несколько действий и настроить цвет текста и фона.

Реализация этого метода также необходима, чтобы сделать строку доступной для редактирования:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
}
БалестраПатрик
источник
Я могу получить всю эту функциональность с помощью всего лишь десятка строк кода? Или вы просто говорите вставить в эту функцию любой код, который я в конечном итоге использую. Ни один из приведенных кодов даже не выглядит так, как будто он изменяет ячейку. Кроме того, пытаясь решить эту проблему в Swift.
Дэйв Джи,
Да, вы можете получить все функции только с этим кодом. Это встроенная функция. Вау, это даже правильный ответ, и кто-то проголосовал против. Я удивлен.
BalestraPatrick
Имейте в виду, что это доступно с iOS8 + и позволяет проводить ТОЛЬКО влево, вам нужно сделать индивидуальную реализацию, чтобы делать смахивание вправо. Кроме того, быстрый и простой ответ
Иржи Тречак,
Спасибо, что поделились этим. Если я слишком некомпетентен, чтобы реализовать полное меню, я мог бы использовать это более простое решение. Я проголосовал за него, так как он актуален, но я не могу выбрать его в качестве ответа, поскольку он не отвечает на вопрос о том, как имитировать полное меню почты iOS8, плюс он написан на Objective-C.
Dave G
15

Я нашел эту библиотеку MGSwipeTableCell. После долгих поисков для реализации слайд-ячейки в табличном представлении с использованием swift я нашел эту и только одну строку кода для реализации и нашел ее чрезвычайно полезной.

     func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
  {
    let reuseIdentifier = "programmaticCell"
    var cell = self.table.dequeueReusableCellWithIdentifier(reuseIdentifier) as! MGSwipeTableCell!
    if cell == nil
    {
      cell = MGSwipeTableCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: reuseIdentifier)
    }

    cell.textLabel!.text = "Title"
    cell.detailTextLabel!.text = "Detail text"
    cell.delegate = self //optional

    //configure left buttons
    cell.leftButtons = [MGSwipeButton(title: "", icon: UIImage(named:"check.png"), backgroundColor: UIColor.greenColor())
      ,MGSwipeButton(title: "", icon: UIImage(named:"fav.png"), backgroundColor: UIColor.blueColor())]
    cell.leftSwipeSettings.transition = MGSwipeTransition.Rotate3D

    //configure right buttons
    cell.rightButtons = [MGSwipeButton(title: "Delete", backgroundColor: UIColor.redColor())
      ,MGSwipeButton(title: "More",backgroundColor: UIColor.lightGrayColor())]
    cell.rightSwipeSettings.transition = MGSwipeTransition.Rotate3D

    return cell
  }

Это единственная функция, которую вам нужно будет реализовать и обновить файл пода.

Сому
источник
11

Полное решение Swift 3:

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        tableView.tableFooterView = UIView(frame: CGRect.zero) //Hiding blank cells.
        tableView.separatorInset = UIEdgeInsets.zero
        tableView.dataSource = self
        tableView.delegate = self
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return 4
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath)

        return cell
    }

    //Enable cell editing methods.
    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {

        return true
    }

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

    }

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

        let more = UITableViewRowAction(style: .normal, title: "More") { action, index in
            //self.isEditing = false
            print("more button tapped")
        }
        more.backgroundColor = UIColor.lightGray

        let favorite = UITableViewRowAction(style: .normal, title: "Favorite") { action, index in
            //self.isEditing = false
            print("favorite button tapped")
        }
        favorite.backgroundColor = UIColor.orange

        let share = UITableViewRowAction(style: .normal, title: "Share") { action, index in
            //self.isEditing = false
            print("share button tapped")
        }
        share.backgroundColor = UIColor.blue

        return [share, favorite, more]
    }

}
мриаз0011
источник
2

AFAIK нет встроенного готового решения, и даже если бы оно было в iOS9, вы, вероятно, не сможете его использовать, поскольку в обозримом будущем вы не можете поддерживать только iOS9 в своем приложении.

Вместо этого я рекомендую вам заглянуть в эту библиотеку:

https://github.com/CEWendel/SWTableViewCell

Он очень легко настраивается, достаточно доработан и хорошо работает в любом быстром проекте, над которым я работал.

Надеюсь, поможет!

Иржи Тречак
источник
Благодарю. Новичок в разработке и никогда раньше не использовал GitHub. Я просто загрузил zip-файл и открыл проект в X-Code, а затем запустил проект, но получил сообщение «Build Failed». Должен ли я объединить код в свой проект, прежде чем я смогу увидеть, как он работает?
Дэйв Джи
Вам лучше установить Cocoapods в качестве диспетчера зависимостей; Это отраслевой стандарт, который избавит вас от головной боли. Подробнее о коконодах и о том, как их использовать, здесь cocoapods.org
Джири Тречак
Спасибо, Джири, после краткого прочтения о CocoaPods, похоже, мне придется продолжить чтение сегодня вечером, чтобы понять их. Мне захотелось, и вместо того, чтобы запускать проект на github, я просто начал смотреть на код. Это в объекте-C! Мое приложение написано на Swift, и это язык, с которым я знаком. Придется ли мне переводить решение github на Swift или, поскольку они могут работать бок о бок, смогу ли я скопировать код ViewController Objective-C в свой BasicCellViewController?
Dave G
С cocoapods вы запускаете библиотеки бок о бок, цель C и swift, если вы используете iOS8 +. Затем вы можете без проблем использовать код Obj-C в своем быстром проекте (но он будет скрыт в проекте «pods»), единственное, что вам нужно сделать, это импортировать библиотеку objective-c в свой «Bridging Header» developer.apple.com. / library / prerelease / ios / documentation / Swift /…
Иржи Тречак,
Просто прочтите о CocoaPods ( raywenderlich.com/97014/use-cocoapods-with-swift ), я думаю, это будет слишком много для моего мозга, чтобы его пережевывать. Я понимаю эту концепцию, но реализую ее в терминале, использую рабочие области, заставляя мое приложение работать на коде, не объединенном с моим другим кодом ... плюс настраивая фактическую функцию меню, чтобы она выглядела / действовала так, как я хочу ... взорваться. Собираюсь изучить, как я бы просто вставил этот obj-c и сказал своему приложению, что я использую оба языка. Я не делал этого раньше, но кажется проще,
Дэйв Джи,
1

Это проще, чем вы думаете. Вот пример класса Swift с реализованным UITableView и возможностью прокрутки UITableViewCell.

import UIKit

class ViewController: UIViewController {

    // MARK: Properties

    let strings = ["firstString", "secondString", "thirdString"]

    // MARK: Outlets

    @IBOutlet weak var tableView: UITableView!

    // MARK: Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self
    }
}

extension ViewController: UITableViewDataSource, UITableViewDelegate {

    // MARK: UITableViewDataSource

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return objects.count
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: indexPath)
        let currentString = strings[indexPath.row]
        cell.textLabel?.text = currentString
        return cell
    }

    // MARK: UITableViewDelegate

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
    }

    func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let leftAction = UIContextualAction(style: .normal, title:  "Red", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
            print("leftAction tapped")
            success(true)
        })

        leftAction.image = UIImage(named: "")
        leftAction.backgroundColor = UIColor.red

        return UISwipeActionsConfiguration(actions: [leftAction])
    }

    func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let rightAction = UIContextualAction(style: .normal, title:  "Green", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
            print("rightAction tapped")
            success(true)
        })

        rightAction.image = UIImage(named: "")
        rightAction.backgroundColor = UIColor.green

        return UISwipeActionsConfiguration(actions: [rightAction])
    }

}
iAleksandr
источник