Проведіть пальцем до пункту Видалити та кнопку "Додатково" (як у програмі Mail на iOS 7)

Як створити кнопку "більше", коли користувач провів клітинку у вигляді таблиці (наприклад, поштова програма в iOS 7)

Я шукав цю інформацію і тут, і на форумі Cocoa Touch, але, здається, не знаходжу відповіді, і я сподіваюся, що хтось розумніший за мене може дати мені рішення.

Мені б хотілося, щоб, коли користувач пропустив клітинку для перегляду таблиці, відображається більше однієї кнопки редагування (за замовчуванням це кнопка видалення). У програмі Mail для iOS 7 можна проведіть пальцем, щоб видалити, але з'являється кнопка "БІЛЬШЕ".

enter image description here

233
Перевірте це: teehanlax.com/blog/reproducing- the-ios-7-mail-apps-interface та моя реалізація за допомогою автоматичного розкладу JASwipeCellExperiment
додано Автор Alexis, джерело
додано Автор null, джерело
У iOS 11 це можливо без коду третьої сторони. прокрутіть вниз для моєї відповіді
додано Автор Lewis42, джерело
@GuyKahlonMatrix спасибі за рішення він працює як шарм. Це питання є результатом № 1 на багатьох пошуках у Google, і люди змушені обмінюватися своїми знаннями, використовуючи коментарі, тому що хтось вирішив, що це більш корисно закрити питання і проповідувати демократію. Це місце явно потребує кращих модифікацій.
додано Автор Şafak Gezer, джерело
Якщо ви можете націлити iOS 8, моя відповідь нижче буде те, що ви хочете.
додано Автор Johnny, джерело
@ ŞafakGezer Як встановити ширину кнопок rowEditActionButtons
додано Автор ArgaPK, джерело
@MonishBansal Bansal Схоже, хтось у цьому потоці ( devforums.apple.com/message/860459#860459 в форумі розробників Apple) пішли вперед і побудували власну реалізацію. На GitHub можна знайти проект, який робить те, що ви хочете: ролика
додано Автор Guy Kahlon, джерело
Щоб додати кнопку "Видалити", я реалізую наступні дві функції. - (BOOL) tableView: (UITableView *) tableView canEditRowAtIndexPath: (NSIndexPath *) indexPath; - (void) tableView: (UITableView *) tableView commitEditingStyle: (UITableViewCellEditingStyle) редагуванняStyle forRowAtIndexPath: (NSIndexPath *) indexPath; І я хочу додати кнопку "More" поруч з нею.
додано Автор Guy Kahlon, джерело
Я думаю, що цей підручник може допомогти: noreferrer "> raywenderlich.com/62435/…
додано Автор César Abreu, джерело

20 Відповіді

Як реалізувати

Схоже, що iOS 8 відкриває цей API. Підказки щодо такої функціональності є в Beta 2.

Щоб отримати щось робоче, виконайте наступні два способи, щоб отримати бажаний ефект від вашого UITableView.

- tableView:editActionsForRowAtIndexPath:
- tableView:commitEditingStyle:forRowAtIndexPath:


відомі проблеми

У документації вказано tableView: commitEditingStyle: forRowAtIndexPath:

"Не викликається для дій редагування за допомогою UITableViewRowAction - замість цього буде викликаний обробник дії."

Проте без неї не можна працювати. Навіть якщо заглушка методу порожня, вона поки що потребує його. Це найбільш очевидно помилка в бета-версії 2.


Джерела

https://twitter.com/marksands/status/481642991745265664 https://gist.github.com/marksands/76558707f583dbb8f870

Original Answer: https://stackoverflow.com/a/24540538/870028


Оновити:

Sample code with this working (In Swift): http://dropbox.com/s/0fvxosft2mq2v5m/DeleteRowExampleSwift.zip

Зразок коду містить цей простий у методі MasterViewController.swift метод, і саме цим методом ви отримуєте поведінку, показану на скріншоті OP:

override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {

    var moreRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "More", handler:{action, indexpath in
        println("MORE•ACTION");
    });
    moreRowAction.backgroundColor = UIColor(red: 0.298, green: 0.851, blue: 0.3922, alpha: 1.0);

    var deleteRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Delete", handler:{action, indexpath in
        println("DELETE•ACTION");
    });

    return [deleteRowAction, moreRowAction];
}
122
додано
Дуже дякую. :) Ваша відповідь мені дуже допомогла
додано Автор Somu, джерело
Схоже, що обробники отримують виклик, але клітина не "закрита" пізніше. Я пропускаю очевидний спосіб зробити це? Виклик endEditing: у табличному перегляді не робить нічого.
додано Автор Ben Lachman, джерело
Щоб відповісти на власний коментар. Ви називаєте tableView.editing = false ( NO в objc), а комірка "закриється".
додано Автор Ben Lachman, джерело
Я не працюю в об'єкті c .. Той же код я написав. будь ласка, запропонуйте кілька натяків.
додано Автор Solid Soft, джерело
це зробили. Але не впевнений, чому це сталося. Він працює зі мною в UITableViewController не в UITableView, який знаходиться всередині UIViewController.
додано Автор Solid Soft, джерело
@Johnny Так, я вже згадував. Зараз працюю я успадкував з UITableViewController і працював. Дякую за твою підтримку.
додано Автор Solid Soft, джерело
Як додати значок замість тексту? Я не хочу видаляти текст, просто хочу значок видалення. Як домогтися цього в стрімкому? Будь ласка, допоможіть
додано Автор Alok Nair, джерело
Якби я тільки бачив цю відповідь, перш ніж зануритися в складну реалізацію перед iOS 8!
додано Автор fujianjin6471, джерело
Це може здатися занадто простим, але я просто хочу переконатися, що основи покриті. Чи відповідає ваш UIViewController протоколу UITableViewDelegate? Якщо це так, чи призначаєте ви це self.tableView.delegate = self; (або ще що-небудь)?
додано Автор Johnny, джерело
@Siegfoult Ви пробували реалізувати (навіть якщо залишили порожній) tableView: commitEditingStyle: forRowAtIndexPath :?
додано Автор Johnny, джерело
@SolidSoft У вас є прикладний проект, на який я міг би подивитися? Я міг би краще допомогти.
додано Автор Johnny, джерело
@SolidSoft На жаль, я забув позначити вас.
додано Автор Johnny, джерело
Здається, це правильно, але в Xcode 6 GM жест жезлом не працює. Доступ до editActions можна отримати, помістивши перегляд таблиці в режим редагування. Хто-небудь інший вважає, що серветка не працює?
додано Автор Siegfoult, джерело
Хороша інформація
додано Автор Gabox, джерело

