2016-04-25 3 views
0

Я пытаюсь реализовать табличное представление multi-selection в iOS. Как это работает:Невозможно отменить выбор первой выбранной ячейки в tableview

У каждого предмета есть флажок слева. Когда пользователь отключает этот флажок, режим tableview переключается в режим многоэкранного выбора. Теперь пользователь может выбрать дополнительные элементы, нажав на флажок или в любом месте в ячейках. Это все работает нормально, за исключением 1 вещи:

Скажите, что у меня есть 3 объекта в моем списке: A, B и C упорядочены по алфавиту. Я использую флажок «А», чтобы перейти в режим множественного выбора, и перейдите к добавлению B и C. Если я снова нажму B или C, элемент будет отменен, а соответствующие флажки снова не будут отмечены. Если я попытаюсь отменить выбор A до того, как B и C будут отменены, ячейка по-прежнему будет выбрана. Однако он удаляется из моего массива выбранных элементов. Это всегда происходит с элементом, который я использую для входа в режим множественного выбора.

Мой код:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 
    let cell = tableView.cellForRowAtIndexPath(indexPath) as! MyNotificationTableViewCell 
    let notification = fetchedResultsController.objectAtIndexPath(indexPath) as! MyNotification 

    if(tableView.allowsMultipleSelection){ 
     if(!selectedNotificationsArray.containsObject(notification.notification_id)){ 
      tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: UITableViewScrollPosition.None) 
      selectedNotificationsArray.addObject(notification.notification_id) 
      cell.selectionButton.imageView?.image = UIImage(named: "CheckboxChecked") 
     } 
    }else{ 
     tableView.deselectRowAtIndexPath(indexPath, animated: false) 
     let alert = UIAlertView(
      title: notification.scope, 
      message: notification.message, 
      delegate: self, 
      cancelButtonTitle: LocalizedString("cancel"), 
      otherButtonTitles: LocalizedString("alert_option_mark_as_read") 
     ) 
     alert.tag = 1 
     selectedNotificationsArray.addObject(notification.notification_id) 
     alert.show() 
    } 

    cell.setNeedsDisplay() 
} 

func alertView(alertView: UIAlertView, clickedButtonAtIndex buttonIndex: Int) { 
    if (buttonIndex == 1) { 
     markSelectedNotificationsAsRead() 
    }else{ 
     selectedNotificationsArray.removeAllObjects() 
    } 
} 

override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) { 
    print("deselected a cell") 

    let cell = tableView.cellForRowAtIndexPath(indexPath) as! MyNotificationTableViewCell 
    let notification = fetchedResultsController.objectAtIndexPath(indexPath) as! MyNotification 

    if(selectedNotificationsArray.containsObject(notification.notification_id)){ 
     selectedNotificationsArray.removeObject(notification.notification_id) 
     tableView.deselectRowAtIndexPath(indexPath, animated: false) 
     cell.selectionButton.imageView?.image = UIImage(named: "CheckboxUnchecked") 
     if(selectedNotificationsArray.count == 0){ 
      switchNavigationBarMode(false) 
      tableView.reloadData() 
     } 
    } 
} 

func tappedSelectionCheckbox(sender: CheckBoxButton){ 
    let notification = fetchedResultsController.objectAtIndexPath(sender.cellIndexPath!) as! MyNotification 
    print("tapped checkbox of notification with message: " + String(notification.message)) 
    if(tableView.allowsMultipleSelection == false){ 
     switchNavigationBarMode(true) 
    } 
    if(selectedNotificationsArray.containsObject(notification.notification_id)){ 
     tableView(tableView, didDeselectRowAtIndexPath: sender.cellIndexPath!) 
    }else{ 
     tableView(tableView, didSelectRowAtIndexPath: sender.cellIndexPath!) 
    } 
    //Redraw cell so that the checkbox is updated 
    tableView(tableView, cellForRowAtIndexPath: sender.cellIndexPath!).setNeedsDisplay() 
} 

