• Apfeltalk ändert einen Teil seiner Allgemeinen Geschäftsbedingungen (AGB), das Löschen von Useraccounts betreffend.
    Näheres könnt Ihr hier nachlesen: AGB-Änderung
  • Was gibt es Schöneres als den Mai draußen in der Natur mit allen Sinnen zu genießen? Lasst uns teilhaben an Euren Erlebnissen und macht mit beim Thema des Monats Da blüht uns was! ---> Klick

Instanzvariable hat immer den Wert 0!

reeng

Granny Smith
Registriert
30.08.10
Beiträge
13
Hallo zusammen

Ich wäre super froh, wenn Jemand bei meinem Problem behilflich sein könnte. Ich habe einen TableViewController (BooksTableViewController) erstellt. In diesem Controller befinden sich fünf Elemente in der Tabelle. Beim Klicken auf ein Element gelangt man zur Detail-Ansicht dieses Elementes ==> BookDetailViewController, welcher ein normaler ViewController ist. Nun habe ich in BooksTableViewController eine Instanzvariable deklariert. Folgende der Auszug von meinem BooksTableViewController.h File (Nur der String rowName ist hier meine Anliegen):
Code:
#import <UIKit/UIKit.h>
@class BookDetailViewController;


@interface BooksTableViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource> {
	IBOutlet UITableView * booksTableView;
	NSMutableArray *booksArray;
	BookDetailViewController *bookDetailViewController;
	NSString *rowName; 
	
	
}

@property (nonatomic, retain) NSMutableArray *booksArray;
@property (nonatomic, retain) BookDetailViewController *bookDetailViewController;
@property (readwrite) NSString *rowName; 
@end

Im BooksTableViewController.m File habe ich dann Folgende Zeilen geschrieben:
Code:
self.rowName = [NSString stringWithFormat:@"%@",[booksArray objectAtIndex:row]];
NSLog([NSString stringWithFormat:@"%@",self.rowName]);
Die NSLog Zeile schreibt mir nun erfolgreich den Inhalt der ausgewählten Zelle ins Terminal bzw. der Inhalt der Zelle wird erfolgreich in meine Instanzvariable rowName dieser Klasse gespeichert.

Nun möchte ich ein Objekt dieser Klasse in BookDetailViewController erzeugen. Folgend der Auszug aus dem BookDetailViewController.h File:
Code:
#import <UIKit/UIKit.h>
#import "BooksTableViewController.h"


@interface BookDetailViewController : UIViewController {
	BooksTableViewController *booksTableViewController;

}
@property (nonatomic, retain) BooksTableViewController *booksTableViewController;
-(void) loadView;


@end

Zu Aller Letzt noch der Auszug aus der loadView-Methode vom BookDetailViewController.m File:
Code:
-(void)loadView{ //Manuell ergänzt;

	BooksTableViewController *booksTableViewController = [[BooksTableViewController alloc] init]; 	
	NSLog(@"%d",booksTableViewController.rowName); 
		  
}

Und hier ist mein Problem. Im Terminal sollte doch nun von der NSLog-Zeile aus der Inhalt der angetippten Zelle stehen, wie es bereits in der Klasse BooksTableViewController der Fall war?! Leider steht dort jedoch 8 mal untereinander "2010-09-13 17:14:33.476 ORBooks[948:207] 0"
Vielleicht ist mein Problem trivial und man muss nur irgendwie die Instanzvariable eine Art global / public setzen, wie es bei Java auch der Fall ist, oder ich habe einfach einen dumme Fehler übersehen. Ich entschuldige mich für die vielen Code-Schnipsel, welche ich hier gepostet habe, hoffe jedoch, dass mir Jemand weiterhelfen kann.

Vielen Dank im Voraus

Gruss aus der Schweiz

reeng
 

MacApple

Schöner von Bath
Registriert
05.01.04
Beiträge
3.652
Code:
-(void)loadView{ //Manuell ergänzt;

	BooksTableViewController *booksTableViewController = [[BooksTableViewController alloc] init]; 	
	NSLog(@"%d",booksTableViewController.rowName); 
		  
}

Und hier ist mein Problem. Im Terminal sollte doch nun von der NSLog-Zeile aus der Inhalt der angetippten Zelle stehen, wie es bereits in der Klasse BooksTableViewController der Fall war?!
Warum sollte das der Fall sein? Du erzeugst hier eine neue Instanz. Die hat aber nichts mit der Instanz zu tun, die die Tabelle auf dem Bildschirm verwaltet.

MacApple
 

reeng

