2016-01-05 3 views
0

J'ai essayé de comprendre cela maintenant pendant un moment. Je pense que j'ai épuisé toutes les options de recherche, alors je vous le dis, piaulez.Affichage de l'indicateur d'activité sur TableView avec programmation asynchrone - Swift

J'ai une vue de table qui se connecte à une vue Web. La vue Web dessine une carte, parfois avec des milliers de coordonnées, de sorte que le temps de chargement peut parfois être un peu long, évidemment en fonction du périphérique de l'utilisateur. Donc, je veux brancher un indicateur d'activité pour laisser l'utilisateur savoir que l'application n'a pas planté.

J'ai donc créé l'indicateur d'activité par programme, et l'ai configuré pour l'activer sur didSelectRowAtIndexPath. Le problème ici est que l'indicateur ne commence pas à montrer jusqu'à ce que la tâche soit terminée - et quel est le point de l'indicateur alors. Donc, je comprends que la solution ici est de le faire de manière asynchrone, mais la solution que j'ai essayé n'a aucun effet. J'ai essayé de brancher le code dans la fonction prepareForSegue, mais c'est encore pire - il se place dans la vue de la carte avant le chargement des données, affichant ainsi une carte vierge.

Toute aide ici? Voici mon code. Merci!

class MapSelect: UITableViewController { 

    let subdivisionArray = [There's an array here] 

    let selectionArray = [There's an array here] 

    let model = Model() 
    var myView = UIView() 
    var activityIndicator = UIActivityIndicatorView() 


    override func viewDidLoad() { 
     super.viewDidLoad() 

     self.navigationController?.navigationBarHidden = false 

     myView = UIView(frame: CGRectMake(0, 0, self.tableView.frame.size.width, self.tableView.frame.size.height)) 
     myView.backgroundColor=UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1.0) 
     myView.alpha = 0.0 
     UIView.animateWithDuration(1.0, animations: {() -> Void in 
      self.myView.alpha = 0.5 
     }) 
     self.view.addSubview(myView) 
     activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge) 
     activityIndicator.startAnimating() 
     activityIndicator.center = CGPointMake(self.tableView.frame.size.width/2, self.tableView.frame.size.height/2) 
     self.tableView.addSubview(activityIndicator) 
     self.stopSpinner() 


    } 

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


    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 

     return subdivisionArray.count 
    } 

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

     cell.textLabel?.font = UIFont.boldSystemFontOfSize(18) 
     cell.textLabel?.text = subdivisionArray[indexPath.row] 

     return cell 
    } 

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) 
    { 
     if subdivisionArray[indexPath.row] != "County" { 
      performSegueWithIdentifier("toMapSelect2", sender: self) 
     } else { 

      self.spinner() 

      let seconds = 0.1 
      let delay = seconds * Double(NSEC_PER_SEC) // nanoseconds per seconds 
      let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay)) 
      dispatch_after(dispatchTime, dispatch_get_main_queue(), { 

        self.performSegueWithIdentifier("toMapView", sender: self) 

      }) 
      self.stopSpinner() 

     } 

    } 

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { ... } 

    func spinner() { 
     myView.hidden = false 
     myView.alpha = 0.0 
     UIView.animateWithDuration(1.0, animations: {() -> Void in 
      self.myView.alpha = 0.5 
     }) 
     activityIndicator.startAnimating() 
     activityIndicator.hidden = false 
    } 

    func stopSpinner() { 
     myView.hidden = true 
     activityIndicator.stopAnimating() 
     activityIndicator.hidden = true 
    } 

} 

Voici également le code qui charge la carte à la vue Web dans une « classe MapView » séparée:

override func viewDidLoad() { 
     super.viewDidLoad() 


     do { 
      if prevSelectionType == "ed" { 
       prevSelectionLabel = prevSelection 
       prevSelection = model.decodeElectionDistrict(prevSelection) 
      } else { 
       prevSelectionLabel = prevSelection 
      } 

     } 

     var regionEds : Array<String> = Array<String>() 

     do { 
      var pred : NSPredicate 
      pred = NSPredicate(format: "region = %@", "") 
      if prevSelectionType != "county" { 
       if prevSelectionType != "ed" { 
        pred = NSPredicate(format: "region = %@" , prevSelection) 
       } else { 
        pred = NSPredicate(format: "ed = %@" , prevSelection) 
       } 
       requestPick3.predicate = pred 
      } 
      requestPick3.resultType = NSFetchRequestResultType.DictionaryResultType 
      requestPick3.propertiesToFetch = ["ed"] 
      requestPick3.returnsDistinctResults = true 
      let resultsPre = try context.executeFetchRequest(requestPick3) 
      for result in resultsPre { 
       let resultEd : String = result["ed"] as! String 
       regionEds.append(resultEd) 
      } 
     } catch { 
      print("Error") 
     } 

     self.mapView.delegate = self 

     var dCoords : Array<Double> = Array<Double>() 
     var twdString : String = String() 
     var query : PFQuery = PFQuery() 
     do { 
      if prevSelectionType != "county" { 
       let predicate = NSPredicate(format:"twd IN %@", regionEds) 
       query = PFQuery(className: "Coords2016", predicate: predicate) 
      } else { 
       query = PFQuery(className: "Coords2016") 
      } 
      query.limit = 1000 
      let userArray = try query.findObjects() 
      //   print(userArray) 
      for item in userArray { 
       dCoords = item["coords"] as! Array<Double> 
       twdString = item["twd"] as! String 
       twdString = model.twdToEdAbbrev(twdString) 
       addBoundry(dCoords, twd: twdString) 
      } 

     } catch { 
      print("Error") 
     } 

     // DEFINE CENTER LOCATION 
     let initialLocation = CLLocation(latitude: centerLat, longitude: centerLong) 

     // DEFINE ZOOM SIZE 
     centerMapOnLocation(initialLocation) 

     toggleSwitch.setOn(false, animated: true) 

    } 
+0

pourquoi ne pas mettre l'indicateur sur votre MapView? Et dans votre MapViewController, cachez d'abord le webview, montrez l'indicateur, et après que le webview a fini de charger, montrez-le et cachez l'indicateur. – Surely

+0

J'irais certainement pour cette solution si je pouvais (et peut-être je peux, si je peux comprendre dehors). Le problème est que l'écran se bloque sur la tableview tout en croquant les données de coordonnées - et je ne sais pas exactement pourquoi, puisque tout ce travail est fait dans MapViewController. –

+0

pouvez-vous poster votre code webview, juste la partie pour charger l'URL. Je pense que vous pouvez essayer de placer la partie load url à viewDidAppear de votre contrôleur MapView. – Surely

Répondre

0

le problème avec votre code est que vous commencez la fileuse, puis arrêtez nouveau presque immédiatement, et certainement avant tout le travail a terminé

vous devez mettre tout le travail dans une file d'attente d'arrière-plan, mais tout ce qui met à jour l'interface utilisateur doit être fait dans la file d'attente principale

dispatch_async(dispatch_get_main_queue(), { 
    self.spinner() 
}) 

puis plus tard

dispatch_async(dispatch_get_main_queue(), { 
    self.updateMapInSomeWay() 
}) 

Si vous le faites comme ça, vous n'avez pas besoin de déconner avec 0.1s retards avant de commencer

Voici un bon tutoriel pour vous aider à démarrer sur traitement en arrière-plan http://www.raywenderlich.com/92428/background-modes-ios-swift-tutorial