10

Vor zwei Monaten begann ich eine neue iPhone Anwendung zu schreiben und aus diesem Grund habe ich einen generischen RESTFul Web Service erstellt, der mir viele dieser notwendigen Funktionen wie Benutzerauthentifizierung, Benutzerprofile, a Freundschaftssystem, Medienverarbeitung, ein Nachrichtensystem und so weiter. In meinen Augen gibt es mehrere Anwendungsfälle, um diesen Webservice für zukünftige iPhone-Anwendungen wiederzuverwenden.iOS App Architektur mit NSOperationen

Mit dieser Geisteshaltung entschied ich mich, eine statische Bibliothek für diese Anwendung (und alle zukünftigen Anwendungen) zu schreiben, die alle schweres wie Medien (Bild, Video, Sound) einrichten und verarbeiten, mit dem Webdienst kommunizieren , Parsing und Mapping der Ergebnisse, Umgang mit CoreData und so weiter.

Angesichts meiner Anwendung gibt es Szenarien, wenn viele parallele Aufgaben ausgeführt werden (schlimmsten Fall) z. der Benutzer ändert derzeit sein Profilbild, während die Anwendung den Standort des Benutzers an den Server sendet (im Hintergrund) und eine neue Push-Benachrichtigung empfangen wird.

Also beschlossen, jede logische Operation (wie SendUserLocation oder GetCurrentFriendList) in einer NSOperation zu verkapseln und sie zu einer serviceQueue (NSOperationQueue) hinzuzufügen.

Jede Operation ist in der Lage, Subtasks zu erzeugen, wenn der Vorgang erfolgreich vom Webservice ausgeführt wurde und jetzt verarbeitet werden soll.

alt text

Ein typischer Servicemanager Verfahren sieht wie

- (void)activateFriendsSync:(id)observer onSuccess:(SEL)selector { 
    ELOSyncFriends *opSyncFriends = [[ELOSyncFriends alloc] initWithSM:self]; 
    [self ELServiceLogger:opSyncFriends]; 
    [serviceQueue addOperation:opSyncFriends]; 
    if(observer) { 
     [self registerObserver:observer selector:selector name:opSyncFriends.notificationName]; 
    } 
} 

Jede Operation, Anforderung (zum Server) und Subtask wird ein GUID als notificationName des übergeordnete Objekt zu benachrichtigen, wenn es die Verarbeitung fertig ist. Wenn alles in einer Operation abgeschlossen ist, sendet es eine Benachrichtigung zurück an die Benutzerschnittstelle.

Das hieß, der Code zum Hinzufügen und Entfernen von Teilaufgaben wie folgt aussieht

- (void)removeSubTask:(NSNotification*)notification { 
    ELRequest *request = (ELRequest*)[notification object]; 
    [subTasks removeObjectIdenticalTo:request.notificationName]; 
    if([subTasks count] == 0) { 
     // all SubTaks done, send notification to parent 
     [serviceManager.notificationCenter postNotificationName:self.notificationName object:request]; 
    } 
} 

- (NSString*)addSubTask { 
    NSString* newName = [self GetUUID]; 
    [subTasks addObject:[newName retain]]; 
    [serviceManager.notificationCenter addObserver:self selector:@selector(removeSubTask:) name:newName object:nil]; 
    return newName; 
} 

- (NSString *)GetUUID { 
    CFUUIDRef theUUID = CFUUIDCreate(NULL); 
    CFStringRef string = CFUUIDCreateString(NULL, theUUID); 
    CFRelease(theUUID); 
    return [(NSString *)string autorelease]; 
} 

Jetzt alles, was ich zu tun habe ist den servicemanager in meiner gui nennen eine bestimmte Operation zu starten, wie

[self.core.serviceManager activateFriendsSync:nil onSuccess:nil]; 

Wenn ich einen Beobachter registrieren will, muss ich Objekt nur einen Beobachter passieren und einen Selektor wie diese

