Как отобразить сообщение об ошибке при выборе строки в другом разделе - PullRequest
0 голосов
/ 28 июня 2019

По сути, у меня есть tableView, который разделен на секции.

TableView позволяет выбирать несколько строк и отображает вспомогательный элемент .checkmark на всех выбранных строках.

Если пользователь начинает выбирать строки под одним разделом и пытается выбрать другую строку под другим, я хотел бы, чтобы появилось предупреждающее сообщение и выбор не был сделан.

Ниже приведен код:

import UIKit

class TableViewController: UITableViewController {
    var Name = UserDefaults.standard.string(forKey: "name")!
    var sections = [Section]()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellId")
        navigationController?.navigationBar.prefersLargeTitles = true
        fetchJSON()

        self.tableView.allowsMultipleSelection = true

        }

    }

Ответы [ 4 ]

1 голос
/ 28 июня 2019

Реализация UITableViewDelegate метод tableView(_:willSelectRowAt:).

Используйте map(_:), чтобы получить sections от indexPathsForSelectedRows.

Проверьте, содержится ли indexPath's section в tableView(_:willSelectRowAt:) в ранее полученном sections array, используя contains(_:)

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    if let sections = tableView.indexPathsForSelectedRows?.map({ $0.section }) {
        if !sections.contains(indexPath.section) {
            //Show Alert here....
            let alert = UIAlertController(title: "Alert..!!", message: "You're selection row from Section:\(indexPath.section)", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            self.present(alert, animated: true, completion: nil)

            return nil
        }
    }
    return indexPath
}

tableView (_: willSelectRowAt:) возвращаемое значение: объект индекса пути это подтверждает или изменяет выбранную строку. Вернуть объект NSIndexPath кроме indexPath, если вы хотите, чтобы была выбрана другая ячейка. Вернуть ноль, если вы не хотите, чтобы выбранная строка.

0 голосов
/ 28 июня 2019

Check tableView (_: willSelectRowAt:) . Вы можете вернуть nil из этого метода делегата, чтобы предотвратить выбор строки.

override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    if let
        indexPathsForSelectedRows = tableView.indexPathsForSelectedRows, indexPathsForSelectedRows.count > 0,
        indexPath.section != indexPathsForSelectedRows[0].section
    {
        // If there is at least one row already selected
        // And the section of that row is different than the section of the row about to be selected
        // Don't allow the selection
        let alertController = UIAlertController(title: "Whoops!", message: "Don't do that!", preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "Okay", style: .default, handler: nil))
        present(alertController, animated: true, completion: nil)
        return nil
    }

    // There's either nothing selected yet or the section of this row is the same as those already selected
    return indexPath
}
0 голосов
/ 28 июня 2019

Я думаю, вам нужно создать для этого дополнительную логику, например. Вы можете поместить в один массив все выбранные indexPath и всегда сравнивать первый элемент (indexPath) с каждым элементом, который вы хотите добавить, indexPath содержит свойство Section, поэтому просто нужно сравнить, равен ли раздел или нет, если это не так, вы показываете оповещение, которое хотите, после этого вы отменяете выбор элемента вручную.

var selectedItems = [IndexPath]()
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if let firstIndexPath = selectedItems.first{
        //If the section with the first element selected and the new selection are not equals, display your message
        if indexPath.section != firstIndexPath.section{
            let alert = UIAlertController(title: "Warning", message: "Message", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: {
                a in
                self.selectIndexPath(indexPath: indexPath, isSelected: false)
            }))
            //You can put it here if you prefer not wait for the closure for realize the deselection
            //self.selectIndexPath(indexPath: indexPath, isSelected: false)
            self.present(alert, animated: true, completion: nil)
            return
        }
        self.selectIndexPath(indexPath: indexPath, isSelected: true)
    }else{
        self.selectIndexPath(indexPath: indexPath, isSelected: true)
    }


}
func selectIndexPath(indexPath: IndexPath, isSelected: Bool){

    tableView.cellForRow(at: indexPath)?.accessoryType = isSelected ? .checkmark : .none
    if isSelected{
       selectedItems.append(indexPath)
    }else{
        selectedItems.removeAll(where: {$0 == indexPath})
        tableView.deselectRow(at: indexPath, animated: true)
    }
    let section = sections[indexPath.section]
    let item = section.items[indexPath.row]
    // for all selected rows assuming tableView.allowsMultipleSelection = true
}
0 голосов
/ 28 июня 2019

Из того, что я понимаю, вы можете сделать следующее:

  1. Добавьте значение bool в структуру вашего раздела, чтобы проверить, выбран ли у вас какой-либо элемент
struct Section {
    let name : String
    var hasItemsSelected: Bool
    let items : [Portfolios]
}
  1. измени свой didSelectRowAt

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        //when you select a row check if there is another row selected on another section by checking if the hasItemsSelected is true on all other sections

        //1. create an array containing all section besides the current section
        let allOtherSections = sections
                                    .enumerated()
                                    .filter {  $0.offset != indexPath.section }
                                    .map { $0.element } 

        //2. if allOtherSections does not have seledcted items
        if allOtherSections.allSatisfy { $0.hasItemsSelected == false } {
           self.sections[indexPath.section].hasItemsSelected = true
           tableView.cellForRow(at: ind exPath)?.accessoryType = .checkmark
        } else {

           let numberOfSelectedRowsOnCurrentIndexPath = tableView.indexPathsForSelectedRows?.enumerated().filter { $0.offset != 1 }.count
           if numberOfSelectedRowsOnCurrentIndexPath == 0 {
             self.sections[indexPath.section].hasItemsSelected = false
           }

           tableView.deselectRow(at: indexPath, animated: true)

           //show the alert here
           let alertController = UIAlertController(title: "Title", message: "Your message", preferredStyle: .alert)
           alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
           self.present(alertController, animated: true, completion: nil)
        }
    }

Я надеюсь, что помог вам

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...