Frage zu NSURLConnection sendAsynchronousRequest

C

Carlie

Aktives Mitglied
Thread Starter
Dabei seit
26.05.2006
Beiträge
255
Reaktionspunkte
11
Hallo,

seid einigen Tagen sitze ich über folgendem Problem, und verstehe nicht wo sich der fehler eingeschlichen hat. Zur Problematik. Wenn der View geladen wird, werden keine daten abgerufen und angezeigt. Erst wenn ich die refresh funktion benutze, werden die Daten abgerufen und auch angezeigt. Kann mir jemand einen Tipp geben. Ich stehe auf dem Schlauch und weiß nicht weshalb die Daten beim ersten anzeigen nicht abgerufen werden.

Code:
- (void)updateItems {
    
    NSString *ergbnisseURL = @"Web Seite";
    NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:ergbnisseURL]];
    [NSURLConnection sendAsynchronousRequest: theRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *allCoursesData, NSError *error) {
        if (allCoursesData == nil) {
            NSLog(@"error = %@", error);
        }
        else {
            NSError *error;
            self.alleErgebnisse = [NSJSONSerialization
                                   JSONObjectWithData:allCoursesData
                                   options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves
                                   error:&error];
            
            self.heim1 = self.alleErgebnisse[@"Heim1"];
            self.gast1 = self.alleErgebnisse[@"Gast1"];
            self.ergebniss1 = self.alleErgebnisse[@"Ergebniss1"];
            self.heim2 = self.alleErgebnisse[@"Heim2"];
            self.gast2 = self.alleErgebnisse[@"Gast2"];
            self.ergebniss2 = self.alleErgebnisse[@"Ergebniss2"];
            self.heim3 = self.alleErgebnisse[@"Heim3"];
            self.gast3 = self.alleErgebnisse[@"Gast3"];
            self.ergebniss3 = self.alleErgebnisse[@"Ergebniss3"];
            self.heim4 = self.alleErgebnisse[@"Heim4"];
            self.gast4 = self.alleErgebnisse[@"Gast4"];
            self.ergebniss4 = self.alleErgebnisse[@"Ergebniss4"];
            self.heim5 = self.alleErgebnisse[@"Heim5"];
            self.gast5 = self.alleErgebnisse[@"Gast5"];
            self.ergebniss5 = self.alleErgebnisse[@"Ergebniss5"];
            self.heim6 = self.alleErgebnisse[@"Heim6"];
            self.gast6 = self.alleErgebnisse[@"Gast6"];
            self.ergebniss6 = self.alleErgebnisse[@"Ergebniss6"];
            self.heim7 = self.alleErgebnisse[@"Heim7"];
            self.gast7 = self.alleErgebnisse[@"Gast7"];
            self.ergebniss7 = self.alleErgebnisse[@"Ergebniss7"];
            self.heim8 = self.alleErgebnisse[@"Heim8"];
            self.gast8 = self.alleErgebnisse[@"Gast8"];
            self.ergebniss8 = self.alleErgebnisse[@"Ergebniss8"];
            self.heim9 = self.alleErgebnisse[@"Heim9"];
            self.gast9 = self.alleErgebnisse[@"Gast9"];
            self.ergebniss9 = self.alleErgebnisse[@"Ergebniss9"];
            self.heim10 = self.alleErgebnisse[@"Heim10"];
            self.gast10 = self.alleErgebnisse[@"Gast10"];
            self.ergebniss10 = self.alleErgebnisse[@"Ergebniss10"];
            self.heim11 = self.alleErgebnisse[@"Heim11"];
            self.gast11 = self.alleErgebnisse[@"Gast11"];
            self.ergebniss11 = self.alleErgebnisse[@"Ergebniss11"];
            self.heim12 = self.alleErgebnisse[@"Heim12"];
            self.gast12 = self.alleErgebnisse[@"Gast12"];
            self.ergebniss12 = self.alleErgebnisse[@"Ergebniss12"];
            self.heim13 = self.alleErgebnisse[@"Heim13"];
            self.gast13 = self.alleErgebnisse[@"Gast13"];
            self.ergebniss13 = self.alleErgebnisse[@"Ergebniss13"];
            self.heim14 = self.alleErgebnisse[@"Heim14"];
            self.gast14 = self.alleErgebnisse[@"Gast14"];
            self.ergebniss14 = self.alleErgebnisse[@"Ergebniss14"];
            self.heim15 = self.alleErgebnisse[@"Heim15"];
            self.gast15 = self.alleErgebnisse[@"Gast15"];
            self.ergebniss15 = self.alleErgebnisse[@"Ergebniss15"];
            self.heim16 = self.alleErgebnisse[@"Heim16"];
            self.gast16 = self.alleErgebnisse[@"Gast16"];
            self.ergebniss16 = self.alleErgebnisse[@"Ergebniss16"];
            self.heim17 = self.alleErgebnisse[@"Heim17"];
            self.gast17 = self.alleErgebnisse[@"Gast17"];
            self.ergebniss17 = self.alleErgebnisse[@"Ergebniss17"];
            self.heim18 = self.alleErgebnisse[@"Heim18"];
            self.gast18 = self.alleErgebnisse[@"Gast18"];
            self.ergebniss18 = self.alleErgebnisse[@"Ergebniss18"];
            self.heim19 = self.alleErgebnisse[@"Heim19"];
            self.gast19 = self.alleErgebnisse[@"Gast19"];
            self.ergebniss19 = self.alleErgebnisse[@"Ergebniss19"];
            self.heim20 = self.alleErgebnisse[@"Heim20"];
            self.gast20 = self.alleErgebnisse[@"Gast20"];
            self.ergebniss20 = self.alleErgebnisse[@"Ergebniss20"];
            self.heim21 = self.alleErgebnisse[@"Heim21"];
            self.gast21 = self.alleErgebnisse[@"Gast21"];
            self.ergebniss21 = self.alleErgebnisse[@"Ergebniss21"];
            self.heim22 = self.alleErgebnisse[@"Heim22"];
            self.gast22 = self.alleErgebnisse[@"Gast22"];
            self.ergebniss22 = self.alleErgebnisse[@"Ergebniss22"];
            self.heim23 = self.alleErgebnisse[@"Heim23"];
            self.gast23 = self.alleErgebnisse[@"Gast23"];
            self.ergebniss23 = self.alleErgebnisse[@"Ergebniss23"];
            self.heim24 = self.alleErgebnisse[@"Heim24"];
            self.gast24 = self.alleErgebnisse[@"Gast24"];
            self.ergebniss24 = self.alleErgebnisse[@"Ergebniss24"];
            self.heim25 = self.alleErgebnisse[@"Heim25"];
            self.gast25 = self.alleErgebnisse[@"Gast25"];
            self.ergebniss25 = self.alleErgebnisse[@"Ergebniss25"];
            
        }
    }];
    [self.tableView reloadData];
    [self.refreshControl setTintColor:[UIColor colorWithRed:0.000 green:0.000 blue:0.630 alpha:1.000]];
    //[self setRefreshControl: self.refreshControl];
    [self performSelector:@selector(stopRefresh) withObject:nil afterDelay:3];
    [self.refreshControl endRefreshing];
    

}

