2016-02-12 3 views
1

У меня есть отдельный класс из UIViewController, настроенный как мой делегат UITableView и мой UITableViewDataSource.Некоторые методы делегата UITableView называются 5 раз, другие вообще не вызываются

Я пытаюсь инициализировать класс UITableViewDelegate и назначать его UITableView.

Вот что странно ...

методы numberOfSectionsInTableView и Tableview (: numberOfRowsInSection) называются пять раз, в то время как Tableview (_: cellForRowAtIndexPath) никогда не вызывается.

Я проверил как номерOfSectionsInTableView, так и tableView (: numberOfRowsInSection) возвращает значения как минимум одного.

Если я перемещаю методы UITableViewDataSource и UITableViewDelegate в ViewController, код работает правильно.

В чем причина этого поведения?

class MessagesViewController: UIViewController, ManagedObjectContextSettable { 

    var managedObjectContext: NSManagedObjectContext! 
    @IBOutlet var messagesTableView: UITableView! 

    override func viewDidLoad() { 
     setupMessagesTableView() 
    } 

    private func setupMessagesTableView() { 
     let dataSource = MessagesTableViewDataSource(managedObjectContext: managedObjectContext, conversationList: fetchedObjects as! [Conversation]) 
     // Assume fetchedObjects is an array fetched from CoreData store. I have removed the code that defines it for the purpose of this example. 
     self.messagesTableView.dataSource = dataSource 
     self.messagesTableView.delegate = dataSource 
    } 

} 

class MessagesTableViewDataSource: NSObject, UITableViewDataSource, UITableViewDelegate { 

    var managedObjectContext: NSManagedObjectContext! 
    var conversationList: [Conversation] 

    required init(managedObjectContext: NSManagedObjectContext, conversationList: [Conversation]) { 
     self.managedObjectContext = managedObjectContext 
     self.conversationList = conversationList 
     let conversation = Conversation() 
     self.conversationList.append(conversation)    
    } 

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

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

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCellWithIdentifier("CellID", forIndexPath: indexPath) as UITableViewCell! 
     let conversation: Conversation = self.conversationList[indexPath.row] 
     cell.textLabel!.text = conversation.name as? String 
     return cell 
    } 

} 
+0

Убедитесь, что self.conversationList.count выше нуля. –

+0

Может ли быть, что dialogList заполняется фоновым потоком и не заполняется во время отображения таблицыView, и в этом случае счетчик будет равен нулю? – Michael

+0

Я добавляю экземпляр в список обсуждения в функцию init класса DataSource, чтобы избежать этой проблемы. Я проверил значение chatList.count, чтобы убедиться, что он равен 1. – Kory

ответ

1

Проблема заключается в том, что ваш экземпляр MessagesTableViewDataSource будет освобождён. Свойства делегата и dataSource в UITableView слабы. Вы объявляете свой источник данных (MessagesTableViewDataSource) в качестве локальной переменной внутри вашей функции, и поэтому ничто не содержит ссылки на экземпляр MessageTableViewDataSource.

Чтобы исправить это, определите переменную экземпляра для dataSource и назначьте ее в viewDidLoad.

Пример кода:

класс MessagesViewController: UIViewController, ManagedObjectContextSettable {

let dataSource: MessagesTableViewDataSource? 
var managedObjectContext: NSManagedObjectContext! 
@IBOutlet var messagesTableView: UITableView! 

override func viewDidLoad() { 
    setupMessagesTableView() 
} 

private func setupMessagesTableView() { 
    dataSource = MessagesTableViewDataSource(managedObjectContext: managedObjectContext, conversationList: fetchedObjects as! [Conversation]) 
    // Assume fetchedObjects is an array fetched from CoreData store. I have removed the code that defines it for the purpose of this example. 
    self.messagesTableView?.dataSource = dataSource 
    self.messagesTableView?.delegate = dataSource 
} 

}

0

Проверьте раму вашего стола. Если высота или ширина равна 0, tableView:cellForRowAtIndexPath: не будет вызываться.

+0

. Кадр, кажется, установлен правильно. – Kory

0

У меня такая же проблема, и я считаю, что это ошибка в UIKit.

Я создал простой источник данных списка и небольшой контроллер просмотра, чтобы проверить это, и я могу подтвердить, что cellForRowAtIndexPath не вызывается. 'numberOfRowsInSection' возвращает значение больше 0, и кадр tableView установлен правильно.

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

SimpleListDataSource.swift

import UIKit 

class SimpleListDataSource : NSObject, UITableViewDataSource { 

    var items: [String] 
    var cellIdentifier: String 

    typealias CellConfiguration = (UITableViewCell, String) ->() 
    var cellConfiguration: CellConfiguration 

    init(items: [String], cellIdentifier: String, cellConfiguration: CellConfiguration) { 
     self.items = items 
     self.cellIdentifier = cellIdentifier 
     self.cellConfiguration = cellConfiguration 
    } 

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     print("Number of rows: \(self.items.count)") 
     return self.items.count 
    } 

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
     print(__FUNCTION__) 
     let cell = tableView.dequeueReusableCellWithIdentifier(self.cellIdentifier, forIndexPath: indexPath) 
     self.cellConfiguration(cell, self.items[indexPath.row]) 
     return cell 
    } 
} 

ViewController.swift

import UIKit 

class ViewController: UIViewController { 

    @IBOutlet weak var tableView: UITableView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let data = ["a", "b", "c"] 
     let dataSource = SimpleListDataSource(items: data, cellIdentifier: "cell") { (cell, string) ->() in 
      cell.textLabel?.text = string 
     } 

     self.tableView.dataSource = dataSource 
     self.tableView.reloadData() 
    } 
} 
+0

См. Мой ответ ниже. Вы должны объявить переменную экземпляра для dataSource, иначе экземпляр SimpleListDataSource будет освобожден. –

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