Granny Smith
Registriert
30.08.10
Beiträge
13
Hallo MacApple

Vielen Dank für deine rasche Antwort. Ok, verstehe ich. Wie kann ich dann mein Anliegen praktisch umsetzen? Gibt es keine globale Variablen, die ich verwenden kann, bis das Programm wieder geschlossen wird (Variablen die ich von jeder Klasse aus verwenden kann)? Ich wäre super froh um eine kurze Erklärung, wie ich den Inhalt von rowName in die neue Klasse übernehmen kann. Bin leider noch ziemlich neu in der Mac- bzw. OOP-Welt.

Gruss

reeng
 

Poljpocket

Salvatico di Campascio
Registriert
07.01.07
Beiträge
432
Die Mac-Welt hat direkt nichts mit OOP zu tun! Es gibt viele OOP-Sprachen, welche auch auf Windows/Linux und Anderen Plattformen weit verbreitet sind (C++, VB, Java, ...).

Nun, globale Instanzen sind nicht direkt die Idee von OOP. Du solltest jedem Objekt nur diese Instanzen direkt zur Verfügung stellen, die es auch benötigt. Ich mache das meistens über die init-Methoden (also diese überschreiben). Dann kann ich einem Table-Controller zum Beispiel das Array mit den Daten für die Tabelle übergeben. Mehr braucht dieser Controller ja nicht.

Das heisst nicht, dass globale Instanzen nicht möglich sind! Du musst sie nur ausserhalb des @implementation definieren und dann im Header mittels dem keyword 'extern' auch noch deklarieren, damit dann alle Klassen, welche diesen Header importieren, die Instanz kennen.

Gruss ppocket
 

reeng

Granny Smith
Registriert
30.08.10
Beiträge
13
Hallo zusammen

Danke für eure Feedbacks. Im Nachhinein ist es mir völlig klar, wieso mein Versuch nicht funktioniert hat. Ich habe nun zwei alternative Lösungen gefunden:

1.Variante:
Bei der Klasse BookDetailViewController habe ich eine Instanzvariable und die dazugehörige Set-Methode (setRowname: ) hinzugefügt. Nach dem Instanzieren des Objects bookDetailViewController in der Klasse BooksTableViewController kann ich nun mit [bookDetailViewController setRowname:[booksArray objectAtIndex:row]]; meine ausgewählte Zelle dem neuen ViewController übergeben und damit weiter Arbeiten (z.B. für ein Label-Text)

2. Variante:
Bevor der bookDetailViewController geladen wird, schreib ich mir den Inhalt der ausgewählten Zelle in ein .txt-File. Beim Laden des ViewController in der viewDidLoad-Methode, lade ich mir den Inhalt des Text-Files wieder in ein NSString und kann damit weiterarbeiten (z.B. für ein Label-Text)

Ist die letztere Variante eher eine unschöne Lösung, verstösst sie gegen den guten Programmierstiel, oder wird diese Variante öfters eingesetzt?

Gruss

reeng
 

MacApple

Schöner von Bath
Registriert
05.01.04
Beiträge
3.652
Ist die letztere Variante eher eine unschöne Lösung,
Ja.
verstösst sie gegen den guten Programmierstiel,
Ja.
oder wird diese Variante öfters eingesetzt?
Nein.
Die letzte Variante ist nicht nur eine unschöne Lösung, sie ist sogar noch schlimmer als globale Variablen. Stell Dir mal vor, diese Art von Parameterübergabe innerhalb eines Programms wäre „üblich“, was meinst Du, wie beschäftigt die Festplatte in Deinem Rechner wäre und wie langsam dadurch Dein Programm laufen würde. Daten im RAM hin und her zu schieben ist wesentlich schneller, als sie über die Festplatte zu wuchten.
Die erste Variante ist der korrekte Weg.

MacApple
 

reeng

Granny Smith
Registriert
30.08.10
Beiträge
13
Hallo MacApple