Я створив нову бібліотеку для реалізації swippable кнопок, які підтримують різні переходи і розширювані кнопки, такі як iOS 8 поштова програма.

https://github.com/MortimerGoro/MGSwipeTableCell

Ця бібліотека сумісна з усіма різними способами створення UITableViewCell та її тестуванням на iOS 5, iOS 6, iOS 7 і iOS 8.

Ось зразок деяких переходів:

Перехід кордону:

Border transition

Перехід кліпу

Перехід кліпу

3D-перехід:

enter image description here

117
додано
Це дивовижна бібліотека, і те, що дуже добре, це те, що вона все ще підтримує.
додано Автор confile, джерело
Чудова робота! Було б дивно мати зворотний виклик, щоб налаштувати анімацію.
додано Автор Pacu, джерело
@MortimerGoro Хороша людина. Виглядає добре. Я намагаюся реалізувати подібний ефект в одному з моїх проектів Android. Скажіть, будь ласка, як я можу досягти цього в Android?
додано Автор Nitesh Khatri, джерело
Існують також деякі проблеми з VoiceOver з цією установкою. Інакше це дивовижна робота!
додано Автор Kane Cheshire, джерело
Wow, серйозно вражаюча робота!
додано Автор Ben Williams, джерело
Це дуже поганий бутон .. Просто великий, дякую!
додано Автор 0yeoj, джерело
на iOS 8 + iPad, я просто не отримую удар.
додано Автор ScorpionKing2k5, джерело
@ MortimerGoro, я спробував з "MGSwipeTableCel" L рамки, але проблема в тому, коли я перезавантажити мою таблицю, то swipe кнопка прихована. Будь-яка робота навколо цієї проблеми.
додано Автор Ganesh Guturi, джерело
Дивовижний!!! Просто проходите повз, але не можете допомогти голосувати за фантастичні анімації !!!
додано Автор Z.pyyyy, джерело
Чудова робота! Це допомагає мені багато і врятує багато часу.
додано Автор Moin Uddin, джерело