Die Methode rufe ich mit [self updateItems] in der ViewDidLoad auf.
 
Ich habe nicht genau verstanden was Du mit "wenn ich die refresh Funktion aufrufe" meinst.
Aber:

viewDidLoad wird aufgerufen wenn alle Objekte fertig miteinnader verbunden sind.
Egal ob man XIB, Storyboard oder von Hand im ViewController programmiert.

ABER: Keine der Views muss sichtbar sein. Du kannst ViewController und Views im Voraus laden, wenn Du magst.

Was Du suchst ist "viewDidAppear".

Ein Tableview kümmert sich erst um seine Daten wenn er Teil einer "angezeigten" View Hierarchie ist.

Du solltest also die Daten in "viewDidLoad" laden und in "viewDidAppear" den tableView reload ausführen.

Mal davon abgesehen würde ich diese Methoden nicht so verdrahten.
Ich benutze generelle Controller (einfaches NSObject, die sich mit dem ViewController und den Daten "unterhalten".

Diese Controller verwalte ich im AppDelegate.
Die kennen die ViewController und die Datenmodelle.

Wenn ich diese Controller im AppDelegate vorhalte, kümmern diese sich um die "Lebensdauer" ihrer ViewController und Daten.
Es ist durchaus sinnvoll ViewController vorzuhalten um nicht aus dem AppDelegate alles neu zu laden.

Aber egal, dazu ist zu wenig Code da.
 
Hallo,

erst einmal danke für deine Antwort. Ich habe schnell gemerkt das ich die Methode viewDidAppear noch anlegen muss (war mir als Anfänger so nicht bewusst). Habe diese Methode geschrieben und generell den Code an einigen stellen abgändert. Netzwerkabfragen, AlertView usw mit eingebaut. Auf jeden fall scheint jetzt die abfrage zu funktionieren. Aber eine frage hätte ich noch, bezüglich der ladezeiten. Das JSON Dokument welches ich abrufe ist ca 8 KB groß. Außer bei 3G verbindung, dauert das laden der Daten sehr lange (bis 15 sec.). Leider habe ich noch keine erfahrungswerte. Aber es erscheint mir für eine so kleine Datei eine sehr lange zeit zu sein. Weiter ist mir aufgefallen das Eine Zweite JSON datei mit 10 KB immer schneller abgerufen/angezeigt wird. An was kann so etwas liegen?
 
Das ist ein generelles Problem der Latenz und der Round-Trip-Time.
Der Verbindungsaufbau dauert immer lange und auch das hin und her der Daten.
Wenn der Request einmal gesendet ist, sollte die länge der JSON Datei kaum ins Gewicht fallen.

Das die zweite Datei schneller ist liegt daran, dass iOS die Verbindung mit Keep-Alive aufhält.
Deshalb entfällt der Aufbau bei jedem Folgerequest.

Der Punkt der asynchronen Verbindungen ist ja eben, dass man während die Daten laden noch mit der App arbeiten kann.
Du solltest die Daten lokal vorhalten und eben im Hintergrund aktualisieren.

Du wirst vermutlich feststellen, dass die App so gut wie nur wartet, indem Du vor der NSURLConnection und in den completion block mal eine Ausgabe mit Zeit hängst.

Es ist eben nicht so, dass man "einfach nur" die Daten holt wenn man sie anzeigen möchte.
Um eine gute interaktive App zu schreiben muss man sich schon ein paar Gedanken machen.

Der asynchrone Teil bringt Dir im Moment ja relativ wenig, da der TableView halt leer ist.

Zum Abschluss eine kleine Anmerkung.
Es sieht schlimm wie Du die JSON Elemente in die ganzen Properties kopierst.
Das ist doch nicht nötig, JSON stellt Dir doch eine Map- bzw. Listenabstraktion zur Verfügung.
Das aber nur am Rande.

Code:
self.heim21 = self.alleErgebnisse[@"Heim21"];
self.gast21 = self.alleErgebnisse[@"Gast21"];
self.ergebniss21 = self.alleErgebnisse[@"Ergebniss21"];

Sowas ist furchtbar.

EDIT:

Das Du eine JSON Map mit "Heim21" und "Gast21" als key hast, sieht auch schon komisch aus.
Zeig doch mal das JSON oder schick mir die URL als BM.
Ich kill auch nicht den Server.
 
Erst noch mal was grundsätzliches. Ich habe vor ca 4 Monaten erst mit Object-C begonnen. Deine Kritik werde ich natürlich aufnehmen. Aber genau dieser Punkt, ist denke ich als Anfänger mit eines der größten probleme. Ich kann absolut nicht einschätzen wie gut oder schlecht der geschrieben Code ist. Ich Orientiere mich an Podcasts, Appe Doku und Bücher. Aber aller anfang ist nun mal schwer. Gerade aus diesem Blickwinkel nochmals danke für deine ausführliche erklärung. Ich habe jetzt mehrere dinge nochmals auf meine Bug Liste geschrieben. Ich werde mir auf jeden fall das Thema noch intensiver anschauen, wie ich hier daten vorhalten kann um hier die wartezeit angenehmer zu gestalten.

Du hast mir auf jeden fall weitere Denkanstöße gegeben.

Zu JSON selbst muss ich noch sagen, das ich davon bis vor 14 tagen null ahnung hatte. In meinen Büchern ist das gar nicht erklärt (sondern nur XML) und bei Apple selbst habe ich auch nicht wirklich viel gefunden.
Und das kommt dann eben dabei heraus. Aber auch dies werde ich mir nochmals anschauen.

Eine JSON Datei schicke ich dir per Mail.
 
Oh, das sollte keine Kritik sein.

Ich habe aus Langeweile ne kleine App nachprogrammiert, so ähnlich wie Du sie geschrieben hast.
Wenn ich sie in bisschen poliert habe schick ich Dir einen Link.

Nur mal als Anregung:

Nimm doch ein JSON Array mit Dictionaries als Elemente für ein Spiel:

Code:
[ {"Heim" : "Mannschaft A",
    "Gast" : "Mannschaft B", 
    "Ergebnis" : [0, 1, 0, 3] // Tore Heim, Tore Gast, Punkte Heim, Punkte Gast
  },
  {"Heim" : "Mannschaft A",
    "Gast" : "Mannschaft B", 
    "Ergebnis" : [0, 1, 0, 3] // Tore Heim, Tore Gast, Punkte Heim, Punkte Gast
  }
]

Dann ist die Anzahl der Array Elemente 'gamedata.count' gleich der UITableView Rows.
Du brauchst dann nur mit 'dict = [gameData objectAtIndex:[indexPath row]]' das dictionary holen.

Dann kannst Du eine UITableViewCell mit den keys befüllen.

Die Spaces gehören natürlich nicht ins JSON.

Ich schrein Dir mal was. Vermutlich bis morgen. Kannst Du dann als ZIP downloaden.
 
Vielleicht war Kritik auch das falsche wort, und ich sollte stattdessen eher hilfestellung sagen. Aber wie gesagt, das ist vollkommen OK. Denn zum ersten mal hat mir jemand geschrieben wie man es besser Coden kann. Ich bin darüber sehr froh und auch dankbar.
Das ich viel zu umständlich den Code aufgebaut habe, sehe ich jetzt auch. Ich werde die nächste Tage auf jeden fall nochmals einiges an Arbeit investieren müssen um den Code hier etwas zu vereinfachen. Auch das Thema mit den Daten Vorhalten muss ich mir anschauen. Gibt es zu diesem Thema von Apple eine Doku?
 
Zurück
Oben Unten