2016-03-31 5 views
1

У меня есть следующие два ViewControllers (один из них - TableViewController), который CategoryTableViewController имеет метод делегата, который будет вызываться при выборе ячейки таблицы. Затем CreateRecipeViewController реализует этот метод делегата и обрабатывает выбранную строку категории.Swift 2.1 - Неожиданно найдено нуль во время разворачивания необязательного вызова метода делегата

Я получаю fatal error: unexpectedly found nil while unwrapping an Optional на линии delegate.categoryController(self, didSelectCategory: categoryCell)

print(categoryCell) правильно печатает значение строки выбранной ячейки таблицы, так что я не знаю, почему я получаю эту ошибку.

Я новичок в реализации протокола, поэтому может быть высокий шанс, что я делаю это неправильно. Я бы очень признателен, если кто-то может дать мне понять эту ошибку.

CategoryTableViewController (выбрать категорию)

protocol CategoryTableViewControllerDelegate: class { 
    func categoryController(controller: CategoryTableViewController, didSelectCategory category: String) 
} 

class CategoryTableViewController: UITableViewController { 

    ... 

    weak var delegate: CategoryTableViewControllerDelegate! 

    ... 

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {   

     if let categoryCell = recipeCategory[indexPath.row].name { 
      print(categoryCell) 
      delegate.categoryController(self, didSelectCategory: categoryCell) 
     } 
    } 

} 

CreateRecipeViewController (получает выбранной категории)

extension CreateRecipeViewController: CategoryTableViewControllerDelegate { 
    func categoryController(controller: CategoryTableViewController, didSelectCategory category: String) { 

     let selectedCategory = category 
     dismissViewControllerAnimated(true, completion: nil) 

     let cell = RecipeCategoryCell() 
     cell.configureSelectedCategoryCell(selectedCategory) 

     recipeCategoryTableView.reloadData() 
    } 
} 

UPDATE

enter image description here

+0

'delegate' is nil – dan

+0

Не могли бы вы рассказать о том, как я могу заставить делегат удерживать значение' categoryCell'. Я новичок в этом. –

+0

Нужна ли нисходящая линия? –

ответ

3

Проблема в том, что вы забыли присвоить значение для свойства delegate. Другими словами, delegate - это нуль.

С delegate является неявным необоснованным дополнительным типом, вам не нужно добавлять знак вопроса или восклицательный знак, чтобы развернуть его. Вот почему вы не заметили ошибки.

Чтобы решить эту проблему, просто поставить знак вопроса после delegate:

delegate?.categoryController(self, didSelectCategory: categoryCell) 

Но это не решает проблему! Таким образом, categoryController(:didSelectCategory:) никогда не будет называться!

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

Для упрощения, позвоните нам CategoryTableViewControllerОтправитель и CreateRecipeViewController приемник.

Это то, что я думаю, вы хотите сделать. Вы хотите, чтобы пользователь выбирал категорию в отправителе и передавал выбранную категорию получателю. Итак, в отправителе вам нужно позвонить performSegueWithIdentifier, правильно?

Когда вид будет выполнен, вызывается prepareForSegue. Вам необходимо переопределить этот метод:

override func prepareForSegue(segue: UIStoryBoardSegue) { 
    if segue.identifier == "your segue's identifier" { 
     let destinationVC = segue.destinationViewController as! reciever 
     destinationVC.selectedCategory = self.selectedCategory 
    } 
} 

В приведенном выше коде есть некоторые вещи, которые не определены. Давайте определим их сейчас.

Первое, что есть destination.selectedCategory.Вы добавляете свойство в приемнике:

var selectedCategory: String! 

В viewDidLoad приемника, вы можете использовать это свойство, чтобы знать, что пользователь выбрал. Другими словами, данные передаются этому свойству.

Второй - self.selectedCategory. Давайте определим, что хорошо, в передатчике:

var selectedCategory: String! 

В tableView(:didSelectRowAtIndexPath:indexPath:) отправителя, вам нужно присвоить self.selectedCategory категория выбрана:

self.categorySelected = recipeCategory[indexPath.row].name 

И БУМ! Это оно!

+0

Спасибо. Я думал, что вся цель реализации делегирования заключается в совместном использовании свойств между несколькими контроллерами view. Я применил 'prepareForSegue' для получателя -> отправителя, так как у меня есть tableview на приемнике. Вы хотите сказать, что для отправителя -> приемника необходим «prepareForSegue»? и делегат не нужен? См. Обновленное изображение. –

+0

'prepareForSegue' необходимо, когда вам нужно что-то сделать, прежде чем идти другим контроллером. Я в основном переопределяю его, когда хочу передать значение другому vc. Так что да, это необходимо для отправителя -> приемника. Вся точка делегирования - это не передача данных между контроллерами представлений. Он используется, когда класс должен уведомлять другой класс о том, что с ним что-то случилось. Например, 'UITextFieldDelegate' имеет такие методы, как' didEndEditing'. Это сообщает классу-исполнителю, что текстовое поле закончило редактирование. Это немного напоминает обратные вызовы в Javascript. @SeongLee – Sweeper

+0

Я вижу. Я неправильно понял понятие делегата. Я буду следить за тем, как я пошел с вашим руководством, спасибо большое! –