Forum>Entwickler>Erfahrung mit Apple Dev Tools und REALBasic (oder evt. VB)?

Erfahrung mit Apple Dev Tools und REALBasic (oder evt. VB)?

Stefab
Stefab04.06.0916:52
Hallo!

Wollte fragen, ob es hier jemanden gibt, der Erfahrung sowohl mit den Apple Developer Tools (Xcode, Interface Builder, etc.) UND mit REALBasic (oder notfalls Visual Basic) hat? Zum Erfahrungsaustausch und sonst was. (zB. über iChat wäre toll!).

Ich versuche mich gerade in die Developer Tools einzuarbeiten, hauptsächlich, wegen Programmieren fürs iPhone. (später oder nebenbei sicher auch für den Mac) Das einzige, worin ich mich momentan recht gut auskenne ist REALBasic. Falls jemand in einer ähnlichen Situation steckt, können wirs ja gemeinsam versuchen. Vielleicht sucht ja auch jemand die andere Richtung (zB. wegen Multiplattform) oder was weiß ich. Ich bin im AIM als "stuepfnick" eingetragen und in letzter Zeit wieder regelmäßig online mit iChat. Ansonsten einfach hier antworten. Ich wäre für jede Hilfe dankbar, bin auch gerne bereit anderen weiter zu helfen. (falls ich irgendwie kann )
Hatte früher natürlich auch andere Programmiersprachen, vom C64-Basic, GEOS-Assembler (als Kind) über verschiedene Amiga-Sprachen (Jugendlicher) bis seit ca. 10 Jahren zum Mac. Leider war nie C oder C++ dabei.
0

Kommentare

Stefab
Stefab04.06.0917:00
PS: Ach ja, OpenGL war auch dabei, allerdings hab ich davon schon vieles wieder vergessen, da doch schon einige Jahre her und ziemlich komplex.
0
Johloemoe
Johloemoe04.06.0917:52
Lerne C! Es hilft nix, du kommst an der Sprache nicht vorbei. Besorg dir ein gutes Buch oder versuch es im Internet, aber ich weiss nicht ob Online-Tutorials ausreichend erhellend sind...
0
Stefab
Stefab04.06.0919:13
Klar mach ich das. Bin gerade bei den "Getting Started" Texten auf den Apple Seiten.