Відповідь Джонні є правильною. Я просто додаю це нижче, щоб зробити його більш зрозумілим для початківців (і для тих з нас, хто відмовляється вивчати синтаксис Swift :)

Переконайтеся, що ви оголосили uitableviewdelegate та використовуйте такі способи:

 -(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
 UITableViewRowAction *button = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 1" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
    {
        NSLog(@"Action to perform with Button 1");
    }];
    button.backgroundColor = [UIColor greenColor]; //arbitrary color
    UITableViewRowAction *button2 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 2" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
                                    {
                                        NSLog(@"Action to perform with Button2!");
                                    }];
    button2.backgroundColor = [UIColor blueColor]; //arbitrary color

    return @[button, button2]; //array with all the buttons you want. 1,2,3, etc...
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
// you need to implement this method too or nothing will work:

}
 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return YES; //tableview must be editable or nothing will work...
    }
68
додано
Важливо згадати canEditRowAtIndexPath
додано Автор Heckscheibe, джерело
Якщо я перезавантажу таблицю після переміщення клітинки, то ці клавіші промахування видно або приховано?
додано Автор Ganesh Guturi, джерело

Це (досить смішно) приватний API.

Наступні два способи є приватними та надіслані до делегатів UITableView:

-(NSString *)tableView:(UITableView *)tableView titleForSwipeAccessoryButtonForRowAtIndexPath:(NSIndexPath *)indexPath;
-(void)tableView:(UITableView *)tableView swipeAccessoryButtonPushedForRowAtIndexPath:(NSIndexPath *)indexPath;

Вони досить зрозумілі.

25
додано
Apple відкрила цю функцію з iOS 8. Дивіться відповідь Johnny нижче.
додано Автор Siegfoult, джерело

Щоб покращити відповідь Джонні, тепер це можна зробити за допомогою загальнодоступного API:

func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {

    let moreRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "More", handler:{action, indexpath in
        print("MORE•ACTION");
    });
    moreRowAction.backgroundColor = UIColor(red: 0.298, green: 0.851, blue: 0.3922, alpha: 1.0);

    let deleteRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "Delete", handler:{action, indexpath in
        print("DELETE•ACTION");
    });

    return [deleteRowAction, moreRowAction];
}
23
додано
Не могли б ви оновити код до Swift 3? Дякую
додано Автор bibscy, джерело
спасибі працює нормально.
додано Автор Shahbaz Akram, джерело

Я сподіваюся, що ви не можете чекати, поки яблуко дасть вам те, що вам потрібно? Так ось мій варіант.

Створіть власну клітинку. Майте два uiviews в ньому

1. upper
2. lower

У нижньому вигляді додайте потрібні вам кнопки. Справлятися з його діями просто     як і будь-які інші IBActions. Ви можете визначити час анімації, стиль і що завгодно.

тепер додайте uiswipegesture до верхнього виду і відкрийте нижній вигляд у жесті. Я зробив це раніше і його найпростіший варіант, наскільки я стурбований.

Сподіваюся, що це допоможе.

17
додано

Це неможливо за допомогою стандартного SDK. Однак існують різні рішення третіх сторін, які більш-менш імітують поведінку в Mail.app. Деякі з них (наприклад, MCSwipeTableViewCell , DAContextMenuTableViewController , RMSwipeTableViewCell ) визначає, чи використовує розпізнавач жестів, деякі з них (наприклад, SWTableViewCell ) розміщують другий UISScrollView нижче стандартного UITableViewCellScrollView ( приватний subview UITableViewCell ), і деякі з них змінюють поведінку UITableViewCellScrollView .

Мені найбільше подобається останній підхід, оскільки сенсорне керування виглядає найбільш природним. Зокрема, MSCMoreOptionTableViewCell добре. Ваш вибір може змінюватись залежно від ваших конкретних потреб (чи потрібна панорама зліва направо, чи потрібна сумісність з iOS 6 тощо). Також пам'ятайте, що більшість цих підходів пов'язані з тягарем: вони можуть легко зламати майбутню версію iOS, якщо Apple вносить зміни до ієрархії subview Ucode-UITableViewCell.

7
додано

Код версії 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]
    }

}
7
додано

Вам потрібно підклас UITableViewCell і метод підкласу willTransitionToState: (UITableViewCellStateMask) стан , який викликається, коли користувач переміщується по комірці. Прапори state дадуть вам знати, чи відображається кнопка Delete, і показувати/приховувати кнопку More.

