Totale Anfängerfrage! Ich bitte um Verständnis

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

  • Totale Anfängerfrage! Ich bitte um Verständnis

    Anfängerfrage

    Sorry, Ihr Profis da draußen, wenn ich wahrscheinlich die total nervige Anfängerfrage stelle, aber ich drehe mich im Kreis und alle meine Bücher, Internetrecherchen bringen mir keine Antwort. Das bestätigt meinen Verdacht, dass ich irgendwas ganz und gar nicht kapiert habe in Objective C. Deshalb bitte ich nun hier um Gnade und natürlich einen inspirierenden Impuls.

    Mein Problem in Kürze: Wie kann ich während der Laufzeit meiner App auf ein selbst instanziertes Objekt einer selbst erstellten Klasse von allen möglichen Stellen aus zugreifen (außerhalb der Methode, mit der ich das Objekt erstellt habe).

    Das Problem im Detail:

    Meine eigene Klasse:

    Quellcode

    1. // RH_myClass01.h
    2. #import <Foundation/Foundation.h>
    3. @interface RH_myClass01 : NSObject
    4. // zwei Instanzvariablen als properties
    5. @property NSString *myClass01String;
    6. @property int myClass01Integer;
    7. // eine Methode, die einen int-Wert mit 100 multipliziert und zurückgibt
    8. - (int) multiply: (int) anyInteger;
    9. @end
    Alles anzeigen


    Dazu die passende Implementierung:

    Quellcode

    1. // RH_myClass01.m
    2. #import "RH_myClass01.h"
    3. @implementation RH_myClass01
    4. // zwei Instanzvariablen als properties
    5. @synthesize myClass01String;
    6. @synthesize myClass01Integer;
    7. // eine Methode, die den int-Wert mit 100 multipliziert und zurückgibt
    8. - (int) multiply: (int) anyInteger {
    9. return anyInteger * 100;
    10. }
    11. @end
    Alles anzeigen



    So weit so gut, ich kann nun auch ein Objekt erstellen im ViewController, aber was ich nicht kann, ist auf dieses Objekt dann auch zugreifen und zwar von außerhalb der Methode, mit der ich es erstellt habe.

    Zunächst die Einbindung mit @class in die Header-Datei:

    Quellcode

    1. // RH_ViewController.h#import <UIKit/UIKit.h>
    2. @class RH_myClass01;
    3. @interface RH_ViewController : UIViewController {
    4. }
    5. @end


    Dann die Implementierung (incl. Objekterstellung in der Methode „viewDidLoad“)

    Quellcode

    1. // RH_ViewController.m
    2. #import "RH_ViewController.h"
    3. #import "RH_myClass01.h"
    4. @interface RH_ViewController ()
    5. @end
    6. @implementation RH_ViewController
    7. - (void)viewDidLoad {
    8. [super viewDidLoad];
    9. // Do any additional setup after loading the view, typically from a nib.
    10. RH_myClass01 *myObjektOfClass01 = [[RH_myClass01 alloc] init];
    11. myObjektOfClass01.myClass01String = @"Teststring";
    12. myObjektOfClass01.myClass01Integer = 5;
    13. }
    Alles anzeigen


    Sobald ich von außerhalb dieser Methode auf das Objekt „myObjektOfClass01“ zugreifen möchte bekomme ich ein „nil“. Das ist das Prinzip der Verkapselung, habe ich schon verstanden, aber wie kann man dann beispielsweise in einer anderen Methode z.B. die Daten manipulieren, wenn sie gar nicht im Zugriff sind.

    Eine Antwort, die ich im Internet gefunden hatte, war „Instanzvariablen“, aber wenn ich im Interface eine gleichnamige Variable deklarieren will (myObjektOfClass01), dann bekomme ich in der Methode „viewDidLoad“ einen Hinweis „local declaration of instance hides ...“

    Uns so drehe ich mich im Kreis und bitte um Hilfe !

    Vielen Dank an alle, die sich bemühen, meinem Horizont entsprechend zu antworten: Ich bin seit zwei Wochen als Hobbyprogrammierer mit Xcode beschäftigt, habe Erfahrungen mit Visual Basic, aber auch das ist lange her.
    Meine Signatur: Wir sehen die Welt nicht wie sie ist, sondern wie wir sind ! :huh:

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von LukeSideWalker ()

  • Erstmal vorab ein "Willkommen im Forum" und eine Bitte an alle Neueinsteiger (bin doch selber fast noch einer):

    Hört bitte auf, Euch schon im vornherein für alles Mögliche zu entschuldigen: Etwas nicht zu wissen ist doch keine Schande, und Euch wird hier keiner den Kopf abreissen, wenn Ihr eine Frage stellt, die der ein oder andere Profi "banal" findet. Entscheidend ist nur, dass Ihr gegebene Antworten wirklich zu verstehen versucht und Eigeninitiative zeigt. Zumindest ist das meine Meinung ... Soweit das Wort zum Sonntag, nun weiter:

    LukeSideWalker schrieb:

    So weit so gut, ich kann nun auch ein Objekt erstellen im ViewController, aber was ich nicht kann, ist auf dieses Objekt dann auch zugreifen und zwar von außerhalb der Methode, mit der ich es erstellt habe.

    Das Entscheidende ist, dass Deine Variable myObjektOfClass01 nur lokal in der Methode viewDidLoad definiert ist. Wie soll also eine Methode ausserhalb die Speicheradresse des von Dir erzeugten Objektes kennen? Gar nicht. Deshalb ist Dein Ansatz mit einer Instanzvariablen (="ivar") schon vollkommen richtig: Der ViewController braucht eine ivar (oder einfacher direkt ein Property) vom Typ RH_myClass01, in der Du den Zeiger auf die Instanz der Klasse speicherst. Nennen wir diese mal auch myObjektOfClass01 (eine lokale Variable brauchst Du dann ja nicht mehr), dann kannst Du auf die Methoden dieses Objektes mit

    Quellcode

    1. [myObjektOfClass01 myClass01String]

    oder

    Quellcode

    1. myObjektOfClass01.myClass01String

    zugreifen.

    HTH, Mattes

    P.S.: Als Code formatiert werden Programmstücke wesentlich leichter lesbar...
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Erst einmal will ich Mattes' ersten Absatz unterstreichen.

    Sein Ansatz ist auch richtig. Der Fehler, den du bekommst, hat eine bestimmte Ursache. Nehmen wir an, dass du eine Instanzvariable mit den Namen var hast. Dabei spielt es keine Rolle, ob du die explizit deklarierst oder über ein @synthesize:

    Quellcode

    1. @interface MyClass : NSObject
    2. @property (copy) NSString* var; // Dies synthetisiert KEINE Instanzvariable. Wirf alle Bücher weg, die das behaupten.
    3. @end

    Quellcode

    1. @implementation MyClass
    2. @synthesize var; // Hier wird eie Instanzvariable deklariert.
    3. - (void)method
    4. {
    5. NSString *var; // Hier eine lokale Variable: Fehler
    6. var = @"Amin";
    7. }
    8. @end

    Das Problem liegt darin, dass es in -method zwei Variablen mit dem Namen var gibt: Die Instanzvariable, die in jeder Methode sichtbar ist (das wilst du ja) und die lokale Varable, die du gleich eingangs der Methode definierst. IN der Zuweisung in der nächsten Zeile ist nicht mehr ganr klar, ob das nun an die lokale Variable oder an die Instanzvariable gehen soll. Der Compiler entscheidet sich für die lokale Variable. Die Instanzvariable ist daher i -method nicht mehr ereichbar. Die lokale Variable verdeckt sozusagen die Instanzvariable: "shadows".

    Eigentlich ist das gar nicht einmal so schlimm, weil du außerhalb von Settern ohnehin nie auf die Instanzvariablen zugreifen willst. Der Coder, der an eine Instanzvariable etwas zuweist läuft daher immer über einen Setter:

    Quellcode

    1. - (void)method
    2. {
    3. NSString *var; // Hier eine lokale Variable: Fehler
    4. var = @"Amin"; // Das solte lokal sein
    5. self.var = @"Amin"; // Das geht an die Instanzvariable
    6. }

    Der Compiler vermutet also richtig, findet das aber gefährlich. Löschst du die Deklaration der lokalen Variable, ist der Code immer noch übersetzbar, obwohl er jetzt etwas ganz anderes tut.
    Um also diesen Namenskonklikt zu vermeiden und zu verhindern, dass man versehentlich auf INstanzvariablen zugreift, nennt man diese anders als die Eigenschaft. Das geht auch ganz einfach:

    Quellcode

    1. @implementation MyClass
    2. @synthesize var = _var; // Hier wird die Instanzvariable _var (aber nicht: var) deklariert.
    3. - (void)method
    4. {
    5. NSString *var; // Kein Fehler, die lokale Variable heißt var, die Instanzvariable _var
    6. var = @"Amin"; // Es ist klar, dass die lokale Variable gemeint ist
    7. }
    8. @end
    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"?
  • Vielen Dank an alle!

    Hallo Zusammen,

    vielen dank, ich bin happy, es hat jetzt alles geklappt. Die Antwort, die mir allerdings am schnellsten geholfen hat, war die von Florian, er hat erkannt, dass ich bei der Instanzierung meines Objektes einen leicht falsche Programmierung gewählt habe:

    Falsch war:

    Quellcode

    1. RH_myClass01 *myObjektOfClass01 = [[RH_myClass01 alloc] init];


    Richtig ist (bei Instanzvariablen):

    Quellcode

    1. myObjektOfClass01 = [[RH_myClass01 alloc] init];


    Vielen Dank für die weiteren Erklärungen
    und das mit den Code-Tags habe ich jetzt auch verstanden !

    Schönen Abend alle Zusammen! :thumbsup:
    Meine Signatur: Wir sehen die Welt nicht wie sie ist, sondern wie wir sind ! :huh:
  • Und noch ein Nachtrag: mache Dich mit den Cocoa-Namenskonventionen vertraut. Die sind nicht nur schmückendes Beiwerk, sondern werden für eine das Framework durchziehende Technik (Key-Value-Coding) benötigt. Abgesehen davon erhöht ihre Befolgung die Lesbarkeit Deines Codes ganz erheblich.

    Ach ja: Willkommen im Forum!
  • LukeSideWalker schrieb:

    Hallo Zusammen,

    vielen dank, ich bin happy, es hat jetzt alles geklappt. Die Antwort, die mir allerdings am schnellsten geholfen hat, war die von Florian, er hat erkannt, dass ich bei der Instanzierung meines Objektes einen leicht falsche Programmierung gewählt habe:

    Falsch war:

    Quellcode

    1. RH_myClass01 *myObjektOfClass01 = [[RH_myClass01 alloc] init];


    Richtig ist (bei Instanzvariablen):

    Quellcode

    1. myObjektOfClass01 = [[RH_myClass01 alloc] init];


    Vielen Dank für die weiteren Erklärungen
    und das mit den Code-Tags habe ich jetzt auch verstanden !

    Schönen Abend alle Zusammen! :thumbsup:

    Das ist leider nicht richtig, wenngleich in diesem Falle unerheblich. Richtig wäre:

    Quellcode

    1. self.myObjektOfClass01 = [[RH_myClass01 alloc] init];
    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"?