2015-04-22 4 views
5

Я пытаюсь создать объектно-ориентированное приложение для iOS, и у меня возникают проблемы с вызовом перезагрузки таблицы (взаимодействие ui) из одного из моих файлов быстрых классов.iOS перезагрузка UITableView из класса Swift/объекта

Если я работаю без объектов и пишу все это в моем методе viewDidLoad интерфейса InterfaceController, все работает ... но не, если я помещаю это в классы.

Я использую асинхронный запрос для загрузки json-данных из веб-службы. После получения данных я использую эти данные в качестве источника данных для своего представления в таблице. Кажется, что tableview инициализируется после запуска без данных, поэтому необходимо вызвать reload() в представлении таблицы после завершения асинхронного запроса.

Так вот подробности:

Главная TableController

import UIKit; 


class DeviceOverview: UITableViewController { 

@IBOutlet var myTableView: UITableView! 

var myDevices = Array<String>(); 
var myDevicesSection = NSMutableDictionary() 
var deviceObjects = Array<NSDictionary>(); 
var mappingSectionIndex = Array<String>(); 
var sharedUserDefaults = NSUserDefaults(suiteName: "group.barz.fhem.SharingDefaults") 

// THIS IS AN ATTEMPT TO give the class itself as PARAMETER 
// ALSO TRIED TO USE myTableView (IBOutlet) 
var fhem :FHEM = FHEM(tableview : self) 

override func viewDidLoad() { 

    super.viewDidLoad() 

} 


override func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
    return self.fhem.sections.count 
} 

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    var devicesInSection : Array<NSDictionary> = self.fhem.sections[self.fhem.mappingSectionIndex[section]] as! Array<NSDictionary> 
    return devicesInSection.count; 
} 

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCellWithIdentifier("device", forIndexPath: indexPath) as! TableViewCell 
    let sectionName : String = fhem.mappingSectionIndex[indexPath.section] 
    if let devices : Array<NSDictionary> = self.fhem.sections.objectForKey(sectionName) as? Array<NSDictionary> { 
     let device = devices[indexPath.row] 
     var alias : NSString?; 
     if let attr : NSDictionary = device.objectForKey("ATTR") as? NSDictionary { 
      alias = attr.objectForKey("alias") as? String 
     } 
     if (alias != nil) { 
      cell.deviceLabel.text = alias as? String 
     }else{ 
      if let deviceName : String = device.objectForKey("NAME") as? String { 
       cell.deviceLabel.text = deviceName 
      } 
     } 
    } 
    return cell 
} 

FHEM Класс

import UIKit 


class FHEM: NSObject { 

var devices : [NSDictionary] 
var sections : NSMutableDictionary 
var deviceNames : [String] 
var mappingSectionIndex : [String] 
var myTableViewController : DeviceOverview 

init(tableview : DeviceOverview){ 
    self.devices = Array<NSDictionary>() 
    self.sections = NSMutableDictionary() 
    self.deviceNames = Array<String>() 
    self.mappingSectionIndex = Array<String>() 
    self.myTableViewController = tableview 
    super.init() 

    let url = NSURL(string: "xyz"); 
    var request = NSURLRequest(URL: url!); 

    NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) { 
     (response, data, error) in 
     if let jsonData: NSData? = data { 
      // do some great stuff 
      // 
      // this is an attempt to call the table view to reload 
      self.myTableViewController.myTableView.reloadData() 
     } 
    } 
} 
} 

Он бросает ошибки компиляции, если я пытаюсь поставить переменную self в конструктор моего конструктора

var fhem :FHEM = FHEM(tableview : self) 

Он также не работает, если я пытаюсь поставить UITableView непосредственно в конструктор

var fhem :FHEM = FHEM(tableview : myTableView) 

Am Я шел по полному ложному пути, используя объекты и взаимодействующий с пользовательским интерфейсом?

+0

Вы можете отправить уведомление для своей перезагрузки таблицы и добавить наблюдателя к контроллеру tableView для запуска reloadData –

+0

Интерстинг, у вас есть пример? – Barzille

ответ

9

Вы можете просто оставить уведомление, когда ваша асинхронная задача заканчивается:

NSNotificationCenter.defaultCenter().postNotificationName("refreshMyTableView", object: nil) 

Добавить наблюдатель на это уведомление на ваш DeviceOverview метода класса viewDidLoad:

NSNotificationCenter.defaultCenter().addObserver(self, selector: "refreshList:", name:"refreshMyTableView", object: nil) 

и добавить метод, который будет в вашем классе DeviceOverview

func refreshList(notification: NSNotification){ 
    myTableView.reloadData() 
} 
+0

Спасибо, что сделал трюк! Не могли бы вы проголосовать за вопрос? – Barzille