Unfortunately this method gives you neither the width of the Delete button nor the animation time. So you need to observer & hard-code your More button's frame and animation time into your code (I personally think Apple needs to do something about this).

6
додано
"Я особисто думаю, що Apple повинна щось зробити з цим". Я згоден. Ви вже написали їм повідомлення про помилку або запит на функцію?
додано Автор Tafkadasoh, джерело

Для швидкого програмування

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
  if editingStyle == UITableViewCellEditingStyle.Delete {
    deleteModelAt(indexPath.row)
    self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
  }
  else if editingStyle == UITableViewCellEditingStyle.Insert {
    println("insert editing action")
  }
}

func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {
  var archiveAction = UITableViewRowAction(style: .Default, title: "Archive",handler: { (action: UITableViewRowAction!, indexPath: NSIndexPath!) in
       //maybe show an action sheet with more options
        self.tableView.setEditing(false, animated: false)
      }
  )
  archiveAction.backgroundColor = UIColor.lightGrayColor()

  var deleteAction = UITableViewRowAction(style: .Normal, title: "Delete",
      handler: { (action: UITableViewRowAction!, indexPath: NSIndexPath!) in
        self.deleteModelAt(indexPath.row)
        self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic);
      }
  );
  deleteAction.backgroundColor = UIColor.redColor()

  return [deleteAction, archiveAction]
}

func deleteModelAt(index: Int) {
  //... delete logic for model
}
4
додано
@bibscy Ви можете запропонувати редагування. Не використовували swift протягом довгого часу, так що не впевнений, що правильний синтаксис
додано Автор Michael Yagudaev, джерело
Не могли б ви оновити код для Swift 3?
додано Автор bibscy, джерело

З iOS 11 це загальнодоступне в UITableViewDelegate . Ось приклад коду:

- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath {
    UIContextualAction *delete = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive
                                                                         title:@"DELETE"
                                                                       handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
                                                                           NSLog(@"index path of delete: %@", indexPath);
                                                                           completionHandler(YES);
                                                                       }];

    UIContextualAction *rename = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal
                                                                         title:@"RENAME"
                                                                       handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
                                                                           NSLog(@"index path of rename: %@", indexPath);
                                                                           completionHandler(YES);
                                                                       }];

    UISwipeActionsConfiguration *swipeActionConfig = [UISwipeActionsConfiguration configurationWithActions:@[rename, delete]];
    swipeActionConfig.performsFirstActionWithFullSwipe = NO;

    return swipeActionConfig;
}

Також доступні:

- (UISwipeActionsConfiguration *) tableView: (UITableView *) tableView leadingSwipeActionsConfigurationForRowAtIndexPath: (NSIndexPath *) indexPath;

Docs: https://developer.apple.com/documentation/uikit/uitableviewdelegate/2902367-tableview?language=objc

3
додано

Я хотів додати ту ж функціональність моєму додатку, а після проходження багатьох різних навчальних посібників ( raywenderlich , який є найкращим рішенням DIY), я дізнався, що у Apple є свій клас UITableViewRowAction , який дуже зручно.

Необхідно змінити метод кодової точки Tableview на це:

override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]?  {
   //1   
    var shareAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Share" , handler: { (action:UITableViewRowAction!, indexPath:NSIndexPath!) -> Void in
   //2
    let shareMenu = UIAlertController(title: nil, message: "Share using", preferredStyle: .ActionSheet)

    let twitterAction = UIAlertAction(title: "Twitter", style: UIAlertActionStyle.Default, handler: nil)
    let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil)

    shareMenu.addAction(twitterAction)
    shareMenu.addAction(cancelAction)


    self.presentViewController(shareMenu, animated: true, completion: nil)
    })
   //3
    var rateAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Rate" , handler: { (action:UITableViewRowAction!, indexPath:NSIndexPath!) -> Void in
   //4
    let rateMenu = UIAlertController(title: nil, message: "Rate this App", preferredStyle: .ActionSheet)

    let appRateAction = UIAlertAction(title: "Rate", style: UIAlertActionStyle.Default, handler: nil)
    let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil)

    rateMenu.addAction(appRateAction)
    rateMenu.addAction(cancelAction)


    self.presentViewController(rateMenu, animated: true, completion: nil)
    })
   //5
    return [shareAction,rateAction]
  }

Докладніше про це можна дізнатися на сторінці Цей сайт . Власна документація від Apple. дійсно корисно для зміни кольору фону:

