1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

Obj-C Anfängerfrage

Dieses Thema im Forum "OS X-Developer" wurde erstellt von wosinzky, 13.05.07.

  1. wosinzky

    wosinzky Gloster

    Dabei seit:
    07.02.06
    Beiträge:
    62
    Hallo Entwickler,

    so langsam werde ich mit Xcode und Objective-C warm, aber die Philosophie von Obj-C, Cocoa usw. hab ich aber NOCH nicht verstanden. Da ich aber aus der C/C++ Welt komme, habe ich ein paar Verständnissprobleme. Das Buch "Programming in Objective-C" habe ich mir schon besorgt. Aber wie es immer so ist mit diesen Bücherbeispielen, sie sind immer ideal und vereinfacht gewählt (den Leser bloss nicht verwirren). D.h. auf die eigentlichen nicht trivialen Fragen bekommt man keine Antwort!

    Konstruktoren/Destruktoren (ich schreibe mal K und D, das ist kürzer :) )
    --------------------------------------------------------------------------
    Wie bekannt ist, ist in C++ immer ein K und ein D vorhanden. Wenn keiner implementiert wird, wird halt Einer gestellt. In Obj-C gibts es keine K's bzw. D's wie in C++, stattdessen übernimmt die alloc/init-Kombination dieselbe Rolle des K (Also ein Standard der aber nicht verbindlich ist?). Hoffentlich hab ich's bis hierher richtig verstanden.
    Darüber hinaus der werden in C++ die K's und D's immer ausgerufen. Ob man will oder nicht.

    Wenn ich in C++ einen String in einer Methode benutzen möchte, dann schreibe ich zB. so:

    int
    Klasse::methode()
    {
    std::string aString = "blah";
    }


    Wenn ich die Methode verlasse, weiss ich das der String automatisch zerstört wird (der D wird aufgerufen).

    Das gleiche in Obj-C müsste dann folgendermaßen aussehen:


    - (int ) methode()
    {
    NSString *aString;

    aString = [[NSString alloc] init];

    }

    Das Objekt aString wird aber beim verlassen der Methode nicht zerstört (is nur nen Zeiger auf ein Obj, ich weiss). Oder doch? Wie heisst in Obj-C der D? Wenn das Obj nicht zerstört wird, dann ist der Speicherbereich auf den der Zeiger zeigt verloren? Oder etwa nicht?

    Ich hoffe ihr versteht mein Verständnissproblem. Wie lange lebt ein Objekt? Wie heissen den K's und D's? Und was hat es mit den autorelease-Pools aufsich?

    Hoffentlich habe ich nicht zuviele Rechtschreibfehler gemacht :)

    Thx
    Wosinzky
     
  2. MacApple

    MacApple Lord Grosvenor

    Dabei seit:
    05.01.04
    Beiträge:
    3.470
    1 Person gefällt das.
  3. pepi

    pepi Cellini

    Dabei seit:
    03.09.05
    Beiträge:
    8.741
    In Deinem all wäre das [aString free]; allerdings hat das mit den Retain Countern von Cocoa noch nichts zu tun.
    Gruß Pepi
     
  4. Peter Maurer

    Peter Maurer Carmeliter-Renette

    Dabei seit:
    16.03.04
    Beiträge:
    3.274
    NSObject kennt keine -free-Methode, soviel ich weiss. Ich glaube, Du meinst [aString release]. ;)

    Und das hat was mit Retain-Countern zu tun: Die -release-Methode dekrementiert naemlich den Retain-Counter und ruft, falls letzterer bei Null angekommen ist, -dealloc auf. -autorelease dekrementiert den Counter haengend, naemlich dann, wenn der aktuelle Autorelease-Pool sein Leben aushaucht und dem Objekt die vorher beantragte -release-Botschaft sozusagen zurueckschickt (siehe die von MacApple o.g. Links), und deshalb geschieht auch alles andere dann ebenso haengend.

    Jedenfalls gilt: Wer selber -dealloc aufruft (ausser natuerlich [super dealloc] in der -dealloc-Methode einer Unterklasse), der macht was falsch.
     
  5. Yeti

    Yeti Gast

    Das wäre IMHO wohl die direkte Übersetzung in Objective-C/Cocoa:
    - (int ) methode()
    {
    NSString *aString = @"bla";
    // sollte das gleich sein wie ...= [NSString stringWithString: @"bla"];
    }

    (Zerstört wird aString nicht direkt beim Verlassen der Methode, sondern durch den Autoreleasepool. Wenn ich nicht ganz falsch liege.)
     
  6. wosinzky

    wosinzky Gloster

    Dabei seit:
    07.02.06
    Beiträge:
    62
    Moin aus dem hohen Norden,

    nach den anstrengenden Christi Himmelfahrt Tagen, habe ich endlich wieder ein bisschen Zeit gefunden mich den wahren Problemen dieser Welt zu widmen ;) . Hier mein kleines Getter-Setter-Testprogramm mit dem ich so meine kleinen Verständnissprobleme habe.

    Die Definition

    #import <Cocoa/Cocoa.h>

    @interface SetGet : NSObject {
    NSString *myString;
    }

    - (id) init;
    - (void) dealloc;
    - (void) set : (NSString *) newVal;
    - (NSString *) get;

    @end



    Die Implementation

    #import "SetGet.h"

    @implementation SetGet

    - (id) init
    {
    printf("=== init ===\n");

    if ((self = [super init])) // superclass may return nil
    {
    myString = [[NSString alloc] init];
    }

    return self;
    };

    - (void) dealloc
    {
    printf("=== dealloc ===\n");

    [myString release];

    [super dealloc];
    }

    - (void) set : (NSString *) newVal
    {
    printf("=== set ===\n");
    [myString release];
    myString = [newVal copy];
    };

    - (NSString *) get
    {
    printf("=== get ===\n");
    return myString;
    };

    @end



    Und einmal ausprobiert

    #import "SetGet.h"
    #import <Cocoa/Cocoa.h>

    int main(int argc, char *argv[])
    {
    SetGet *myTest = [[SetGet alloc] init];

    [myTest set: @"a text"];

    printf("%s\n", [[myTest get] UTF8String]);

    [myTest release];

    return 0;
    }




    Die Ausgabe


    [Session started]
    === init ===
    === set ===
    === get ===
    Setter_Getter_Tester[313] *** _NSAutoreleaseNoPool(): Object 0x3079e0 of class NSCFData autoreleased with no pool in place - just leaking
    a text
    === dealloc ===

    Setter_Getter_Tester has exited with status 0.



    Was will er mit seinem ARP? Ich baue doch alles ordnungsgemäss auf und ab! Oder nicht? Wo ist mein Denkfehler?

    MfG
    Wosinzky
     
  7. Peter Maurer

    Peter Maurer Carmeliter-Renette

    Dabei seit:
    16.03.04
    Beiträge:
    3.274
    Schnellschuss -- wer's besser weiss, der korrigiere mich bitte:

    Du selber machst gar keinen Fehler, Wosinzky, aber Cocoa braucht nun mal zumindest einen aktiven Autorelease-Pool. Die -UTF8String-Methode aus NSString z.B. autoreleaset ihren Rueckgabewert, wie auch der Dokumentation zu entnehmen ist (Hervorhebung von mir):

    Also mach' mal einen Autorelease-Pool um Deine Anweisungen rum und guck, ob's dann geht. :)

    Code:
    int main(int argc, char *argv[])
    {
    	NSAutoreleasePool *mainAutoreleasePool = [[NSAutoreleasePool alloc] init];
    	SetGet *myTest = [[SetGet alloc] init];
    	[myTest set: @"a text"];
    	printf("%s\n", [[myTest get] UTF8String]);
    	[myTest release];
    	[mainAutoreleasePool release];
    	return 0;
    }
    Hoffentlich hab' ich mich nicht vertippt. Abgesehen davon hat Dein Code fuer mein Gefuehl ein paar Schoenheitsfehler, aber das Fass lassen wir jetzt mal zu. Wahrscheinlich ist Dir das eh selber klar.
     
  8. MacApple

    MacApple Lord Grosvenor

    Dabei seit:
    05.01.04
    Beiträge:
    3.470
    Dieser Setter ist sehr gefährlich, denn wenn mal newVal == myString ist, wird newVal released, bevor es kopiert wird. Das ist gar nicht gut für die Stabilität des Programms. Abhilfe: myString ein autorelease schicken.

    MacApple
     
  9. Peter Maurer

    Peter Maurer Carmeliter-Renette

    Dabei seit:
    16.03.04
    Beiträge:
    3.274
    Das war einer der "Schoenheitsfehler", die ich gemeint hab'. :D

    Und weil Setter so ein schoenes Thema sind, hier gleich noch die Variante, die ich am liebsten verwende:

    Code:
    - (void)setValue: (id)newValue {
    	[newValue retain];
    	[myValue release];
    	myValue = newValue;
    }
    Denn merke: NSStrings sind non-mutable. In den meisten Faellen (wenn's nicht heimlich doch ein NSMutableString ist, der spaeter noch veraendert wird), reicht es also voellig aus, denselben String, der uebergeben wird, weiterzuverwenden.

    Und wenn man Objekte verwendet, die das NSCopying-Protokoll nicht unterstuetzen, dann geht copy eh nicht.

    Koennte uebrigens sein, dass die NSString-copy-Methode sich tatsaechlich selbst zu einer retain-Anweisung vereinfacht. Ich erinnere mich schwach, mal sowas gelesen zu haben; aber ausprobiert hab' ich's noch nie. Und es koennte auch stringWithString o.ae. betroffen haben.

    Und wenn's doch kopiert werden soll, dann eben so:

    Code:
    - (void)setValue: (id)newValue {
    	id copiedValue = [newValue copy];
    	[myValue release];
    	myValue = copiedValue;
    }
    Es bleibt natuerlich Geschmackssache; aber manchmal ist es einfach netter, nicht allzuviel Kram sich im Autorelease-Pool ansammeln zu lassen. :)
     
  10. MacApple

    MacApple Lord Grosvenor

    Dabei seit:
    05.01.04
    Beiträge:
    3.470
    Das stand aber noch nicht da, als ich meinen Beitrag geschrieben habe. ;)

    Eben weil man dem Setter auch einen NSMutableString übergeben darf, muss man sich darüber im klaren sein, was das für Konsequenzen haben kann.

    Logisch.

    Ja, NSString ist ja ein Class-Cluster, besteht also eigentlich aus diversen anderen Klassen, die dann jeweils optimierte Methoden haben.

    Wie ich einen Setter implementiere sollte keine Geschmacksfrage sein, sondern sich am erwarteten Verhalten orientieren.

    MacApple
     

Diese Seite empfehlen