0

Я мало знаю Swift, но я писал Objective-C для iOS некоторое время. (По крайней мере в Objective-C) вы должны позвонить init по адресу super перед тем, как получить доступ к себе, иначе вы объект не инициализирован правильно. Вы также не назначаете self на результат super.init(), что необходимо в Objective-C, похоже, что это не в Swift.

tl; dr - Переведите вызов на super.init() до самой первой строки в вашем FHEM классе 'init.

+0

Спасибо, я попробую, что – Barzille

+0

Это приведет к ошибке: Свойство «self.devices» не инициализировано при вызове super.init – Barzille

2

Hi Вы можете использовать Уведомление как предложение В ответах вы также можете найти делегацию, чтобы решить эту проблему.

Делегат делает что-то подобное, но сделал это легко.

Здесь вы передаете контроллер табличного представления в свой пользовательский класс. Это вы можете сделать с делегатом. создать пользовательский метод делегирования в вашем пользовательском классе. set delegate с объектом контроллера табличного вида.

здесь вы не обязаны принимать IBOutlet вашего зрения таблицы, потому что ваш контроллер унаследовали от табличного контроллера, так что это мнение табличное

import UIKit 


class DeviceOverview: UITableViewController,FHEMDelegate { 

    @IBOutlet var myTableView: UITableView! 

    var myDevices = Array<String>(); 
    var myDevicesSection = NSMutableDictionary() 
    var deviceObjects = Array<NSDictionary>(); 
    var mappingSectionIndex = Array<String>(); 
    var sharedUserDefaults = NSUserDefaults(suiteName: "group.barz.fhem.SharingDefaults") 
    var fhem :FHEM? 
    // THIS IS AN ATTEMPT TO give the class itself as PARAMETER 
    // ALSO TRIED TO USE myTableView (IBOutlet) 


    override func viewDidLoad() { 

     super.viewDidLoad() 
     fhem = FHEM() 
     fhem?.delegate = self 

    } 


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

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
//  var devicesInSection : Array<NSDictionary> = self.fhem!.sections[self.fhem!.mappingSectionIndex[section]] as Array<NSDictionary> 

     return 5; 
    } 

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCellWithIdentifier("device", forIndexPath: indexPath) as UITableViewCell 
     let sectionName : String = fhem!.mappingSectionIndex[indexPath.section] 
     if let devices : Array<NSDictionary> = self.fhem!.sections.objectForKey(sectionName) as? Array<NSDictionary> { 
      let device = devices[indexPath.row] 
      var alias : NSString?; 
      if let attr : NSDictionary = device.objectForKey("ATTR") as? NSDictionary { 
       alias = attr.objectForKey("alias") as? String 
      } 
      if (alias != nil) { 
       // cell.deviceLabel.text = alias as? String 
      }else{ 
       if let deviceName : String = device.objectForKey("NAME") as? String { 
        // cell.deviceLabel.text = deviceName 
       } 
      } 
     } 
     return cell 
    } 
    func reloadDataOfTable() 
    { 
     self.tableView.reloadData() 
    } 
} 

FHEM

import UIKit 
protocol FHEMDelegate{ 

    func reloadDataOfTable() 
} 
class FHEM : NSObject { 
    var devices : [NSDictionary] 
    var sections : NSMutableDictionary 
    var deviceNames : [String] 
    var mappingSectionIndex : [String] 
    //var myTableViewController : DeviceOverview 
    var delegate :FHEMDelegate? 

override init(){ 
     self.devices = Array<NSDictionary>() 
     self.sections = NSMutableDictionary() 
     self.deviceNames = Array<String>() 
     self.mappingSectionIndex = Array<String>() 
     self.delegate = nil 
     super.init() 

    let url = NSURL(string: "http://google.com"); 
     var request = NSURLRequest(URL: url!); 

     NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) { 
      (response, data, error) in 
      if let jsonData: NSData? = data { 
       // do some great stuff 
       // 
       // this is an attempt to call the table view to reload 
       self.delegate?.reloadDataOfTable() 
      } 
     } 
    } 
} 

Здесь в классе FHEM создайте один пользовательский метод делегирования reloadDataOfTable, который реализует в вашем классе viewcontroller, поэтому, когда получил ответ кода, он вызывает этот метод и этот код кода (reloadDataOfTable) для таблицы перезагрузки dat а.

+0

Работал отлично – Barzille

+0

Есть ли способ переместить self.tableView.reloadData() в расширение протокола FHEM? – 2ank3th

+0

@ 2ank3th не могли бы вы сообщить мне, почему вы хотите self.tableView.reloadData() для расширения протокола. У вас есть метод reloadDataOfTable() протокола в вашем контроллере просмотра, где вы можете это сделать. – user1548843

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