Колір фону кнопки дії.

     

Деклараціяobjective-c@property (неатомічна, копія) UIColor   * backgroundColor Обговорення Використовуйте це властивість, щоб вказати колір фону для кнопки. Якщо ви не вказуєте значення для   це властивість, UIKit призначає колір за замовчуванням на основі значення в   властивість стилю.

     

Доступність Доступно в iOS 8.0 і пізніших версіях.

Якщо ви хочете змінити шрифт кнопки, це трохи складніше. Я бачив інший пост на SO. Задля забезпечення коду, а також посилання, тут код, який вони використовували там. Потрібно змінити вигляд кнопки. Ви повинні зробити певну посилання на tableviewcell, інакше ви б змінили вигляд кнопки у вашому додатку (я не хотів цього, але ви могли б, я не знаю :))

Завдання C:

+ (void)setupDeleteRowActionStyleForUserCell {

    UIFont *font = [UIFont fontWithName:@"AvenirNext-Regular" size:19];

    NSDictionary *attributes = @{NSFontAttributeName: font,
                      NSForegroundColorAttributeName: [UIColor whiteColor]};

    NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString: @"DELETE"
                                                                          attributes: attributes];

    /*
     * We include UIView in the containment hierarchy because there is another button in UserCell that is a direct descendant of UserCell that we don't want this to affect.
     */
    [[UIButton appearanceWhenContainedIn:[UIView class], [UserCell class], nil] setAttributedTitle: attributedTitle
                                                                                          forState: UIControlStateNormal];
}

Swift:

    //create your attributes however you want to
    let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(UIFont.systemFontSize())] as Dictionary!            

   //Add more view controller types in the []
    UIButton.appearanceWhenContainedInInstancesOfClasses([ViewController.self])

Це найпростіший і найбільш потоковий варіант IMHO. Сподіваюся, що це допоможе.

Оновлення: ось версія Swift 3.0:

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    var shareAction:UITableViewRowAction = UITableViewRowAction(style: .default, title: "Share", handler: {(action, cellIndexpath) -> Void in
        let shareMenu = UIAlertController(title: nil, message: "Share using", preferredStyle: .actionSheet)

        let twitterAction = UIAlertAction(title: "Twitter", style: .default, handler: nil)
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)

        shareMenu.addAction(twitterAction)
        shareMenu.addAction(cancelAction)


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

    var rateAction:UITableViewRowAction = UITableViewRowAction(style: .default, title: "Rate" , handler: {(action, cellIndexpath) -> Void in
       //4
        let rateMenu = UIAlertController(title: nil, message: "Rate this App", preferredStyle: .actionSheet)

        let appRateAction = UIAlertAction(title: "Rate", style: .default, handler: nil)
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)

        rateMenu.addAction(appRateAction)
        rateMenu.addAction(cancelAction)


        self.present(rateMenu, animated: true, completion: nil)
    })
   //5
    return [shareAction,rateAction]
}
3
додано
@Septronic Не могли б ви оновити код до Swift 3? shareMenu. не приймає метод addAction . Дякую
додано Автор bibscy, джерело
@bibscy Я додав швидку версію. Вам також потрібен біт для атрибута? sharemenu - це просто UIAlertController, тому він повинен виконати дію. Спробуйте і дайте мені знати, якщо пощастить :)
додано Автор Septronic, джерело
@GuyKahlon так, ви абсолютно праві у відношенні лівого і правого питання проколювання, і я згоден, що для більшої настройки, MGSwipeTableCell є кращим. Власний Apple не є найскладнішим варіантом, але я знайшов його найпростішим для простих завдань.
додано Автор Septronic, джерело
Дякуємо за вашу відповідь. Я впевнений, що це допоможе багатьом розробникам. Так, ви праві, насправді Apple надає це рішення з iOS 8. Але, на жаль, це рідне рішення не забезпечує повну функціональність. Наприклад, у програмі Mail від Apple ви маєте кнопки з двох сторін (одна кнопка з лівого боку та три з правого боку) з поточним API від Apple, ви не можете додавати кнопки для обох сторін, а також поточний API не підтримує дію за замовчуванням, коли користувач провів довжину до кожної сторони. Найкраще рішення для ІМХО є відкритим вихідним кодом MGSwipeTableCell.
додано Автор Guy Kahlon, джерело

Фактичний Swift 3 відповідь