func switchNavigationBarMode(enabled: Bool){ 
    if(enabled){ 
     tableView.allowsMultipleSelection = true 
     backButton = self.navigationItem.leftBarButtonItem 
     self.navigationItem.setLeftBarButtonItem(selectAllButton, animated: true) 
     self.navigationItem.setRightBarButtonItems([markReadButton!, deleteButton!], animated: true) 
     self.navigationItem.title = nil 
    }else{ 
     tableView.allowsMultipleSelection = false 
     self.navigationItem.title = "Notifications" 
     self.navigationItem.setLeftBarButtonItem(backButton, animated: true) 
     self.navigationItem.setRightBarButtonItems(nil, animated: true) 
    } 
} 

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier, forIndexPath: indexPath) as! MyNotificationTableViewCell 
    let notification = fetchedResultsController.objectAtIndexPath(indexPath) as! MyNotification 
    cell.messageLabel.text = notification.message 

    // Unread notifications are bold 
    if(notification.read_date.isEmpty){ 
     cell.messageLabel.font = UIFont(name: "TrebuchetMS-Bold", size: 17) 
    } 

    if(selectedNotificationsArray.containsObject(notification.notification_id)){ 
     tableView.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: UITableViewScrollPosition.None) 
     cell.selectionButton.imageView?.image = UIImage(named: "CheckboxChecked") 

    }else{ 
     tableView.deselectRowAtIndexPath(indexPath, animated: true) 
     cell.selectionButton.imageView?.image = UIImage(named: "CheckboxUnchecked") 
    } 
    cell.selectionButton.cellIndexPath = indexPath 
    cell.selectionButton.addTarget(self, action: #selector(MyNotificationViewController.tappedSelectionCheckbox(_:)), forControlEvents: UIControlEvents.TouchUpInside) 

    let dateFormatter = NSDateFormatter() 
    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.S'Z'" 
    let utcDateTimeObject = dateFormatter.dateFromString(notification.send_date) 
    dateFormatter.dateFormat = "HH:mm" 
    let shortTimestamp = dateFormatter.stringFromDate(utcDateTimeObject!) 
    cell.timestampLabel.text = shortTimestamp 
    let scope = notification.scope 
    switch(scope){ 
    case Constants.NOTIFICATION_SCOPE_DEVICE: 

     break 
    case Constants.NOTIFICATION_SCOPE_INVENTORY: 

     break 
    case Constants.NOTIFICATION_SCOPE_JOURNAL: 

     break 
    case Constants.NOTIFICATION_SCOPE_PROTOCOL: 

     break 
    case Constants.NOTIFICATION_SCOPE_SUPPLIES: 

     break 
    case Constants.NOTIFICATION_SCOPE_SYSTEM: 

     break 
    default: 
     break 
    } 
    return cell 
} 

ответ

0

Вы называете tableView.selectRowAtIndexPath в didSelectRowAtIndexPath. Я ожидаю, что это приведет к некорректному поведению.

Я предлагаю другой более простой подход. Если вы UITableViewCellAccessoryCheckmark для отображения выбранных ячеек, cellForRowAtIndexPath может проверить, есть ли A, B, C и т. Д. В вашем массиве данных, а там для выбранного и добавить галочку. Затем вам просто нужно вызвать reloadData внутри didDeselectRowAtIndexPath, который намного чище.

Это немного изменяет ваш интерфейс, поэтому, если вы строго хотите использовать выделенную сером ячейку стиля, это не сработает, но проблема, кажется, вызывает selectRowAtIndexPath внутри didDeselectRowAtIndexPath. Вы должны найти другой способ выбора ячейки.

+0

«Вы вызываете tableView.selectRowAtIndexPath внутри didDeselectRowAtIndexPath. Я ожидал бы, что это приведет к некорректному поведению». Я ...? Вы хотите сказать, что я называю это неявным образом? Поскольку у моего didDeselectRowAtIndexPath нет прямого вызова selectRowAtIndexPath. – Anubis

+0

похоже, что вы вызываете его по строке 7. –

+0

Но это внутри метода didSelectRowAtIndexPath, а не метода didDeselectRowAtIndexPath, который вы упомянули в своем ответе. – Anubis

Смежные вопросы