"Manager"-Design

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • "Manager"-Design

    Okay, der Titel ist wahrscheinlich etwas missverständlich :)
    Ich schreibe gerade an einer App die, wenn sie mal fertig ist, recht viel mit dem Internet bzw. einem Server kommunizieren muss, nicht nur um Daten zu senden sondern auch um welche zu "empfangen". Nun würde das in meinem Projekt recht viel redundanten Code verursachen, z.B. müssten an vielen Stellen an das gleiche Script eine Abfrage gestellt werden nur eben mit etwas anderen Parametern.
    Nun dachte ich mir, ich schreibe mir einfach eine Singleton-Klasse, die entweder Instanz-Methoden bkeommt (-(NSString*)...) oder noch einfacher Klassenmethoden (+(NSString*)....) bekommt und ich da z.B. mittels

    Quellcode

    1. {mySingleton getDataForParameter:....];
    drauf zugreifen kann und so den Code prima gekapselt habe.
    Da ich ja hier schon mehrfach "auf die Rübe bekommen habe" für das Vorschlagen der Verwendung eines SIngleton wollte ich nun einfach noch mal hören, was denn daran jetzt so doof ist und wie ich das am elegantesten lösen könnte :)
    Vielen Dank schon mal
    Tim

    p.s.: Bitte nicht hauen! ;D
  • Nein, auf keinen Fall ein Singleton, insbesondere mit einem Connection-Manager wird das nicht klappen.
    Ich würde das auch nicht mit einer category machen, sondern eine eigene Klasse verwenden.

    Diese hat eine property vom Typ NSData, in welcher die vom Server geladenen Daten wandern und gleichzeitig ist diese Klasse ihr NSURLConnection-delegate.
    Darüber hinaus kann auch diese Klasse ein eigenes Delegate haben, um z.B. Authentification-Geschichten an den Benutzer ins UI weiterzuleiten. Wenn Du 10.5 nicht mehr unterstützen musst, kannst Du eine Block-basierte API für den Rückruf wenn der Download beendet ist, verwenden.

    Für die Eingabeseite brauchst Du letztlich einen designated initializer (inkl zugehörigen conveniance allocator), der Dir eine URL entgegennimmt oder meinetwegen auch einen string oder einen Formatstring mit variabler Parameterliste. Allerdings würde ich versuchen, das interface auf das absolut nötigste zu beschränken (NSData als Ausgabe, NSURL als Eingabe). Die Erzeugung der URL kannst Du dann ins GUI oder einen weiteren CA verlagern und die Auswertung des NSData-streams kann dann eine andere Schicht übernehmen (z.B. eine Unterklasse/Kategorie für die diversen Ausgabetypen).

    Hoffe das hilft Dir ein bisschen, Gruß, Markus
  • er will aber alles in einem: script-path (NSString), parameter (NSDictionary), delegate (id) und eventuell noch action (SEL) rein schicken. sobald fertig geladen soll das ergebnis an den delegate geschickt werden. fertig.

    der controller soll sich dann um alles kümmern. auch fehlerbehandlung etc
  • Naja, dann braucht er eben einen entspr. CA, habe ich ja geschrieben.

    Trotzdem wird das mit einem Singleton nix. Apple löst in einem Beispiel so, dass sich das Objekt nachdem dem Laden selbst freigibt.
    Was er aber letztlich braucht ist eine weitere Klasse ConnectionPool, welche alle Connecion-Controller verwaltet (und über eine simple Schnittstelle zum Erzeugen neuer Downloads verfügt) und bei deren Beendigung freigibt. Somit kommt der client-code mit der ConnectionController-Klasse überhaupt nicht in Berührung und verwendet ausschließlich ConnectionPool.
  • Markus Müller schrieb:

    Naja, dann braucht er eben einen entspr. CA, habe ich ja geschrieben.

    Trotzdem wird das mit einem Singleton nix. Apple löst in einem Beispiel so, dass sich das Objekt nachdem dem Laden selbst freigibt.
    Was er aber letztlich braucht ist eine weitere Klasse ConnectionPool, welche alle Connecion-Controller verwaltet (und über eine simple Schnittstelle zum Erzeugen neuer Downloads verfügt) und bei deren Beendigung freigibt. Somit kommt der client-code mit der ConnectionController-Klasse überhaupt nicht in Berührung und verwendet ausschließlich ConnectionPool.


    der singleton fasst doch die ganzen connections zusammen. man braucht ja nicht für jede connection einen controller.
    aber egal - jeder wie er will ;)
  • Danke Markus für diese ausführliche Beratung! Ich würde das dann wie folgt machen:
    Ich schreibe mir eine "Fetcher"-Klasse, die sämtliche Connections und so weiter handelt inklusive einiger enums. Ich werde mich vermutlich dann auf einen COnstructor beschränken dem eine der Enums mitgegeben wird (je nachdem was gemacht werden soll) und ein NSDictionary o.ä. gefüllt mit zu sendenden Parametern. In meinen ViewControllern wird ein Objekt dieser Klasse dann erzeugt (und wegen ARC auch zwangsweise in einer ivar gespeichert werden...) und dann wird bei Beendigung des Ladevorgangs einfach eine Delegate-Methode aufgerufen. Wie handelt man das am besten mit dem "selbst release"? Vor allem mit ARC?
  • Man kann das sicher irgendwie mit einem Singleton hinhacken, allerdings fängt es schon bei der Unterscheidung der einzelnen Connections im NSURLConnectionDelegate an, eklig zu werden. Threading ist ebenfalls ein Alptraum mit einem Singleton. Daher: jede connection bekommt einen, leichtgewichtigen, eigenen Controller. Somit hast Du ganz glasklare Zuständigkeiten.

    Die einzelnen Connection-Instanzen werden von einer Klasse ConnectionPool verwaltet, wenn ein Download beendet ist, werden die entspr. callbacks mittels einer NSOperationQueue ausgeführt und die Connection-Instanz schlussendlich entfernt.

    Der Client-Code erzeugt eine Instanz von ConnectionPool und wickelt alle downloads darüber ab. Keinerlei Notwendigkeit für ein Singleton...

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Markus Müller ()

  • und wenn du von 10 verschiedenen orten das verwenden willst, musst du auch irgendwie an den ConnectionPool kommen. wenn der ein singelton wäre, hätte mans einfach ;) ob der dann connection-controller verwaltet oder selbst alles macht ist ja komplett wurscht... aber da es eben nur EINEN connection-pool geben sollte (sag ich jetzt mal) bietet sich ein singelton ja an.
  • @TE
    Ein Bild sagt mehr als tausend Worte:
    Im Anhang ein klitzekleines Beispielprojekt, schnell hingeschrieben. Ist zwar eine Mac-Applikation aber das dürfte alles so wie es ist auch unter iOS laufen (falls nicht, einfach anpassen :) )

    @gritsch
    Nein, auch dann brauchst Du kein Singleton, Du kannst ja die ConnectionPool Instanz herumreichen wo sie gebraucht wird, bzw. in properties in den jeweiligen Controllern vorhalten. Es spricht auch nichts dagegen, einfach mehrere solche zu haben.

    Gruß, Markus
  • Markus Müller schrieb:

    @TE
    Ein Bild sagt mehr als tausend Worte:
    Im Anhang ein klitzekleines Beispielprojekt, schnell hingeschrieben. Ist zwar eine Mac-Applikation aber das dürfte alles so wie es ist auch unter iOS laufen (falls nicht, einfach anpassen :) )

    @gritsch
    Nein, auch dann brauchst Du kein Singleton, Du kannst ja die ConnectionPool Instanz herumreichen wo sie gebraucht wird, bzw. in properties in den jeweiligen Controllern vorhalten. Es spricht auch nichts dagegen, einfach mehrere solche zu haben.

    Gruß, Markus


    sicher kann man. ich kann mich über 5 controller hangeln um dann irgendwo von irgendeinem controller den pool bekomme. beim singleton kümmern mich die ganzen controller zwischendrin aber nicht und auch nicht zu welchem zeitpunkt in welchlem controller der pool erstellt wird...
    aber egal. zeit die augen zu zu machen ;)