Це єдина необхідна функція. Для користувацьких дій вам не потрібні функції CanEdit або CommitEditingStyle.

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let action1 = UITableViewRowAction(style: .default, title: "Action1", handler: {
        (action, indexPath) in
        print("Action1")
    })
    action1.backgroundColor = UIColor.lightGray
    let action2 = UITableViewRowAction(style: .default, title: "Action2", handler: {
        (action, indexPath) in
        print("Action2")
    })
    return [action1, action2]
}
3
додано

Це може допомогти вам.

-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
 UITableViewRowAction *button = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 1" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
    {
        NSLog(@"Action to perform with Button 1");
    }];
    button.backgroundColor = [UIColor greenColor]; //arbitrary color
    UITableViewRowAction *button2 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 2" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
                                    {
                                        NSLog(@"Action to perform with Button2!");
                                    }];
    button2.backgroundColor = [UIColor blueColor]; //arbitrary color

    return @[button, button2]; //array with all the buttons you want. 1,2,3, etc...
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
// you need to implement this method too or nothing will work:

}
 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return YES; //tableview must be editable or nothing will work...
    }
3
додано

There is an amazing library called SwipeCellKit, it should gain more acknowledgement. In my opinion it is cooler than MGSwipeTableCell. The latter doesn't completely replicate the behavior of the Mail app's cells whereas SwipeCellKit does. Have a look

1
додано
@ Підкова7 це дивно. Я ніколи не стикався з будь-яким винятком при використанні SwipeCellKit. Зрештою, яке відношення може мати клітина до такого виключення, яке відбувається через зміни джерела даних?
додано Автор Andrey Chernukha, джерело
Я випробував SwipeCellKit і був вражений ... до тих пір, поки не отримав одне з цих виключень, оскільки кількість рядків перед оновленням перегляду таблиці не було таким, як після оновлення +/- зміни в рядках. Справа в тому, що я ніколи не міняв свій набір даних. Так що, якщо це не хвилює, я не знаю, що це таке. Тому я вирішив не використовувати його і просто використовував нові методи UITableViewDelegate. Якщо потрібно більше налаштувань, завжди можна замінити willBeginEditingRowAt: ....
додано Автор horseshoe7, джерело

Swift 4 & iOS 11+

@available(iOS 11.0, *)
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {

    let delete = UIContextualAction(style: .destructive, title: "Delete") { _, _, handler in

        handler(true)
       //handle deletion here
    }

    let more = UIContextualAction(style: .normal, title: "More") { _, _, handler in

        handler(true)
       //handle more here
    }

    return UISwipeActionsConfiguration(actions: [delete, more])
}
1
додано

Ось трохи тендітний спосіб зробити це, що не передбачає використання приватних API або побудови власної системи. Ви хеджуєте свої ставки, що Apple не порушує це і що, сподіваємося, вони випустять API, який можна замінити на ці кілька рядків коду.

  1. KVO self.contentView.superview.layer.sublayer. Do this in init. This is the UIScrollView's layer. You can't KVO 'subviews'.
  2. When subviews changes, find the delete confirmation view within scrollview.subviews. This is done in the observe callback.
  3. Double the size of that view and add a UIButton to the left of its only subview. This is also done in the observe callback. The only subview of the delete confirmation view is the delete button.
  4. (optional) The UIButton event should look up self.superview until it finds a UITableView and then call a datasource or delegate method you create, such as tableView:commitCustomEditingStyle:forRowAtIndexPath:. You may find the indexPath of the cell by using [tableView indexPathForCell:self].

Це також вимагає, щоб ви реалізовували стандартне редагування таблиць для делегування зворотних викликів.

static char kObserveContext = 0;

@implementation KZTableViewCell {
    UIScrollView *_contentScrollView;
    UIView *_confirmationView;
    UIButton *_editButton;
    UIButton *_deleteButton;
}

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        _contentScrollView = (id)self.contentView.superview;

        [_contentScrollView.layer addObserver:self
             forKeyPath:@"sublayers"
                options:0
                context:&kObserveContext];

        _editButton = [UIButton new];
        _editButton.backgroundColor = [UIColor lightGrayColor];
        [_editButton setTitle:@"Edit" forState:UIControlStateNormal];
        [_editButton addTarget:self
                        action:@selector(_editTap)
              forControlEvents:UIControlEventTouchUpInside];

    }
    return self;
}