Vielen Dank für deinen Tipp. Nun habe ich aber noch folgende Ungewissheit: Als Root Controller verwende ich eine UITabBar. Im ersten Tab oben rechts habe ich einen Button platziert, welcher mir im AppDelegate einen weiteren ViewController (testViewController) mit [window addSubview:testViewController] ladet. In diesem testViewController habe ich ein Textfeld und ein Button oben Links mit dem man durch den Aufruf von [self.view removeFromSuperview] wieder zum rootController bzw. zur TabBar zurückkehren kann. Den eingegebenen Text im Textfeld wird durch den Klick auf den Button zurück in eine Instanzvariable NSString *textFeldText von testViewController gespeichert. Nun zu meiner Frage: Wie ist es mir nun möglich, dass ich diesen eingegebenen Text bzw. die Variable textFeldText von jeder Klasse bzw. jedem ViewController aus abfragen kann? Wenn ich ja in einem anderen ViewController eine Instanz von testViewCOntroller erstelle, bin ich wieder beim Ursprungsproblem von diesem Thema. Bei der Variante mit dem .txt-File wäre dies überhaupt kein Problem. Könnte hier auch Core-Data weiterhelfen, damit ich solche Informationen wie von diesem Textfeld von überall aus erreichen kann?
Ich hoffe du verstehst mein Problem und kannst mir weiterhelfen.

Danke im Voraus und beste Grüsse aus der Schweiz

reeng
 

MacApple

Schöner von Bath
Registriert
05.01.04
Beiträge
3.652
Wie ist es mir nun möglich, dass ich diesen eingegebenen Text bzw. die Variable textFeldText von jeder Klasse bzw. jedem ViewController aus abfragen kann?
Ich glaube, Du solltest Dich mal grundsätzlich mit objektorientierter Programmierung beschäftigen. Objektorientiert Programmieren bedeutet unter Anderem, Daten zu kapseln und eben nicht global im Zugriff zu haben. Deshalb kann man auch nicht einfach so drauf los programmieren (sollte man eh generell nicht), sondern man muss sich schon ein paar Gedanken machen, wo brauche ich welche Daten und wie verpacke ich die dann in Objekte. In Cocoa (Touch) wird auch das Model-View-Controller Prinzip konsequent genutzt. Schau Dir das auch an.

Wenn ich ja in einem anderen ViewController eine Instanz von testViewCOntroller erstelle, bin ich wieder beim Ursprungsproblem von diesem Thema. Bei der Variante mit dem .txt-File wäre dies überhaupt kein Problem. Könnte hier auch Core-Data weiterhelfen, damit ich solche Informationen wie von diesem Textfeld von überall aus erreichen kann?
Wenn man mal Deine Textdatei als „Model“ betrachtet, dann bist Du schon fast auf dem richtigen Weg zum MVC-Prinzip. Du kannst dann aber Deine Textdatei eben durch ein „Model“-Objekt ersetzen, welches die Daten Deines Programms verwaltet. Dein Model kannst Du zum Beispiel auch mit Core Data erstellen. Kommt halt auf das Datenmodel an, ob Core Data passt oder vielleicht doch schon zu oversized ist.

MacApple
 

Pink_Panter

Jonagold
Registriert
05.07.10
Beiträge
19
Hi.
Ich habe das gleiche Problem. Ich möchte eine Variable die in einem View eingegeben wird in einen anderen zum Weiterverarbeiten übergeben.
Ich bin aber aus deiner Lösung nicht so recht schlau geworden.
Ich habe in View1 eine NSString Variable v1 deklariert. Mit property und syntesize usw. Die befülle ich dann mit einem String. In View2 habe ich dann eine neue Variable v2 wie die oben deklariert und #import View1 in die .m Datei geschrieben. Im Viewdidload möchte ich dann mit v2=View1.v1; den Wert übergeben.
Das scheitert aber: "Accessing unknown v1 class method".
Wo liegt mein Fehler?
Gruß
PP
 

MacApple

Schöner von Bath
Registriert
05.01.04
Beiträge
3.652
Im Viewdidload möchte ich dann mit v2=View1.v1; den Wert übergeben.
Das scheitert aber: "Accessing unknown v1 class method".
Wo liegt mein Fehler?
Der Fehler ist, dass Du versuchst über das Klassenobjekt "View1" auf die Property "v1" zuzugreifen. Klassenobjekte haben keine Properties. Du musst schon auf die Instanz von "View1" zugreifen.

MacApple
 

Pink_Panter

Jonagold
Registriert
05.07.10
Beiträge
19
OK.
Funktioniert das so?
In der .h von View2
View1 *view1Instanz;

Und dann in der .m
v2=view1Instanz.v1;

Wie muss ich dann mit view1Instanz weiterverfahren um sie korrekt zu initiieren?
 

Pink_Panter

Jonagold
Registriert
05.07.10
Beiträge
19
Da bin ich mir nicht ganz sicher. geht das so?

View1 *view1Instanz=[[View1 alloc]init];

View1 wird doch erst in der.m mit import eingebunden, kann die .h darauf überheupt schon zugreifen?

PP
 

MacApple