Aber wenn jemand in einer ähnlichen Situation ist, wie ich, kann es keinesfalls schaden, Erfahrungen auszutauschen, darum die Frage. Ergibt doch Sinn, oder?
0
Johloemoe
Johloemoe04.06.0920:24
Tut es, aber ich wollte damit andeuten dass es (leider) nicht viele Überschneidungen zwischen C und VB/RB/*B gibt. Andererseits basieren extrem viele Sprachen auf C, sodass du dann im Prinzip fast alle Sprachen kannst, die im Moment "aktuell" sind
0
Stefab
Stefab05.06.0911:47
Ergibt natürlich Sinn, dazu gleich eine Frage dazu: Gibt es bzgl. C Programmierung etwas ähnliches wie das Redbook für OpenGL?
0
Mr. Krabs
Mr. Krabs05.06.0912:09
Stefab:
NeHe Gamedev-Tutorials:

Schlag dich aber erstmal durch C, Memory-Management, wie die Kompiler und Linker funktionieren usw... Muss nicht, kann aber durchaus hilfreich sein zu wissen, was die Sprache unten den eigenen Füßen so anstellt...
„Deux Strudel!“
0
ExMacRabbitPro05.06.0912:17
Stefanb

Wenn es wirklich um reines C geht, dann stellt dieses Werk:

"Programmieren in C. ANSI C. Mit dem C-Reference Manual." von Brian Kernighan und Dennis Ritchie

Amazon-Link:

sowas wie das Redbook dafür da.
0
ela05.06.0914:54
Ich stimme den Tipps nicht so ganz zu.
Wenn Du für das iPhone entwickeln möchtest, dann nimmst Du ohnehin XCode. Also solltest Du ein gutes Buch für XCode/Object-C kaufen. Such mal bei Amazon nach "Hillegass" Ich habe dieses gekauft und es ist sehr gut geschrieben:
Meine Ausgabe sieht wie die verlinkte aus und ist etwas älter. Für das aktuelle XCode und erst Recht iPhone muss man etwas abstrahieren oder ein wenig suchen - geht aber. Weiß nicht, ob es schon eine neue Auflage gibt.

0
Johloemoe
Johloemoe05.06.0916:11
ela
Naja, eins nach dem anderen wäre nicht schlecht. Wenn man noch keine Erfahrung in C hat haut einen Obj-C echt um. Ist ja so schon anders genug, dass man sich erstmal am Kopfe kratzt.

C-Buch
Ich hab das mit "C Programmieren von Anfang an" von Helmut Erlenkötter (Amazon: ) gelernt. Ist ein kleines Taschenbuch was einem C gut beibrigt.

Große Kompendien bringen imho nix, weil die sich dann implizit auf bestimmte Schnittstellen beziehen, wie Win32, glib oder weiss der Teufel was.

Ich würde das reine C lernen und dann mit dem Hillegass weitermachen!
0
Stefab
Stefab06.06.0920:22
Ich hab de einen super Tipp für den ersten Einstieg bekommen. Den möchte ich hiermit weitergeben, und zwar das eBook, BecomeAnXcoder, welches sogar in deutscher Sprache (und kostenlos) vorliegt:

Es geht die Sache zwar sehr langsam an, aber das ist auch gar nicht schlecht so, deshalb muss man ca. die erste Hälfte (oder mehr) nur einmal lesen (entgegen den Anweisungen im Buch), wenn man zumindest schon mal irgendwas programmiert hat.
Bin gerade auf Seite 67. Was leider nicht so gut erklärt wurde ist, warum der Inhalt von NSString nicht änderbar sein sollte, das hat mir aber nun jemand anders erklärt. (eventuell kommt da später im Buch noch mehr..?) Falls das jemanden interessiert, kann ich das anhand von ein paar Zeilen Beispielcode und einem Satz (oder 2) erklären.
Wenn ich durch das Programmieren mal Geld verdienen sollte, geb ich denen als erstes ne Donation für das feine eBook!
0
ExMacRabbitPro06.06.0920:25
Stefab
Was leider nicht so gut erklärt wurde ist, warum der Inhalt von NSString nicht änderbar sein sollte, das hat mir aber nun jemand anders erklärt. (eventuell kommt da später im Buch noch mehr..?) Falls das jemanden interessiert, kann ich das anhand von ein paar Zeilen Beispielcode und einem Satz erklären.

Warum sollte man das groß erklären müssen? NSString ist nicht änderbar - die Klasse hat keine Methoden dazu. Fertig - Ende - Aus.
Möchte man einen änderbaren String gibt es dafür NSMutableString. Genau so verhält es sich bei NSArray, -Data, -Dictionary, -Set, etc...
0
iCode
iCode07.06.0908:24
Eine Übersicht über die verfügbaren Objective-C / Cocoa-Bücher findest Du bei awakeFromNIB.de : Da hättest Du auch BecomeAnXcoder gefunden.
0
iCode
iCode07.06.0908:31
Was ich nicht nachvollziehen kann: Du behauptest dass Du früher mal mit OpenGL gearbeitet hättest, sagst aber, dass Du kein C kannst. Wie passt das denn zusammen?
Schau Dir mal in dem von Dir erwähnten The Redbook - dem OpenGL Guide - die ganzen Beispiele an. So sieht OpenGL aus. Das ist alles blankes C.
0
iCode
iCode07.06.0908:36
PS: Alle Bücher haben ihre Stärken und ihre Schwächen. Es ist dahr durchaus sinnvoll und empfehlenswert mehr als nur ein Buch gelesen zu haben.
0
Stefab
Stefab07.06.0910:06
Ich muss gestehen, nach dem ich die Kommentare auf der HTML-Version zu "BecomeAnXCoder" gelesen habe: bin ich nun doch wieder verwirrt...

Um es genauer zu sagen, der String kann ja getauscht werden, wie in Beispiel [5], was in der aktualisierten (englischen) HTML-Version auch richtigerweise so im Text steht, also hier der wichtige Teil von Beispiel [5]:

NSString *favoriteComputer;
favoriteComputer = @"iBook";  // [5.7]
favoriteComputer = @"MacBook Pro";
NSLog(@"%@", favoriteComputer);

Dann bei Beispiel [7] wird der String "Julia!" in Uppercase verwandelt, aber in einem anderen NSString (bar) gespeichert:

NSString *foo, *bar;
foo = @"Julia!";
bar  = [foo uppercaseString];
NSLog(@"%@ is converted into %@.", foo, bar);

Nun kann ich das aber auch schreiben:
NSString *foo;
foo = @"Julia!";
NSLog(@"&@",foo);
foo = [foo uppercaseString];
NSLog(@"&@",foo);

Das läuft auch, und es kommt heraus:
Julia!
JULIA!

Was mich jetzt verwirrt: Jemand hat gesagt, wenn ich den Pointer zu dem String wieder verwende, bleibt der String: "Julia!" im Speicher stehen, es gibt aber keinen Pointer mehr dazu, weil dieser (foo) nun auf "JULIA!" an einer anderen Stelle im Speicher zeigt.
Aber ist das nicht bei Codebeispiel 5 genauso?!? Und wenn das so ist, warum wird das dann im Beispiel 5 so gemacht?
Oder ist es sowieso egal, weil "Julia!" bzw. im anderen Falle "iBook" zwar noch irgendwo im Speicher steht, aber es irrelevant ist, weil der Speicher eh nicht mehr durch einen Pointer reserviert ist und daher sowieso überschrieben wird, wenn irgendetwas anderes zufällig an die Stelle schreiben will?
Oder ist es eben nicht empfehlenswert, NSStrings neue Strings zuzuweisen, weil die Strings ohne Pointer dann Speicher blockieren?
Bei ersterem sollte es doch egal sein, ob ich ein NSString-Objekt verwende und diesen tausche, mit einer neuen Version vom alten String, an dem Änderungen vorgenommen wurden, oder ob ich ein NSMutableString Objekt verwende und dessen String mit einer Methode von NSMutableString ändere.

Btw: Am Rande bemerkt, ein IMHO sehr nettes Programm ist der "Cocoa Browser Air", zu finden hier: Das verwendet zwar auch "nur" die Dokumentationen, die man sich zuerst über XCode aus dem Netz laden muss, aber die wunderbare Ansicht mit der Verschachtelung mit der Suche ist schon sehr übersichtlich und macht es einem ziemlich leicht, gewünschte Klassen, und deren Funktionen zu finden. (ähnlich der Language Reference in RB, nur IMHO noch nen Tick besser)
Jemand anderer findet die alte Version "Cocoa Browser" ohne Air besser, dazu kann ich aber nichts sagen, den habe ich nicht probiert. Ich kann mir aber gut vorstellen, dass es an der Macht der Gewohnheit liegt, dass er die alte Version besser findet, Download-Link dazu:
0
Stefab
Stefab07.06.0910:37
iCode: Danke! Wegen OpenGL, dieses habe ich innerhalb von REALBasic verwendet, zuerst mit einem PlugIn, dann später mit Modulen, die alle nötigen Declares und Konstanten enthalten, diese kann man übrigens hier laden:

Allerdings sind diese nicht mehr zu 100% aktuell, weil RB2007-5 (oder neuer) mit einem Programm, das diese nutzt, crasht. Ich habe es gestern korrigiert, so dass es auch wieder mit der neusten Version von RB funktioniert und die Änderungen mitgeteilt (es mussten nur ein paar doppelte Konstanten-Definitionen gelöscht werden), ich denke demnächst wird das auch auf der Webseite aktualisiert. Das ganze ist vor allem daher interessant, weil es Rb3d in neueren Versionen nicht mehr gibt.

Zum eigentlichen Code: Das ganze sieht in RB nicht viel anders aus, als in C. Mathematische Berechnungen sind sowieso praktisch gleich, und OpenGL-Aufrufe sehen dann so aus:

glEnableClientState GL_TEXTURE_COORD_ARRAY

wobei man es auch in Klammern schreiben kann:

glEnableClientState(GL_TEXTURE_COORD_ARRAY)

Das macht offenbar keinen Unterschied. Wenn man Werte an OpenGL-Befehle übergibt:

glVertexPointer 3, GL_FLOAT, 0, Vertices

Wobei "Vertices" einen Memoryblock voller floats ist (in RB werden floats als Single bezeichnet)

Das eigentliche zeichnen dann so:

glDrawElements GL_TRIANGLES, Triangles.Size*0.5, GL_UNSIGNED_SHORT, Triangles

Wobei Triangles.Size*0.5 weil der Memoryblock aus Shorts besteht und die Größe in bytes nun doppelt so groß ist, wie die Anzahl der gespeicherten Zahlen.

Das ganze wird dann (meinem Falle) in alle möglichen Klassen und Unterklassen aufgeteilt. Ins Hauptfenster wird eine von mir erstellte View-Klasse gezogen, bei der man ein paar Werte (wie Größe, usw.) festlegen kann, im Open-Event vom Hauptfenster wird OpenGL initialisiert und dann ruft ein Timer 100x pro Sekunde die Zeichenroutine vom View auf, welche dann die Zeichenroutinen der einzelen Objekte (und Unterobjekte) der Reihe nach aufruft. Die ganze Engine ist ähnlich struktiert, wie rb3d, welches ja auf dem ausgestorbenen Quickdraw3D bzw. Quesa aufbaut. Also das ganze Zeug mit 3D Objekten, 3D Gruppen, Licht-Objekten, Kamera-Objekt, Materialen, Quaternions, Vektoren, usw. usf. (alles ineinander verschachtelt, auf objekt-typische Weise) Ich denke, das sollte deine Frage beantworten
0
ExMacRabbitPro07.06.0911:29
Stefab

ok - ich versuch mal zu erklären was da genau passiert und warum in den Beispielen kein Memory-Leak entsteht. Dass hat primär etwas mit dem Speichermanagement von Obj-C zu tun und ist einfach zu verstehen, wenn man die wenigen Regeln des Speichermanagements von Cocoa kennt. Ich beziehe mich aber ausdrücklich NICHT auf das Garbage Collection Feature in Obj-C 2.0 - dass ich, nebenbei erwähnt, für vollkommen überflüssig halte und in meinen eigenen Projekten auch nicht einsetze und dass z.B. auf dem iPhone auch gar nicht existiert.

also - los gehts....

NSString *favoriteComputer;
favoriteComputer = @"iBook";  // [5.7]
favoriteComputer = @"MacBook Pro";
NSLog(@"%@", favoriteComputer);

In diesem Beispiel wird dynamisch überhaupt kein Speicher allokiert - folglich braucht auch keiner frei gegen zu werden. Der Zeiger "favoriteComputer" wird lediglich nacheinander auf die Adressen der beiden konstanten Strings @"iBook" und @"MacBook Pro" gesetzt und letzterer dann via NSLog ausgegeben. Nur wenn ein NSString via [[... alloc] init] erzeugt wird, wird auch dynamisch Speicher allokiert, über dessen Freigabe man sich gedanken machen muss.

NSString *foo, *bar;
foo = @"Julia!";
bar  = [foo uppercaseString];
NSLog(@"%@ is converted into %@.", foo, bar);

In diesem Beispiel wird in der Tat ein neuer NSString erzeugt, für den auch Speicher allokiert wird. Dies ist der String, der von der Message "uppercaseString" zurück gegeben wird. Allerdings kommt jetzt eine Regel des Speichermanagements des Cocoa Frameworks
ins Spiel: Alle Objekte die von Cocoa-Messsages zurück gegeben werden, sind sog. "autoreleaste" Objekte. Dies bedeutet, dass die Objekte automatisch im Autorelease-Pool liegen und vom Lauzeitsystem freigegeben werden, sobald die referenzierende Vaiable "out off scope" kommt. Dies bedeutet, dass die String auf den "bar" zeigt nach der Methode (oder Funktion?) in der er verwendet wurde, automatisch freigegeben wird.

NSString *foo;
foo = @"Julia!";
NSLog(@"&@",foo);
foo = [foo uppercaseString];
NSLog(@"&@",foo);

Hier gilt das gleiche wie im Beispiel oben drüber, nur dass für den uppercase String kein eigener Zeiger verwendet wurde.


0
kammerlander07.06.0912:44
ExMacRabbitPro
Dies bedeutet, dass die Objekte automatisch im Autorelease-Pool liegen und vom Lauzeitsystem freigegeben werden, sobald die referenzierende Vaiable "out off scope" kommt. Dies bedeutet, dass die String auf den "bar" zeigt nach der Methode (oder Funktion?) in der er verwendet wurde, automatisch freigegeben wird.

Das ist so nicht richtig, der default Autorelease-Pool wird erst beim nächsten Run-Loop durchlauf geleert.
0
iCode
iCode07.06.0913:07
kammerlander
Das ist so nicht richtig, der default Autorelease-Pool wird erst beim nächsten Run-Loop durchlauf geleert.
Das besagte Objekt könnte aber auch in einem anderen Autorelease-Pool liegen.

Wie dem auch sei. Seine Erklärung trifft den Nagel auf den Kopf, und ich finde er hat es recht gut erklärt.
0
iCode
iCode07.06.0913:11
Stefab
Die Information, dass Du OpenGL nur via REALBasic-PlugIn genutzt hast, wäre ausreichend gewesen.
0
iCode
iCode07.06.0913:17
Zum Thema Speichermanagement gibt's bei Macoun auch ein Video vom Uli Kusterer.
0
ExMacRabbitPro07.06.0913:30
kammerlander
ExMacRabbitPro
Dies bedeutet, dass die Objekte automatisch im Autorelease-Pool liegen und vom Lauzeitsystem freigegeben werden, sobald die referenzierende Vaiable "out off scope" kommt. Dies bedeutet, dass die String auf den "bar" zeigt nach der Methode (oder Funktion?) in der er verwendet wurde, automatisch freigegeben wird.

Das ist so nicht richtig, der default Autorelease-Pool wird erst beim nächsten Run-Loop durchlauf geleert.

Ja, da haben wir schon das Problem, sich immer richtig auszudrücken....
Ich habe dass eigentlich so gemeint, dass nach dem Ende der Methode in der der Code steht, der aktuelle Event-Loop vorbei ist. Das "out of scope" ist da wirklich falsch ausgedrückt und deine Beschreibung ist korrekter. Danke für die Richtigstellung/Ergänzung!
0
Stefab
Stefab07.06.0916:38
iCode:
Die Information, dass Du OpenGL nur via REALBasic-PlugIn genutzt hast, wäre ausreichend gewesen.

Der Satz ist nicht ganz richtig! Angefangen habe ich lediglich mit dem Plug-In, welches aber nicht weiterentwickelt wurde und mit neueren RB-Versionen daher nicht kompatibel. Daraufhin bin ich auf die besagten Declare-Libraries ausgewichen, welche nativer RB-Code sind. Damit wird so ziemlich jeder OpenGL-Befehl (bis OpenGL 1.4) aus RB aufrufbar. Mit Declares kann man sich C-Befehle nach RB holen.

iCode & ExMacRabbitPro: Es wird einiges gut erklärt und vor allem wird auch endlich die Garbage-Collection angesprochen, da ich schon etwas Angst hatte, das ganze sei komplizierter.

Aber da, wo es gerade spannend wird, steht quasi nur, siehe oben. Eigentlich geht es ja mir nur um das letzte Codebeispiel (im Vergleich zu den anderen), und die Feststellung/Frage, was das Problem daran ist, dass ich den Inhalt eines solchen NSString Objekts im letzten Beispiel in Uppercase umwandle, ohne dafür aber NSMutableString zu brauchen. Vielleicht hab ich mich zu ungenau ausgedrückt.

Aber soweit ich das verstehe, scheint das ja in Ordnung zu sein, dass man den Inhalt von NSString immer wieder austauscht, auch mit Methoden, die das Original abändern. Ein NSMutableString wird intern vermutlich auch nichts anderes machen, als den Inhalt intern neu zu berechnen und damit den alten String zu ersetzten.
Somit ziehe ich die Schlussfolgerung: Der NSMutableString hat nur die Vorteile, dass er Methoden zur direkten Veränderung mit sich bringt. (eventuell ein paar, die sonst nicht möglich wären)
Also um ganz sicher zu gehen: Es ist völlig ok, wenn ich schreibe:

NSString *foo = @"Rabenau";
foo = [foo uppercaseString];
foo = [foo lowercaseString];
foo = [foo stringByAppendingString:@" geht badenau."];

usw. usf. all zu oft kann man den NSMutableString ja dann wirklich nicht brauchen...
0
ExMacRabbitPro07.06.0917:37
Stefab]

NSString *foo = @"Rabenau";
foo = [foo uppercaseString];
foo = [foo lowercaseString];
foo = [foo stringByAppendingString:@" geht badenau."];

Vorsicht! Du unterliegst da einem fatalen Missverständnis! In dem Beispiel tauschst Du NIEMALS die Zeichen in irgend einem String aus bzw. modifizierst sie!!!! Es wird vielmehr immer ein neuer erzeugt.


Ich versuche es mal zu verdeutlichen:

Nehmen wir an, nach dem Laden des Programms steht der konstante String @"Rabenau" an der Adresse 0x7411.
Demnach enthält der Zeiger foo nach der ersten Zeile die Adresse 0x4711. Jetzt rufst Du die Message "uppercaseString" der Klasse NSString auf. Diese Liefert dir einen Zeiger auf ein neu erzeugtes NSString Objekt, dessen Inhalt eine Kopie des NSStrings bei 0x4711 darstellt, auf den foo zum Zeitpunkt des Aufrufs gezeigt hat - nur eben gewandelt in Großbuchstaben.
Da Du die zurückgelieferte Objektadresse wieder deiner Zeigervariable foo zuweist, hast Du die ursprüngliche Adresse 0x7411 verloren und foo zeigt nun auf den neuen NSString - der z.B. auf Adresse 0x4811 liegt. foo enthält nun also 0x4811.

So weit klar? Ok - nächste Zeile:
In der nächsten Zeile ruft Du auf dem NSString bei Adresse 0x4811 die Message "lowercaseString" auf. Auch diese erzeugt wieder ein neues NSString Objekt (nun mit Kleinbuchstaben) und liefert dessen Adresse - sagen wir die wäre 0x4911. foo zeigt jetzt also auf das NSString Objekt bei 0x4911. Die Referenzen auf die Objekte davor (0x4811 und 0x4711) hast du verloren.

Nun die letzte Zeile - Du kannst es Dir aber sicher schon denken:
Diese Zeile erzeugt wieder ein neues NSString Objekt, an dass an den zuletzt in Kleinbuchstaben formatierten String die Zeichenkette @" geht badenau." anhängt wird. Dieses neue Objekt hat natürlich auch wieder eine neue Adresse - sagen wir 0x5011 - und diese wird dem Zeiger foo zugewiesen. Nach der letzten Zeile zeigt foo also auf einen NSString mit der Adresse 0x5011 und dem Inhalt @"rabenau geht badenau.".

Den originalen, konstanten String @"Rabenau" aus Zeile 1 hast Du dabei aber NIE(!) verändert - dass geht gar nicht - sondern immer ein neues String Objekt erzeugt. Willst Du dass nicht, kommt genau an dieser Stelle NSMutableString ins Spiel. Nur mit ihm ist es möglich, ein und den selben String im Speicher zu modifizieren, ohne immer ein neues Objekt zu erzeugen.

Puh - ich hoffe dass war einigermaßen verständlch...
0
michaeljk07.06.0917:57
Stefab:
Es gibt ja mittlerweile auch noch die RBGL Library, die eigentlich auch mit neueren REALbasic-Versionen problemlos funktionieren dürfte:
RBGL is cross-platform and does not rely on any plugins, either internal or external. RBGL also forms the basis of the RBGLSprites and RBGL3D libraries, which extend its functionality with 2D and 3D gaming capabilities respectively.
0
iCode
iCode07.06.0920:48
Wenn Du Dir mal die id dazwischen anzeigen lässt, ist es vielleicht klarer.
Gleiche id, gleiches Objekt. Andere id, anderes Objekt.
    id foo = @"Rabenau";
    foo = [foo uppercaseString];
    NSLog(@"id:0x%x description:%@.", foo, foo);
    foo = [foo lowercaseString];
    NSLog(@"id:0x%x description:%@.", foo, foo);
    foo = [foo stringByAppendingString:@" geht badenau."];
    NSLog(@"id:0x%x description:%@.", foo, foo);
0
Stefab
Stefab08.06.0915:35
ExMacRabbitPro:

Es ist mir schon klar, dass man den String nicht modifiziert, sondern durch den neuen austauscht. (vereinfacht gesagt).
Weiter oben habe ich ja auch geschrieben, dass der Pointer ja dann auf das neue Objekt zeigt. Die einzige Sache, die mir dabei unklar ist, ob diese alten Strings noch Speicher blockieren oder nicht.

1.) Denn wenn nicht, ist es ja vollkommen egal, ob die alten Strings noch irgendwo im Speicher rumliegen, wenn sie für den Mac nur als ungenutzter Speicher bekannt sind (bzw. eben unbekannt, da nichts mehr darauf verweist), welcher ja dann bei Bedarf einfach überschrieben wird.
Und es ist dann auch folglich ziemlich egal, ob man einen NSMutable-String verwendet und den verändert, oder einen NSString immer wieder auf neue abgeänderte Versionen von sich selbst zeigen lässt.

2.) Aber wenn die alten Speicherstellen weiterhin blockiert werden, müsste man immer wieder neue NSStrings verwenden, oder eben einen NSMutableString.

Also ist es nun 1 oder 2?

Das ist es, worauf ich eigentlich die ganze Zeit hinaus will, da mir das nicht klar ist.
0
Stefab
Stefab08.06.0916:00
michaeljk: Scheint auch ganz interessant zu sein. Ist jedenfalls mehr, als die reinen Declares und Constanden, um pures OpenGL zu verwenden. (evt. eine ganze Engine?) die GLDeclares von denen dürfte in etwa das sein, was ich genutzt habe (direktes Low Level OpenGL). Die "OpenGL Declare Library" von fireye (die ich genutzt habe) ist jedenfalls auch unabhängig von der RB-Version, da ja auch kein Plug-In. Es mussten nur ein paar doppelte Konstanten-Definitionen entfernt werden, da das bei RB2007-5 (und neuer) nicht aktzeptiert wird. Wenn man das allerdings inklusive Programm kompliert, stürzt RB einfach ab (ein Fehler offenbar von REALSoftware), kompiliert man die Declare-Lib alleine, zeigt es die doppelten Konstanten (sind etwa 5-10) der Reihe nach auf, man kann sie einfach rauslöschen, jetzt ist sie sauber und macht von RB 5.5.5 bis RB 2009-v2.1 keine Probleme mehr. Ich weiß aber nicht, ob Fireye die Files am Webserver schon upgedated hat, hab ihn jedenfalls (via iChat) darauf aufmerksam gemacht, und auch die bereinigte Version geschickt.
Hast du vielleicht eine Ahnung, bis zu welcher OpenGL-Version die "GL Declares 1.1.1" von Charcoal Design reichen? Bei denen von fireye ist es OpenGL 1.4.
Jedenfalls danke für den Tipp, werd ich mir bookmarken, evt. kann ichs in Zukunft ja mal brauchen.
0
ExMacRabbitPro08.06.0916:02
Stefab
ExMacRabbitPro:

Es ist mir schon klar, dass man den String nicht modifiziert, sondern durch den neuen austauscht. (vereinfacht gesagt).
Weiter oben habe ich ja auch geschrieben, dass der Pointer ja dann auf das neue Objekt zeigt. Die einzige Sache, die mir dabei unklar ist, ob diese alten Strings noch Speicher blockieren oder nicht.

1.) Denn wenn nicht, ist es ja vollkommen egal, ob die alten Strings noch irgendwo im Speicher rumliegen, wenn sie für den Mac nur als ungenutzter Speicher bekannt sind (bzw. eben unbekannt, da nichts mehr darauf verweist), welcher ja dann bei Bedarf einfach überschrieben wird.
Und es ist dann auch folglich ziemlich egal, ob man einen NSMutable-String verwendet und den verändert, oder einen NSString immer wieder auf neue abgeänderte Versionen von sich selbst zeigen lässt.

2.) Aber wenn die alten Speicherstellen weiterhin blockiert werden, müsste man immer wieder neue NSStrings verwenden, oder eben einen NSMutableString.

Also ist es nun 1 oder 2?

Das ist es, worauf ich eigentlich die ganze Zeit hinaus will, da mir das nicht klar ist.

Irgendwie ist Dir dass Konzept von Zeigern nicht ganz klar. Du scheinst den Zeiger NSString *foo als String zu sehen. Dass ist er aber nicht! Es ist lediglich ein Zeiger (also die Adresse eines NSStrings). In Obj-C gibt es keinen Konstrukt wie in Basic - ala: "Dim str As String" und str IST dann der String. Du hast immer nur Zeiger und in denen stehen die Speicheradressen von den Objekt-Instanzen.

Nun zu Deinen Fragen:

zu 1.
Da ist der Kern den Denkfehlers - es ist prinzipiell nicht egal, wenn Objekte im Speicher liegen auf die kein Zeiger mehr verweist - denn sie belegen immer noch ihren Speicherbereich und werden mit nichten bei Bedarf einfach überschieben. Daher muss man sich immer Gedanken über die Lebensdauer von Objekten sowie deren Freigabe machen. Was uns geradewegs zu Frage 2 führt:

zu 2.
In diesem speziellen Beispiel, wo die Strings durch Aufruf der Messages "uppercaseString", "lowercaseString" und "stringByAppendingString" erzeugt werden, ist eine explizite Freigabe der Objekte nicht notwenig, weil per Definition (sofern nicht anders angegeben) alle Cocoa Messages die neue Objekte liefern diese in den aktuellen Autorelease-Pool legen.
Diese bedeutet, dass das Objekt von System selbst freigegeben wird.
Allerdings - wie oben bereits beschieben - direkt nach Ablauf des Run-Loop Zyklus.

Möchtest Du das Objekt länger behalten, musst Du ihm ein "retain" schicken, damit es nicht freigegeben wird. Danach musst Du es aber auch wieder mit "release" selbst freigeben, damit es vom Obj-C Laufzeitsystem auch final freigegeben werden kann.

0
Stefab
Stefab08.06.0916:11
michaeljk: Obwohl, mir ist da nicht so ganz klar, wie ich diese xml-Dateien in RB reinhole, die OpenGL-Declares (wo auch alle Konstanten dabei sind) sind ganz normale RB-Module, die man entweder in sein Projekt kopiert, oder als externe Dateien verwendet. Diese lassen sich auch ganz normal in RB bearbeiten, somit sehe ich auch Auflistungen aller Befehle und Konstanten (wenn ich das will) und kann diese direkt bearbeiten. Aber irgendwie ist das ganze OT, evt, können wir uns woanders darüber unterhalten, evt. iChat?
0
Stefab
Stefab08.06.0916:40
ExMacRabbitPro: Wie kommst du darauf, das ich das Konzept von Zeigern nicht verstehe? Ich habe nie behauptet das foo ein String ist. Da man aber immer Objekte durch Zeiger benutzt, ist es geläufig diese zur Abkürzung einfach Objekte zu nennen. Darum schreibe ich ja nach dem ersten Satz: "(vereinfacht gesagt)"
Was ich nicht so genau weiß, ist wann der Speicher wieder freigegeben wird, vemutlich aber bei "[pool drain];", könnte ich mir denken.
Jedenfalls ist jetzt die eigentliche Frage geklärt. Auch wenn keine Zeiger mehr auf die alten String-Objekte zeigen, weiß Obj-C intern immer noch, wo diese liegen und kann sie auch wieder freigeben. Nur vor dieser Freigabe blockieren sie eben immer noch Speicher (und man kann nicht mehr darauf zugreifen)
Also führt das zu dem Schluss, entweder für jede "Änderung" (in Anführungszeichen, da es ja keine direkte Änderung ist, nur das Ergebnis ist das gleiche, wie bei einer Änderung) entweder neue NSString-Zeiger zu verwenden, oder eben gleich NSMutableString. Weil Speicher zu belegen, der nicht genutzt/angesprochen werden kann, ist wohl irgendwie sinnlos.

PS: Ich verstehe zwar noch nicht vollständig, wie man mit den Zeigern immer sauber arbeitet, aber ich denke das Grundprinzip von Zeigern schon.
0
ExMacRabbitPro08.06.0917:04
Stefab
ExMacRabbitPro: Wie kommst du darauf, das ich das Konzept von Zeigern nicht verstehe? Ich habe nie behauptet das foo ein String ist. Da man aber immer Objekte durch Zeiger benutzt, ist es geläufig diese zur Abkürzung einfach Objekte zu nennen. Darum schreibe ich ja nach dem ersten Satz: "(vereinfacht gesagt)"
Was ich nicht so genau weiß, ist wann der Speicher wieder freigegeben wird, vemutlich aber bei "[pool drain];", könnte ich mir denken.

Ok - da hatte ich wohl einen falschen Eindruck.

Der Speicher wird wie gesagt, dann freigegeben, wenn der deault Autorelese Pool freigegeben wird. Dass geschieht nach dem Durchlaufen des Run-Loops. Im prinzip also jedes mal, wenn die App einen User-Event (z.B. Button-Click) bearbeitet hat und die Kontrolle wieder an das Laufzeitsystem zurück gegeben wird. Hast Du keinen Run-Loop - z.B. bei einer simplen Terminal App mit einer einfachen main() Funktion, dann musst Du selbst einen Autorelease Pool erzeugen und am Ende auch freigeben.

Außerdem kann es sinnvoll sein, wenn innerhalb eines Run-Loop Zyklus von einer App sehr viele Objekte kurzzeitig erzeugt und dann nicht mehr gebraucht werden (z.B. in einer langen Iteration), eigene Autorelease Pools zu erzeugen und selbst zwischendurch Speicher freizugeben.

Dass gleiche macht man i.d.R. auch innerhalt eines Loops in einem Thread.


0
iCode
iCode08.06.0918:01
Jedenfalls ist jetzt die eigentliche Frage geklärt. Auch wenn keine Zeiger mehr auf die alten String-Objekte zeigen, weiß Obj-C intern immer noch, wo diese liegen und kann sie auch wieder freigeben.

Nein. Obj-C weiss das nicht. Es werden später nur die Objekte gelöscht die vorher dem Autoreleasepool hinzugefügt wurden.
0
dr.code09.06.0920:20
Wo ich gerade das hier sehe:
NSString *foo = @"Rabenau";
foo = [foo uppercaseString];
foo = [foo lowercaseString];
foo = [foo stringByAppendingString:@" geht badenau."];

Was ist der Unterschied zwischen:

NSString *foo = @"Rabenau";
NSString* foo = @"Rabenau";
NSString foo = @"Rabenau";

alles das gleiche? Theoretisch kann man den Stern doch direkt ans NSString machen?
0
kammerlander09.06.0920:34
NSString *foo = @"Rabenau";
NSString* foo = @"Rabenau";

Im Ergebniss das selbe.

NSString foo = @"Rabenau";

Das funktioniert nicht.
0
Stefab
Stefab16.06.0903:55
dr. code: Was ich so gelesen habe, werden Leerzeichen ignoriert, ausser natürlich an notwendigen Stellen, wo sie was trennen, wie zB. einem Methoden-Aufruf

bar = [foo uppercaseString];

Zwischen foo und uppercaseString darf mans natürlich nicht weglassen, aber ob:

NSString *foo = @"Rabenau";
oder
NSString* foo = @"Rabenau";
oder
NSString*foo=@"Rabenau";
oder
NSString * foo = @"Rabenau" ;

ist soweit egal.
0
Stefab
Stefab16.06.0903:57
Und dem Forum hier anscheinend auch, beim letzten Beispiel sind immer so einige Leerzeichen drin, selbst mit dem code-Tag klappt es nicht...
0
Stefab
Stefab16.06.0904:00
also so gehts natürlich auch und ist für den Compiler egal (muss eben ein Bild her):
0

Kommentieren

Diese Diskussion ist bereits mehr als 3 Monate alt und kann daher nicht mehr kommentiert werden.

OK MacTechNews.de verwendet Cookies unter anderem für personalisierte Inhalte, Seitenanalyse und bei der Auslieferung von Google-Anzeigen. Dies war zwar schon immer so, auf Wunsch der EU muss nun jedoch explizit darauf hingewiesen werden. Durch Nutzung der Website erklären Sie sich damit einverstanden. Weitere Informationen