-(void)dealloc {
    [_contentScrollView.layer removeObserver:self forKeyPath:@"sublayers" context:&kObserveContext];
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if(context != &kObserveContext) {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
        return;
    }
    if(object == _contentScrollView.layer) {
        for(UIView * view in _contentScrollView.subviews) {
            if([NSStringFromClass(view.class) hasSuffix:@"ConfirmationView"]) {
                _confirmationView = view;
                _deleteButton = [view.subviews objectAtIndex:0];
                CGRect frame = _confirmationView.frame;
                CGRect frame2 = frame;
                frame.origin.x -= frame.size.width;
                frame.size.width *= 2;
                _confirmationView.frame = frame;

                frame2.origin = CGPointZero;
                _editButton.frame = frame2;
                frame2.origin.x += frame2.size.width;
                _deleteButton.frame = frame2;
                [_confirmationView addSubview:_editButton];
                break;
            }
        }
        return;
    }
}

-(void)_editTap {
    UITableView *tv = (id)self.superview;
    while(tv && ![tv isKindOfClass:[UITableView class]]) {
        tv = (id)tv.superview;
    }
    id delegate = tv.delegate;
    if([delegate respondsToSelector:@selector(tableView:editTappedForRowWithIndexPath:)]) {
        NSIndexPath *ip = [tv indexPathForCell:self];
       //define this in your own protocol
        [delegate tableView:tv editTappedForRowWithIndexPath:ip];
    }
}
@end
1
додано
Виконано. Це може бути помилка або дві, але ви отримаєте суть.
додано Автор xtravar, джерело
Я дуже радий, якщо ви можете надати зразок коду, спасибі
додано Автор Guy Kahlon, джерело
Дякую за допомогу
додано Автор Guy Kahlon, джерело

Swift 4

func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let delete = UIContextualAction(style: .destructive, title: "Delete") { (action, sourceView, completionHandler) in
        print("index path of delete: \(indexPath)")
        completionHandler(true)
    }
    let rename = UIContextualAction(style: .normal, title: "Edit") { (action, sourceView, completionHandler) in
        print("index path of edit: \(indexPath)")
        completionHandler(true)
    }
    let swipeActionConfig = UISwipeActionsConfiguration(actions: [rename, delete])
    swipeActionConfig.performsFirstActionWithFullSwipe = false
    return swipeActionConfig
}
0
додано
що таке вихідний код у ваших кодах? це значок або зображення?
додано Автор Saeed Rahmatolahi, джерело

Ось одне просте рішення. Він здатний відображати та приховувати власні UIView всередині UITableViewCell. Відображення логіки міститься всередині класу, розширеного з UITableViewCell, BaseTableViewCell.

BaseTableViewCell.h

#import 

@interface BaseTableViewCell : UITableViewCell

@property(nonatomic,strong)UIView* customView;

-(void)showCustomView;

-(void)hideCustomView;

@end

BaseTableViewCell.M

#import "BaseTableViewCell.h"

@interface BaseTableViewCell()
{
    BOOL _isCustomViewVisible;
}

@end

@implementation BaseTableViewCell

- (void)awakeFromNib {
   //Initialization code
}

-(void)prepareForReuse
{
    self.customView = nil;
    _isCustomViewVisible = NO;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

   //Configure the view for the selected state
}

-(void)showCustomView
{
    if(nil != self.customView)
    {
        if(!_isCustomViewVisible)
        {
            _isCustomViewVisible = YES;

            if(!self.customView.superview)
            {
                CGRect frame = self.customView.frame;
                frame.origin.x = self.contentView.frame.size.width;
                self.customView.frame = frame;
                [self.customView willMoveToSuperview:self.contentView];
                [self.contentView addSubview:self.customView];
                [self.customView didMoveToSuperview];
            }

            __weak BaseTableViewCell* blockSelf = self;
            [UIView animateWithDuration:.5 animations:^(){

                for(UIView* view in blockSelf.contentView.subviews)
                {
                    CGRect frame = view.frame;
                    frame.origin.x = frame.origin.x - blockSelf.customView.frame.size.width;
                    view.frame = frame;
                }
            }];
        }
    }
}

-(void)hideCustomView
{
    if(nil != self.customView)
    {
        if(_isCustomViewVisible)
        {
            __weak BaseTableViewCell* blockSelf = self;
            _isCustomViewVisible = NO;
            [UIView animateWithDuration:.5 animations:^(){
                for(UIView* view in blockSelf.contentView.subviews)
                {
                    CGRect frame = view.frame;
                    frame.origin.x = frame.origin.x + blockSelf.customView.frame.size.width;
                    view.frame = frame;
                }
            }];
        }
    }
}

