2016-04-01 6 views
0

Ich arbeite mit der folgenden Klasse, die erfolgreich eine Zeile in die UITableView lädt.Nach einer harten Zeit neu zu laden UITableView

import UIKit 
import ResearchKit 

enum Activity: Int { 
    case Demographics 

    static var allValues: [Activity] { 
     var idx = 0 
     return Array(anyGenerator{ return self.init(rawValue: idx++)}) 
    } 

    var title: String { 
     switch self { 
     case .Demographics: 
      return "Demographics" 
     } 
    } 

    var subtitle: String { 
     switch self { 
      case .Demographics: 
       return "Demographics Survey" 
     } 
    } 
} 

class ActivityViewController: UITableViewController { 

    // MARK: UITableViewDataSource 

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     guard section == 0 else { return 0 } 

     return Activity.allValues.count 
    } 

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCellWithIdentifier("activityCell", forIndexPath: indexPath) 

     if let activity = Activity(rawValue: indexPath.row) { 
      cell.textLabel?.text = activity.title 
      cell.detailTextLabel?.text = activity.subtitle 
      if (activity.title == "Demographics"){ 
       if (Data().is_demo_complete()){ 
        cell.textLabel?.textColor = UIColor.lightGrayColor() 
        cell.detailTextLabel?.textColor = UIColor.lightGrayColor() 
        cell.userInteractionEnabled = false 
       } 
      } 
     } 

     return cell 
    } 

    func reloadtable(){ 
     self.tableView.reloadData() 
    } 

    // MARK: UITableViewDelegate 

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 
     guard let activity = Activity(rawValue: indexPath.row) else { return } 

     let taskViewController: ORKTaskViewController 
     switch activity { 
      case .Demographics: 
       taskViewController = ORKTaskViewController(task: DemoTask, taskRunUUID: NSUUID()) 


     } 

     taskViewController.delegate = self 
     navigationController?.presentViewController(taskViewController, animated: true, completion: nil) 
    } 
} 

Ich habe eine andere Klasse Data genannt, wo ich speichern die gesamte Kommunikation auf meinen Server. Die Idee ist, dass ich einige Daten auf dem Server überprüfen muss, um zu wissen, ob ich eine der Zeilen in der TableView ausgrauen oder deaktivieren soll. Von der Datenklasse, wenn der Server Aufruf und erfolgreich abgeschlossen ist, ich tue dies:

dispatch_async(dispatch_get_main_queue(), {() -> Void in 
    ActivityViewController().reloadtable() 
}) 

ich bestätigt habe, dass erfolgreich die reloadtable() Funktion aufruft, in dem es self.tableView.reloadData() läuft. Der Ort, an dem ich feststecke, ist, dass das TableView danach nicht neu lädt. Ich kann sagen, weil ich einen Haltepunkt auf der Linie setze, die if let activity = Activity(rawValue: indexPath.row) { sagt, und der Unterbrechungspunkt wird nicht ein zweites Mal ausgelöst, obwohl ich bestätigen kann, dass die reloadtable() Funktion tatsächlich ausgelöst wird. Was mache ich hier falsch, warum wird der Tisch nicht neu geladen? Vielen Dank!

EDIT

Hier ist die Data Klasse:

class Data: NSObject, NSURLSessionDelegate { 

    var unique_id = UIDevice.currentDevice().identifierForVendor!.UUIDString; 

    var demo_complete = false 

    func check_demo_complete(){ 

     let request = NSMutableURLRequest(URL: NSURL(string: "https://www.myurl.com/is_demo_complete.php")!) 
     request.HTTPMethod = "POST" 
     let postString = "unique_id=\(unique_id)&pass=somepass" 
     request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding) 

     let configuration = NSURLSessionConfiguration.defaultSessionConfiguration() 
     let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil) 

     let task = session.dataTaskWithRequest(request) { 
      data, response, error in 

      if error != nil { 
       print("error=\(error)") 
       return 
      } 

      let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding) 

      if (responseString == "true") { 
       self.demo_complete = true 
       print ("Demo has been completed") 
       dispatch_async(dispatch_get_main_queue(), {() -> Void in 
        ActivityViewController().reloadtable() 
       }) 
      } 
     } 
     task.resume() 
    } 

    func is_demo_complete() -> Bool{ 
     return self.demo_complete 
    } 


} 
+0

Sind Sie sicher, dass Ihre 'self.tableView.dataSource = self' ist? – aimak

+0

Die Zeilen, die in der Tabelle angezeigt werden, sind in einer 'Enum' in derselben Swift-Datei, aber außerhalb der Klassendefinition definiert. Nicht wirklich sicher, was du meinst. Aber Sie können sehen, ich habe einen Filter innerhalb der 'cellForRowAtIndexPath' –

+0

Wenn ein 'UITableView' 'reloadData()' aufgerufen wird, wird es Informationen aus seiner 'UITableViewDataSource' aufrufen. Aus Ihrem Code sollte 'ActivityViewController' die DataSource von' self.tableView' sein. – aimak

Antwort

1

Das Problem ist die ActivityViewController().reloadtable() Anruf. Dies erstellt ein neues ActivityViewController jedes Mal Ihre Data Klasse Daten heruntergeladen. Es ist wichtig, dass Sie nur reloadtable() auf derselben ActivityViewController Instanz aufrufen, die bereits vorhanden ist (und die auf dem Bildschirm angezeigt wird).

Ein gut (einfach, aber einfach) Lösung mit der folgenden Refactoring wäre zu tun:

func check_demo_complete(completion:(Bool ->()){ 
    // your network call 
    dispatch_async(dispatch_get_main_queue()) { 
    if (responseString == "true") { 
     completion(true) 
    } 
    else { 
     completion(false) 
    } 
    // or, simpler : completion(responseString == "true") 
    } 
} 

Auf diese Weise durch check_demo_complete() aufrufen, müssen Sie einen Verschluss passieren verpflichtet hatte:

if (activity.title == "Demographics"){ 
    Data().check_demo_complete() { [weak self] success in 
    if success { 
     // change your textColors etc 
     self?.tableView.reloadData() 
    } 
    } 
} 

Auch dies ist eine grundlegende Lösung, die funktionieren sollte. Die wichtigste Lektion, die Sie lernen sollten, ist: Erstellen Sie keine neue Instanz von Klassen, wenn Sie sie benötigen.

+0

Heilige Sh * t es hat funktioniert. Ich danke dir sehr! Jetzt sehe ich nur, dass der Server-Aufruf wiederholt gemacht wird, ich brauche ihn nur einmal, aber ich kann es wahrscheinlich nicht von hier aus herausfinden. Du hast mir hier eine Technik gegeben, die WIRKLICH nützlich ist! –

+1

Das liegt daran, dass die Anfrage in 'cellForRow' erfolgt, was bedeutet, dass jedesmal eine Zelle angezeigt wird. – aimak

+0

Ja, das habe ich bemerkt, und dann ruft es auf, die Daten von innerhalb dieser Funktion neu zu laden ... Ist es möglich, die Tabelle von außerhalb der 'cellForRow' neu zu laden? –

Verwandte Themen