NSTimer lässt Anwendung einfrieren

  • NSTimer lässt Anwendung einfrieren

    Hi,
    ich versuche gerade alle fünf Sekunden Daten via TCP von einem Server zu holen. Das Holen der Daten funktioniert erfreulicherweise einwandfrei. Dummerweise lässt der Timer aber meine Anwendung einfrieren.

    Quellcode

    1. - (void)awakeFromNib
    2. {
    3. // Timer starten: alle 5 Sekunden Daten holen
    4. trackTimer = [[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(trackTimerFired:) userInfo:nil repeats:YES] retain];
    5. // Aber bitte jetzt schonmal
    6. [self trackTimerFired:nil];
    7. }
    8. - (void)trackTimerFired:(NSTimer*)timer
    9. {
    10. Socket *controlSocket = [Socket socket];
    11. NSMutableData *response = [NSMutableData data];
    12. NSString *caption = [NSString string];
    13. // Künstler holen
    14. [controlSocket connectToHostName:@"192.168.178.22" port:1308];
    15. [controlSocket writeString:@"get current artist"];
    16. [controlSocket readData:response];
    17. caption = [caption stringByAppendingString:[[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding]];
    18. // zurücksetzen
    19. [response init];
    20. // Tracknamen holen
    21. [controlSocket writeString:@"get current trackname"];
    22. [controlSocket readData:response];
    23. caption = [caption stringByAppendingString:@"\n"];
    24. caption = [caption stringByAppendingString:[[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding]];
    25. // TextField setzen
    26. [currentTrack setStringValue:[caption copy]];
    27. // Alles weg damit
    28. [response release];
    29. [caption release];
    30. [controlSocket release];
    31. }
    Alles anzeigen


    Beim Aufruf der Timer-Methode (egal ob das jetzt manuell geschieht oder erst beim Firen des Timers) bleibt das Programm stehen und das Debuggerfenster öffnet sich. Ich hab gerade keine schlüssige Erklärung warum.
    Hat jemand da eine Idee?

    Chris
  • Irgendwo wird ein Log stehen mit so etwas wie EXC_BAD_ACCESS. ;)

    @Calgan:
    Bitte lies dir menen Artikel zur Speicherverwaltung durch:
    macentwicklerwelt.net/doku.php?id=wiki:speicherverwaltung

    oder
    <Werbeeinblendung>
    Rodewig/Negm-Awad, Objective-C und Cocoa, S. 132-176
    </Werbeeinblendung>
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • RE: NSTimer lässt Anwendung einfrieren

    Also, ich schreib dir die Fehler hier rein:

    Quellcode

    1. - (void)awakeFromNib
    2. {
    3. trackTimer = [[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(trackTimerFired:) userInfo:nil repeats:YES] retain];
    4. [self trackTimerFired:nil];
    5. }
    6. - (void)trackTimerFired:(NSTimer*)timer
    7. {
    8. Socket *controlSocket = [Socket socket];
    9. NSMutableData *response = [NSMutableData data];
    10. NSString *caption = [NSString string]; //ganz weg die zeile, weil du unten den pointer caption eh neu setzt
    11. [controlSocket connectToHostName:@"192.168.178.22" port:1308];
    12. [controlSocket writeString:@"get current artist"];
    13. [controlSocket readData:response];
    14. caption = [caption stringByAppendingString:[[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding]]; //Autorelease hinter "alloc/init"
    15. [response init]; //weg damit, das wurde schoin initialisiert, niemals mehr als ein init
    16. [controlSocket writeString:@"get current trackname"];
    17. [controlSocket readData:response];
    18. caption = [caption stringByAppendingString:@"\n"];
    19. caption = [caption stringByAppendingString:[[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding]]; //autorelease hinter "alloc/init"
    20. [currentTrack setStringValue:[caption copy]]; //autorelease hinter copy, copy bring immer ein object zurück mit retaincount 1, kein autoreleastes
    21. [response release];
    22. [caption release]; //caption ist autoreleased, nicht releasen
    23. [controlSocket release]; //controlsocket das gleiche wie caption
    24. }
    Alles anzeigen


    ich hätte den code so geschrieben, so ist es für mich übersichtlicher:

    Quellcode

    1. - (void)awakeFromNib
    2. {
    3. trackTimer = [[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(trackTimerFired:) userInfo:nil repeats:YES] retain];
    4. [self trackTimerFired:nil];
    5. }
    6. - (void)trackTimerFired:(NSTimer*)timer
    7. {
    8. Socket *controlSocket = [Socket socket];
    9. [controlSocket connectToHostName:@"192.168.178.22" port:1308];
    10. [controlSocket writeString:@"get current artist"];
    11. NSMutableData *currentArtist = [NSMutableData data];
    12. [controlSocket readData:currentArtist];
    13. [controlSocket writeString:@"get current trackname"];
    14. NSMutableData *currentTrackname = [NSMutableData data];
    15. [controlSocket readData: currentTrackname];
    16. NSString *caption = [[[NSString alloc] initWithData:currentArtist encoding:NSUTF8StringEncoding] autorelease];
    17. caption = [caption stringByAppendingString:@"\n"];
    18. caption = [caption stringByAppendingString:[[[NSString alloc] initWithData:currentTrackNameencoding:NSUTF8StringEncoding] autorelease]];
    19. [currentTrackField setStringValue:caption];
    20. }
    Alles anzeigen
  • Hi,
    danke für die Erläuterungen. Ich habe mich wohl ein wenig zu sehr an alte Gewohnheiten gehalten, alle Objekte bei Nicht-Mehr-Verwendung freizugeben.

    Den Artikel werde ich mir auf jeden Fall durchlesen, ich denke, dass sich dann einige Unklarheiten beseitigt sein sollten.

    Der Code sieht wirklich übersichtlicher aus, danke. War wohl gestern Abend ein wenig spät. *g*
    Habe das response init rein gemacht, weil ich das Data-Objekt wieder leeren wollte, um neue Daten reinzuschreiben und bei NSData kein clear oder so gefunden. Und bei den übrigen Sachen wollte ich nicht, dass mir Objekte den Speicher zu müllen. Aber scheinbar braucht man sich um Speichermanagement nicht wirklich zu kümmern.

    Danke für eure Hilfe,
    Chris
  • Original von CalganX
    Habe das response init rein gemacht, weil ich das Data-Objekt wieder leeren wollte, um neue Daten reinzuschreiben und bei NSData kein clear oder so gefunden.

    Zum leeren eines NSMutableData Objekt fallen mir da spontan zwei Möglichkeiten ein:

    Quellcode

    1. [theMutableData setData:[NSData data]];
    2. // oder
    3. [theMutableData setLength:0];

    Original von CalganX
    Aber scheinbar braucht man sich um Speichermanagement nicht wirklich zu kümmern.

    Oh doch, man muss sich um das Speichermanagement kümmern. Nur muss man es richtig tun.

    Michael