2015-04-22 20 views
5

Ich versuche, eine objektorientierte iOS-App zu erstellen, und ich habe Probleme beim Aufrufen einer Tabelle reload (UI-Interaktion) aus einer meiner schnellen Klassendateien.iOS ein UITableView von einer Swift-Klasse/Objekt neu laden

Wenn ich ohne Objekte arbeite und all diese Sachen in der ViewDidLoad-Methode meines InterfaceControllers schreibe, funktioniert alles ... aber nicht, wenn ich das in Klassen setze.

Ich verwende eine asynchrone Anfrage, um Json Daten von einem Webservice zu laden. Nach dem Empfang der Daten verwende ich diese Daten als Datenquelle für meine Tabellenansicht. Es scheint, dass die Tabellenansicht nach dem Start ohne Daten initialisiert wird. Daher ist es erforderlich, reload() in der Tabellenansicht aufzurufen, nachdem die Async-Anfrage abgeschlossen wurde.

sind also hier die Details:

Haupt 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 Klasse

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() 
     } 
    } 
} 
} 

Es wirft Fehler kompilieren, wenn ich versuche, die self Variable in den Konstruktor meines Konstruktor zu setzen

var fhem :FHEM = FHEM(tableview : self) 

Es ist nicht auch funktionieren, wenn ich die UITableView direkt in den Konstruktor

var fhem :FHEM = FHEM(tableview : myTableView) 

Am setzen versuche ich entlang komplett falschen Weg zu Fuß Objekte und die Interaktion mit dem ui verwenden?

+0

Sie können eine Benachrichtigung für Ihre Tabellenansicht neu laden und fügen Sie einen Beobachter zu Ihrem TableView-Controller, um die reloadData dort auslösen –

+0

Intersting, haben Sie ein Beispiel? – Barzille

Antwort

9

Sie können nur eine Benachrichtigung hinterlassen, wenn Ihr async Aufgabe beendet:

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

einen Beobachter In dieser Benachrichtigung an DeviceOverview Klassenmethode viewDidLoad:

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

und die Methode hinzufügen, die sein wird, gefeuert an Ihrer DeviceOverview Klasse

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

Vielen Dank, das hat den Trick! Könnten Sie bitte für die Frage stimmen? – Barzille

0

Ich weiß nicht viel Swift, aber ich habe schon seit einiger Zeit Objective-C für iOS geschrieben. (In Objective-C mindestens) Sie müssen auf super vor dem Zugriff auf sich selbst aufrufen, sonst Sie Objekt ist nicht richtig initialisiert. Sie geben auch nicht das self Ergebnis von super.init(), das in Objective-C erforderlich ist, sieht aus, als ob es nicht in Swift ist.

tl; dr - Verschieben Sie den Anruf an super.init() an die erste Zeile in Ihrer FHEM Klasse 'init Methode.

+0

Vielen Dank, ich werde versuchen, dass – Barzille

+0

Das wird in diesem Fehler führen: Eigenschaft 'self.devices' nicht initialisiert bei super.init Anruf – Barzille

2

Hallo Sie können Benachrichtigung als sugg verwenden oben in Antworten sonst können Sie Delegierung verwenden, um dieses Problem zu beheben

Delegat macht so etwas, was Sie getan haben, aber auf einfache Weise.

Hier übergeben Sie Tabellenansicht Controller in Ihrer benutzerdefinierten Klasse.Diese Sache können Sie mit Delegate tun. Erstellen Sie benutzerdefinierte Delegate-Methode in Ihrer benutzerdefinierten Klasse. Setzen Sie den Delegaten mit dem Table-View-Controller-Objekt.

hier Sie nicht nehmen IBOutlet Ihrer Tabellenansicht erforderlich, da der Controller aus der Tabelle View-Controller geerbt, so dass es nach Ansicht der ist Tabellenansicht

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() 
      } 
     } 
    } 
} 

Hier in FHEM Klasse Erstellen Sie eine benutzerdefinierte Delegate-Methode reloadDataOfTable, die in Ihrer ViewController-Klasse zu implementieren, so wenn die Antwort des Codes ruft diese Methode und diese Methode (reloadDataOfTable) Content-Code zum Neuladen der Tabelle dat ein.

+0

Perfekt gearbeitet – Barzille

+0

Gibt es eine Möglichkeit, self.tableView.ReloadData() in die Erweiterung des FHEM-Protokolls zu verschieben? – 2ank3th

+0

@ 2ank3th können Sie bitte lassen Sie mich wissen, warum Sie selb.tableView.reloadData() zu Protokollerweiterung. Sie haben Methode reloadDataOfTable() Protokoll in Ihrem View-Controller, wo Sie dies tun können. – user1548843

Verwandte Themen