[self.core.serviceManager activateFriendsSync:self onSuccess:@selector(myMethod:)]; 

Last but not least meine Frage (n): Die "Architektur" läuft sehr gut und stabil, aber ist es das wert? Schafft es zu viel Aufwand? Macht es überhaupt Sinn? Wie implementieren Sie persönlich gleichzeitige Operationen?

Beste Henrik

P. S. Fühlen Sie sich frei, meine Frage zu bearbeiten, Fragen (als Kommentar) zu stellen, nennen Sie mich Namen für dieses Denken.

Ich hatte es wirklich schwer zu erklären, im Grunde, weil ich kein englischer Muttersprachler bin. Versteh mich nicht falsch. Ich habe diesen Beitrag nicht geschrieben, um ihn zu zeigen.Alles, was ich tun möchte, ist lernen (und vielleicht auch eine fortgeschrittenere iphone/Objective-C Frage zu schreiben)

Antwort

1

Sie haben gerade eine sehr ähnliche Architektur beschrieben, die ich verwende in einigen meiner apps :)

ich habe Schicht mein Service-Manager eine Reihe von Objekten sofort zurückkehren und dann ein aktualisierter Satz Rückkehr nach einer Weile, dh

NSArray *stuff = [serviceManager getFriendsForUser:@"Bob"]; 

und dann, nachdem der Server geantwortet hat, ein NSNotification empfangen wird, dass enthält eine aktualisierte Liste (von Freunden für Bob in diesem Fall).

Abgesehen von dieser winzigen Änderung ist Ihre Architektur die gleiche!

Es ist ziemlich viel Arbeit, um alles einzurichten, aber ich denke, es lohnt sich auf lange Sicht, da das Beheben von Fehlern/die Erweiterung des Codes viel einfacher ist.

+0

Hallo Dean, danke deine Erkenntnisse. –

4

ja, wenn es zu Serviceanforderungen bearbeitet wird und Sie viele Aufrufe zu machen haben, dann ist eine solche Bibliothek nicht (imo) übertrieben, und ich habe etwas Ähnliches geschrieben. Diese Struktur hat es mir sehr leicht gemacht, ein komplexes System mit sehr komplexen und vielfältigen Aufgaben zu verwalten.

der primäre Entwurfsunterschied, den ich machte, war nicht NSNotification mit einem Service Manager zu verwenden. stattdessen bevorzugte ich die Verwendung von Protokollen/Typen für Rückrufe (auf die die Operation Bezug nimmt). NSNotification ist ziemlich schwer. In diesem Fall behält die Operation die Listener/Benachrichtigten Objekte nicht bei, aber die Listener behalten die Operation bei. Wenn die Beziehung 1-1 ist, dann annuliere die Löschung.

eine andere wichtige Überlegung ist, Threading früh zu definieren. Erlaube Clients zu definieren, auf welchen Thread sie ihre Antwort erhalten möchten. Der Grund hierfür ist, dass es häufig eine Einschränkung oder einen logischen Eintrag für den Rückruf gibt, wenn der benachrichtigte/Listener die Benutzeroberfläche aktualisieren muss (z. B. UIKit oder AppKit verwenden). Daher kann der Ersteller zu der Operation "Sie müssen mich über den Hauptthread informieren" oder "Ich kann die Antwort von jedem Thread verarbeiten" sagen. Dies wird Ihren Controller/Listener/Observer-Code und die Chance auf Fehler stark reduzieren.

2

Für „sub-Operationen“: was ist mit ihnen auf die Warteschlange, mit dem übergeordneten Betrieb genommen eine Abhängigkeit (vgl -[ NSOperation addDependency: ]) jedes seiner untergeordneten Operationen zu sein? Die NSOperationQueue kann Ihren gesamten Stapel von Vorgängen für Sie sequenzieren. Ich denke, dass es einfach und natürlich ist, damit zu arbeiten.

Verwandte Themen