Schöner von Bath
Registriert
05.01.04
Beiträge
3.652
Da bin ich mir nicht ganz sicher. geht das so?

View1 *view1Instanz=[[View1 alloc]init];
Nein, das wird nicht gehen. So erzeugst Du eine neue Instanz von View1. Diese neue Instanz hat dann nichts mit der Instanz zu tun, auf die Du eigenlich zugreifen wolltest.

View1 wird doch erst in der.m mit import eingebunden, kann die .h darauf überheupt schon zugreifen?
Dateien greifen nirgends drauf zu. In den Headerdateien stehen nur Deklarationen und in den .m Dateien steht lediglich Code, der zur Laufzeit des Programms ausgeführt wird. Im compilierten Programm gibt es keine .h und .m Dateien mehr. Da gibt es nur noch Objekte und ausführbaren Code.

MacApple
 

Pink_Panter

Jonagold
Registriert
05.07.10
Beiträge
19
OK......., dann stehe ich auf dem Schlauch....
View1 *view1Instanz=View1; Währe das Einzige was mir noch einfallen würde.
Für eine Lösung währe ich dankbar.
 

MacApple

Schöner von Bath
Registriert
05.01.04
Beiträge
3.652
Die Lösung wäre, dass Du Dich mal mit Grundlagen befasst. Du stocherst da im Nebel rum. View1 hast Du doch sicher irgendwo schon mal erzeugt. Vielleicht im Interface Builder. Diese Instanz musst Du zuweisen. Das kannst Du eventuell auch per Outlet machen. Das hängt halt davon ab, wie Dein Projekt aufgebaut ist. Es gibt da keinen Universalweg.

MacApple
 

Pink_Panter

Jonagold
Registriert
05.07.10
Beiträge
19
Den Interface Builder nutze ich um die Elemente anzuordnen und die Verknüpfungen zwischen den Elementen und den Methoden zu erzeugen.
Den ViewController lege ich als UIViewController subview an und lasse die .xib mit erzeugen. In der Header-Datei dann:
@interface MeineDaten : UIViewController {...}
@end
Die Views sind in einem Navigation Controller verbaut und werden dann so instanziiert:
View1 *view1=[[View alloc] initWithNibName:mad:"View1" bundle:nil];
[self.navigationController pushViewController:view1 animated:YES];
[view1 release];

Somit währe view1 die Instanz von View1, richtig? Folglich müsste die Zuweisung der Instanz auf die Variable
View1 *view1Instanz=view1;
sein, oder?
 

MacApple

Schöner von Bath
Registriert
05.01.04
Beiträge
3.652
Den Interface Builder nutze ich um die Elemente anzuordnen und die Verknüpfungen zwischen den Elementen und den Methoden zu erzeugen.
Dazu ist der ja auch da.

Den ViewController lege ich als UIViewController subview an und lasse die .xib mit erzeugen.
Ein ViewController kann kein Subview sein. Er kann nur einen Subview verwalten.

In der Header-Datei dann:
@interface MeineDaten : UIViewController {...}
@end
Die Views sind in einem Navigation Controller verbaut und werden dann so instanziiert:
View1 *view1=[[View alloc] initWithNibName:mad:"View1" bundle:nil];
[self.navigationController pushViewController:view1 animated:YES];
[view1 release];

Somit währe view1 die Instanz von View1, richtig? Folglich müsste die Zuweisung der Instanz auf die Variable
View1 *view1Instanz=view1;
sein, oder?
  1. Was ist hier „View“ jetzt wieder?
  2. Ein View kennt keine Methode initWithNibName:bundle:. Der „designated initializer“ eines Views ist initWithFrame:.
  3. Wegen 2. kann „view1“ nicht die gesuchte View-Instanz sein.

Wie gesagt, Du stocherst da wild im Nebel rum. Das bringt nichts. Befasse dich mit den Grundlagen. Bei Apple gibt es einige einführende Guides zu den Konzepten von Cocoa (Touch).

MacApple
 

Tankman

Jonagold
Registriert
23.06.08
Beiträge
21
Ich habe gerade irgendwie das selbe Problem.
Ich habe ein SplitView Projekt erzeugt, welches ich im InterfaceBuilder ein wenig abgeändert habe.
Jetzt funktioniert das Ganze nicht mehr.
Die GUI des DetailViews aktualisiert sich nicht mehr.
Wie kann ich auf die Instanz des DetailView zugreifen?
Ich habe hier mal den Code, vielleicht kann mir ja jemand weiterhelfen, denn ich hänge an diesem Problem jetzt schon 3 Tage.
Anhang anzeigen Project.zip