@end

Щоб отримати цю функціональність, простіше розширюйте стільницю перегляду таблиці з BaseTableViewCell.

Далі, Усередині UIViewController, який реалізує UITableViewDelegate, створюйте два розпізнавачі жестів для обробки лівого та правого шлангів.

- (void)viewDidLoad {
    [super viewDidLoad];
   //Do any additional setup after loading the view, typically from a nib.

    [self.tableView registerNib:[UINib nibWithNibName:CUSTOM_CELL_NIB_NAME bundle:nil] forCellReuseIdentifier:CUSTOM_CELL_ID];

    UISwipeGestureRecognizer* leftSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleLeftSwipe:)];
    leftSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
    [self.tableView addGestureRecognizer:leftSwipeRecognizer];

    UISwipeGestureRecognizer* rightSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleRightSwipe:)];
    rightSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
    [self.tableView addGestureRecognizer:rightSwipeRecognizer];
}

Потім додайте два серветки

- (void)handleLeftSwipe:(UISwipeGestureRecognizer*)recognizer
{
    CGPoint point = [recognizer locationInView:self.tableView];
    NSIndexPath* index = [self.tableView indexPathForRowAtPoint:point];

    UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:index];

    if([cell respondsToSelector:@selector(showCustomView)])
    {
        [cell performSelector:@selector(showCustomView)];
    }
}

- (void)handleRightSwipe:(UISwipeGestureRecognizer*)recognizer
{
    CGPoint point = [recognizer locationInView:self.tableView];
    NSIndexPath* index = [self.tableView indexPathForRowAtPoint:point];

    UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:index];

    if([cell respondsToSelector:@selector(hideCustomView)])
    {
        [cell performSelector:@selector(hideCustomView)];
    }
}

Тепер, всередині cellForRowAtIndexPath, UITableViewDelegate, ви можете створити власний UIView і прикріпити його до вилученої комірки.

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CustomCellTableViewCell* cell = (CustomCellTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"CustomCellTableViewCell" forIndexPath:indexPath];

    NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:@"CellCustomView"
                                                      owner:nil
                                                    options:nil];

    CellCustomView* customView = (CellCustomView*)[ nibViews objectAtIndex: 0];

    cell.customView = customView;

    return cell;
}

Звичайно, цей спосіб завантаження користувальницького UIView саме для цього прикладу. Керуйте ним, як ви хочете.

0
додано

Я використав tableViewCell , щоб показати декілька даних, після swipe() праворуч на ліворуч на клітині буде показано дві кнопки Затвердити і відхилити, є два методи, перший - ApproveFunc, який приймає один аргумент, і інший - RejectFunc, який також приймає один аргумент.

enter image description here

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
        let Approve = UITableViewRowAction(style: .normal, title: "Approve") { action, index in

            self.ApproveFunc(indexPath: indexPath)
        }
        Approve.backgroundColor = .green

        let Reject = UITableViewRowAction(style: .normal, title: "Reject") { action, index in

            self.rejectFunc(indexPath: indexPath)
        }
        Reject.backgroundColor = .red



        return [Reject, Approve]
    }

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

    func ApproveFunc(indexPath: IndexPath) {
        print(indexPath.row)
    }
    func rejectFunc(indexPath: IndexPath) {
        print(indexPath.row)
    }
0
додано
Дякуємо за цей фрагмент коду, який може надати деяку обмежену та негайну допомогу. відредагуйте свою відповідь, щоб додати пояснення, включаючи припущення, які ви зробили.
додано Автор Tim, джерело
Чи можете ви додати пояснення до вашої відповіді, що читач може дізнатися з неї?
додано Автор Nico Haase, джерело
IT KPI iOS
IT KPI iOS
74 учасників

Чат обсуждения IOS. - Оффтоп, флуд, оскорбления и вбросы здесь не приняты. - За нарушение - предупреждение или mute на неделю. - За спам и рекламу - ban. Все чаты IT KPI: https://t.me/itkpi/602

ios_jobs_ua
ios_jobs_ua
27 учасників

Mobile Dev Jobs UA
Mobile Dev Jobs UA
20 учасників

Публикуем вакансии и запросы на поиск работы по направлению iOS, Android, Xamarin, RN и т.д.