#035 Cheddar: Delegates und Timer (66:01 Minuten)

#035 Cheddar: Delegates und Timer
Diesmal erzeugen wir eine Ausgabe in der Benutzeroberfläche, während der SyncManager arbeitet. Der Benutzer des Programms erhält also erstmals eine Rückmeldung darüber, was das Programm gerade im Hintergrund macht.
Hilfsmittel sind dabei selbstgeschriebene Delegates, dynamische Methodenaufrufe anhand von Selektoren und eine neue Cocoa-Klasse: NSTimer.
Und wer nicht weiss, wovon wir reden, es aber erfahren möchte, der sollte diese Mammutfolge anschauen...!

Delegates hatten wir übrigens auch schon in diesen Folgen erklärt:
  • #011: Hello iPhone!
  • #019: NSTableView mit Leben befüllen
    Selektoren erklären wir unter Anderem in der Folge #031 Cheddar: Threading, wo wir einen Selektor zum Starten des Threads benutzen.

    Ihr bekommt den Quellcode zu dieser Folge in unserem SVN-Repository direkt aus Xcode heraus unter "releases/episode_035", oder am Terminal mit:
    svn checkout https://cheddar1.svn.sourceforge.net/svnroot/cheddar1/releases/episode_035
    Mehr Infos zum Thema in den Artikeln Subversion: Quellcodes zu den Episoden direkt in Xcode und Subversion und Xcode!
    13 Kommentare | Permalink | Trackback-Info | Film in HD ansehen!

  • Anzeige / Partnerlink

    Kommentar hinzufügen

     
    Name:
    Email (optional):
    Text:
    Sicherheitscode:
    Bitte geben Sie hier die unten abgebildete 5-stellige Zahl aus dem Bild ein!
    Um die 1 besser von der 7 unterscheiden zu können, hat die 1 unten immer einen waagerechten Strich.

    13. Unbedeutender Kommentator am 25. Mar 2010, 00:22 Uhr

    @ingo:
    Nochmal zum Thema id vs. NSObject. Dass der Compiler bei id nicht die Methodennamen checkt, ist eine sehr schwache Ausrede. Erstens checkt der Compiler natürlich auch bei id die Methodennamen und zweitens umgeht Ihr diesen Check sowieso durch die Verwendung von performSelector... Methoden.

    12. Bastian am 24. Mar 2010, 19:03 Uhr

    @Pennywise Nachteil an int* anIntPtr ist, dass folgendes Statement
    int* anIntPtr, anInt;
    impliziert, dass man zwei Int-Pointer allokiert, wobei man in Wirklichkeit ein Int und ein Int-Pointer allokiert. Das Statement ist also äquivalent zu:
    int anInt, *anIntPtr;
    Logisch gehört der Stern also zum Variablenname und nicht zum Typ. (Diese Problematik ist allerdings eher C im Allgemeinen anzulasten als unseren Podcastern oder dem großen Apfel)

    Stimmt schon, in der GUI-Programmierung kommt das eher nicht zum Einsatz, aber ich arbeite zum Beispiel gerade an einem Programm, das Core Audio benutzt und da gehts wieder heiß her mit Typecasting und Pointer-gewedel.

    11. Pennywise81 am 24. Mar 2010, 08:39 Uhr

    @jemand:
    int-Pointer sind nichts Außergewöhnliches. Dahinter muss sich nicht zwingend ein Objekt befinden, sondern vielleicht ein C-Array oder eine Referenz auf eine Variable.
    Oder man steppt einfach durch den Speicher.

    Allerdings ist sowas bei High-Level-GUI-Programmierung eher selten im Einsatz.



    Ansonsten kann ich Bastians Kritik nur beipflichten. Man sollte schon versuchen eine einheitliche Schreibweise zu verwenden, wobei das jetzt auch kein Killerkriterium ist. Ich wäre allerdings eher für die Schreibweise int* aIntPointer, was aber wohl eher an meiner Gewohnheit und der Coding-Guideline auf meiner Arbeit liegt ;)

    10. jemand am 23. Mar 2010, 22:56 Uhr

    Ein int als Object-Zeiger?

    9. Bastian Bechtold am 23. Mar 2010, 15:03 Uhr

    Super Podcast, den ihr da macht!

    Aber eine Sache stört mich schon ganz lange: Mal schreibt ihr
    NSTextField* aTextField; // oder auch:
    NSTextField *aTextField; // oder sogar:
    NSTextField * aTextField;

    Ich weiß, das sind Kleinigkeiten, aber es macht den Code unübersichtlicher. Ich persönlich bin für
    NSTextField *aTextField;
    Weil der Stern nur für die eine Variable gilt und somit folgender Ausdruck mehr Sinn macht
    int *anIntPtr, anInt;

    Liebe Grüße,
    Basti

    8. Jixxwar am 22. Mar 2010, 18:40 Uhr

    Die Details sind Nebensache. Ist doch eine super Folge! Muss sagen, seit langem sogar die beste Folge. Zumindest aus meinem Blickwinkel. :)

    7. ingo am 22. Mar 2010, 15:04 Uhr

    @Jixxwar:
    1. Keine Ahnung. :) Wir hätten natürlich auch den sender nehmen können. Der ist wiederum bei den Methoden im SyncManager selbst komplett überflüssig. Aber so kann es nunmal trotz nebenliegendem Skript passieren, wenn man live aufnimmt und auf viel zu viele Dinge achten muss... ;-)
    2. Jepp, so eine Klassenmethode kann man natürlich schreiben
    3. Der Timer läuft ebenfalls im MainThread. Solange der eigene MainThread einen Event oder eine Methode ausführt wird definitiv kein Timer abgefeuert. Ein Timer stellt also nicht automatisch sicher, dass er immer pünktlich aufgerufen wird.

    @Raphael:
    Jepp, das wäre ordentlicher ;)

    Allgemein:
    Die Folge ist schon ziemlich lang und wir hatten echt ein Zeitproblem. Wir haben also alles auf das grundsätzliche Thema runtergekürzt, dass wir verstanden wissen wollten.

    6. Raphael am 22. Mar 2010, 14:55 Uhr

    Jungs, schöne Folge! Kurzes Feedback:
    (Gerade gesehen, dass auf "id" und "@protocol" bereits eingegangen wurde, deshalb lösche ich diese Punkte mal wieder, das folgende gilt aber auch für die aktuelle Umsetzung.)
    - Im dealloc vom Table Controller wäre es schön, wenn wir schauen ob die Delegate Property vom Sync Manager uns selbst (self) entspricht und wenn ja auf nil setzten, wenn wir selber weggehen.
    Gruss, Raphael

    5. Jixxwar am 22. Mar 2010, 14:24 Uhr

    Huhu, sehr schöne Folge. Vielen Dank, auch für den wunderbaren Buchtipp. Kannte das Buch noch gar nicht, Hellgrün ist auch sehr schön.

    Nur einige Punkte:
    - In den neuen Delegate Methoden des im ViewController, warum wird hier der "self.syncManager.files" für den Zugriff auf die Files Dict verwendet und nicht die übergebene "sender" Variable?


    - Kann man das Delegate für den SyncManager nicht direkt beim Erstellen anlegen. Also z.B. [SyncManager syncManagerWithDelegate:self]; ?

    +(id)syncManagerWithDelegate:(NSObject*)newDelegate { ... }


    - Sollte man den NSTimer nicht vor dem endgültigen Statusupdate, damit es nicht passieren kann, dass die 'ing Form zum Schluss darsteht? (Nochmalige ausführung des Timers, zwischen Textset und Timerkill)


    mfg.
    Dominic

    4. ingo am 21. Mar 2010, 23:45 Uhr

    Wie man eigene Protokolle erstellt, wird von uns noch erklärt werden. Uns ist zunächst mal wichtig, dass man das grundlegende Prinzip versteht. Zudem können wir leider nicht alles auf einmal machen...speziell von NSProxy sind wir noch eine Folgenanzahl im 2stelligen Bereich entfernt ;)

    Apple nutzt im Übrigen erst seit dem iPhone und Leopard ernsthaft Protokolle und intensiviert das mit Snow Leopard deutlich - und ich gehe mit Dir konform, dass das definitiv ein wichtiger Schritt ist.

    3. Wursthaut am 21. Mar 2010, 23:30 Uhr

    > Eigentlich sollte unter Cocoa alles von NSObject ableiten
    Nö, siehe NSProxy!

    Das das Ganze mit NSObject wunderbar funktioniert ist klar.
    Der Beste Weg das Ganze zu realisieren, ist aber wahrscheinlich der mit Hilfe eines Protokolls (so wie es Apple auch macht).
    Bsp.: NSTableView:
    - (void)setDelegate:(id <NSTableViewDelegate>)delegate;

    2. ingo am 21. Mar 2010, 22:14 Uhr

    Eigentlich sollte unter Cocoa alles von NSObject ableiten. Sonst hat man keinerlei Methoden für Speichermanagement oder gar performSelector-Methoden.

    Natürlich kann man auch id nehmen, aber da checkt z.B. der Compiler nicht mehr, wenn man sich bei Methodennamen vertippt.

    1. Wursthaut am 21. Mar 2010, 19:06 Uhr

    Warum verwendet ihr statt id NSObject bei der Deklaration des Delegate-Pointers? (Hintergrund: Klassen müssen nicht unbedingt Abkömmlinge von NSObject sein.)