Kommunikation zwischen TextField und Label in verschiedenen Klassen

NGLocanovic

Neues Mitglied
Thread Starter
Dabei seit
09.09.2013
Beiträge
5
Reaktionspunkte
0
Zu allererst "Hallo" an die MacUser-Community!
Ich habe erst seit kurzem einen Mac und will langsam in der Mac/iOS-Programmierung einsteigen.

Jetzt stellt sich mir ein (bestimmt) sehr simples Problem in den Weg.
Meine "App" habe ich aufs wesentliche reduziert, um es leicht verständlich zu machen.
Mein Vorhaben:
Ich möchte mit dem TextField (und dem Button) der "SecondViewController"-Klasse das Label der "FirstViewController"-Klasse ändern. Ich habe Verschiedenstes probiert - Ergebnis immer ernüchternd. Meine Vermutung ist, dass die FirstViewController-Klasse nicht die Berechtigung hat das Textfeld auszulesen

Dies ist mein letzter Versuch gewesen:


Code:
FirstViewController.h

[COLOR=#D12F1B][FONT=Menlo][COLOR=#78492a]#import [/COLOR]<UIKit/UIKit.h>[/FONT][/COLOR]
[FONT=Menlo]
[/FONT]
[FONT=Menlo][COLOR=#bb2ca2]@interface[/COLOR] FirstViewController : [COLOR=#703daa]UIViewController[/COLOR][/FONT]
[FONT=Menlo]
[/FONT]
[COLOR=#BB2CA2][FONT=Menlo]@property[COLOR=#000000] ([/COLOR]weak[COLOR=#000000], [/COLOR]nonatomic[COLOR=#000000]) [/COLOR]IBOutlet[COLOR=#703daa]UILabel[/COLOR][COLOR=#000000] *label;[/COLOR][/FONT][/COLOR]
[FONT=Menlo]
[/FONT]
[COLOR=#BB2CA2][FONT=Menlo]@end[/FONT][/COLOR]

Code:
FirstViewController.m
[COLOR=#D12F1B][FONT=Menlo][COLOR=#78492a]#import [/COLOR]"FirstViewController.h"[/FONT][/COLOR]
[FONT=Menlo]
[/FONT]
[COLOR=#4F8187][FONT=Menlo][COLOR=#bb2ca2]@interface[/COLOR]FirstViewController[COLOR=#000000] ()[/COLOR][/FONT][/COLOR]
[FONT=Menlo]
[/FONT]
[COLOR=#BB2CA2][FONT=Menlo]@end[/FONT][/COLOR]
[FONT=Menlo]
[/FONT]
[FONT=Menlo][COLOR=#bb2ca2]@implementation[/COLOR] FirstViewController[/FONT]
[FONT=Menlo]
[/FONT]
[FONT=Menlo]- ([COLOR=#bb2ca2]void[/COLOR])viewDidLoad[/FONT]
[FONT=Menlo]{[/FONT]
[COLOR=#3D1D81][FONT=Menlo][COLOR=#000000]    [[/COLOR][COLOR=#bb2ca2]super[/COLOR]viewDidLoad[COLOR=#000000]];[/COLOR][/FONT][/COLOR]
[COLOR=#008400][FONT=Menlo]// Do any additional setup after loading the view, typically from a nib.[/FONT][/COLOR]
[FONT=Menlo]}[/FONT]
[FONT=Menlo]
[/FONT]
[FONT=Menlo]- ([COLOR=#bb2ca2]void[/COLOR])didReceiveMemoryWarning[/FONT]
[FONT=Menlo]{[/FONT]
[COLOR=#3D1D81][FONT=Menlo][COLOR=#000000]    [[/COLOR][COLOR=#bb2ca2]super[/COLOR]didReceiveMemoryWarning[COLOR=#000000]];[/COLOR][/FONT][/COLOR]
[COLOR=#008400][FONT=Menlo]// Dispose of any resources that can be recreated.[/FONT][/COLOR]
[FONT=Menlo]}[/FONT]
[FONT=Menlo]
[/FONT]
[COLOR=#BB2CA2][FONT=Menlo]@end[/FONT][/COLOR]

Code:
SecondViewController.h
[COLOR=#D12F1B][FONT=Menlo][COLOR=#78492a]#import [/COLOR]<UIKit/UIKit.h>[/FONT][/COLOR]
[COLOR=#D12F1B][FONT=Menlo][COLOR=#78492a]#import [/COLOR]"FirstViewController.h"[/FONT][/COLOR]
[FONT=Menlo]
[/FONT]
[COLOR=#703DAA][FONT=Menlo][COLOR=#bb2ca2]@interface[/COLOR][COLOR=#000000] SecondViewController : [/COLOR]UIViewController[COLOR=#000000] <[/COLOR]UITextFieldDelegate[COLOR=#000000]>[/COLOR][/FONT][/COLOR]
[FONT=Menlo]
[/FONT]
[COLOR=#BB2CA2][FONT=Menlo]@property[COLOR=#000000] ([/COLOR]weak[COLOR=#000000], [/COLOR]nonatomic[COLOR=#000000]) [/COLOR]IBOutlet[COLOR=#703daa]UITextField[/COLOR][COLOR=#000000] *TextField;[/COLOR][/FONT][/COLOR]
[FONT=Menlo]
[/FONT]
[FONT=Menlo]- ([COLOR=#bb2ca2]IBAction[/COLOR])Button:([COLOR=#703daa]UIButton[/COLOR] *)sender;[/FONT]
[FONT=Menlo]
[/FONT]
[COLOR=#BB2CA2][FONT=Menlo]@end[/FONT][/COLOR]

Code:
SecondViewController.m
[COLOR=#D12F1B][FONT=Menlo][COLOR=#78492a]#import [/COLOR]"SecondViewController.h"[/FONT][/COLOR]
[FONT=Menlo]
[/FONT]
[COLOR=#4F8187][FONT=Menlo][COLOR=#bb2ca2]@interface[/COLOR]SecondViewController[COLOR=#000000] ()[/COLOR][/FONT][/COLOR]
[FONT=Menlo]
[/FONT]
[COLOR=#BB2CA2][FONT=Menlo]@end[/FONT][/COLOR]
[FONT=Menlo]
[/FONT]
[FONT=Menlo][COLOR=#bb2ca2]@implementation[/COLOR] SecondViewController[/FONT]
[FONT=Menlo]
[/FONT]
[FONT=Menlo]- ([COLOR=#bb2ca2]void[/COLOR])viewDidLoad[/FONT]
[FONT=Menlo]{[/FONT]
[COLOR=#3D1D81][FONT=Menlo][COLOR=#000000]    [[/COLOR][COLOR=#bb2ca2]super[/COLOR]viewDidLoad[COLOR=#000000]];[/COLOR][/FONT][/COLOR]
[COLOR=#008400][FONT=Menlo]// Do any additional setup after loading the view, typically from a nib.[/FONT][/COLOR]
[FONT=Menlo]}[/FONT]
[FONT=Menlo]
[/FONT]
[FONT=Menlo]- ([COLOR=#bb2ca2]void[/COLOR])didReceiveMemoryWarning[/FONT]
[FONT=Menlo]{[/FONT]
[COLOR=#3D1D81][FONT=Menlo][COLOR=#000000]    [[/COLOR][COLOR=#bb2ca2]super[/COLOR]didReceiveMemoryWarning[COLOR=#000000]];[/COLOR][/FONT][/COLOR]
[COLOR=#008400][FONT=Menlo]// Dispose of any resources that can be recreated.[/FONT][/COLOR]
[FONT=Menlo]}[/FONT]
[FONT=Menlo]
[/FONT]
[FONT=Menlo]-([COLOR=#bb2ca2]BOOL[/COLOR])textFieldShouldReturn:([COLOR=#703daa]UITextField[/COLOR] *)textField[/FONT]
[FONT=Menlo]{[/FONT]
[COLOR=#3D1D81][FONT=Menlo][COLOR=#000000]    [textField [/COLOR]resignFirstResponder[COLOR=#000000]];[/COLOR][/FONT][/COLOR]
[COLOR=#BB2CA2][FONT=Menlo]returnYES[COLOR=#000000];[/COLOR][/FONT][/COLOR]
[FONT=Menlo]}[/FONT]
[FONT=Menlo]
[/FONT]
[FONT=Menlo]- ([COLOR=#bb2ca2]IBAction[/COLOR])Button:([COLOR=#703daa]UIButton[/COLOR] *)sender {[/FONT]

[COLOR=#4F8187][FONT=Menlo]FirstViewController[COLOR=#000000] *firstView = [[[/COLOR]FirstViewController[COLOR=#3d1d81]alloc[/COLOR][COLOR=#000000]] [/COLOR][COLOR=#3d1d81]init[/COLOR][COLOR=#000000]];[/COLOR][/FONT][/COLOR]

[FONT=Menlo]    firstView.[COLOR=#4f8187]label[/COLOR].[COLOR=#703daa]text[/COLOR] = [COLOR=#bb2ca2]self[/COLOR].[COLOR=#4f8187]TextField[/COLOR].[COLOR=#703daa]text[/COLOR];[/FONT]

[FONT=Menlo]}[/FONT]

Ich hoffe auf positive Antwort und entschuldige mich schonmal vorab falls es das Thema schon dutzendfach gibt. Ich wusste einfach nicht welches Schlagwort mein Problem beschreibt :/
Viele Grüße
NG_Locanovic
 
Hallo NG_Locanovic,

zuerst mal was am Rande:

Code:
SecondViewController.h
[COLOR=#D12F1B][FONT=Menlo][COLOR=#78492a]#import [/COLOR]"FirstViewController.h"[/FONT][/COLOR]
[...]
[FONT=Menlo]- ([COLOR=#bb2ca2]IBAction[/COLOR])Button:([COLOR=#703daa]UIButton[/COLOR] *)sender;[/FONT]

Methodennamen werden per Konvention immer mit einem kleinen Buchstaben am Anfang benannt, und Klassen für gewöhnlich im Implementationsfile importiert, nicht im Header. Wenn du den Namen einer Klasse im Header bekannt machen möchtest, kannst du das mit @class machen. Macht Apple auch so: Schau mal in den AppDelegate Header ;)

Zum Problem selbst: in der Button: Methode definierst du einen neuen FirstViewController. Ich sehe allerdings nirgends, dass du firstView (dass besser firstVC oder ähnlich heißen sollte, da eine "View" etwas anderes als ein "View Controller" ist und das so zu Verwirrung führt) irgendwann mal auf den Bildschirm geschickt hättest. Ich tippe mal, dass dieses zweite Label erst gar nicht auftaucht, oder? Was den Button angeht, so musst du ein @property in der SecondViewController Klasse erstellen, wie du es auch für das UITextField getan hast. Danach kannst du die Beschriftung des Buttons mit Hilfe von button.titleLabel.text ändern.


Gruß Jörg
 
Zum Problem selbst: in der Button: Methode definierst du einen neuen FirstViewController. Ich sehe allerdings nirgends, dass du firstView (dass besser firstVC oder ähnlich heißen sollte, da eine "View" etwas anderes als ein "View Controller" ist und das so zu Verwirrung führt) irgendwann mal auf den Bildschirm geschickt hättest. Ich tippe mal, dass dieses zweite Label erst gar nicht auftaucht, oder? Was den Button angeht, so musst du ein @property in der SecondViewController Klasse erstellen, wie du es auch für das UITextField getan hast. Danach kannst du die Beschriftung des Buttons mit Hilfe von button.titleLabel.text ändern.

Hallo Jörg,
Vielen Dank erstmal für deine Antwort und für den Tipp, ich werde mich daran halten ;)

Das Problem ist leider noch nicht gelöst (vielleicht hab ich auch wieder was falsch gemacht).
Meine SecondViewController.h sieht jetzt folgendermaßen aus:
Code:
[COLOR=#78492A][FONT=Menlo]#import [/FONT][/COLOR][COLOR=#D12F1B][FONT=Menlo]<UIKit/UIKit.h>[/FONT][/COLOR][COLOR=#D12F1B][FONT=Menlo][COLOR=#78492a]#import [/COLOR]"FirstViewController.h"[/FONT][/COLOR]
[FONT=Menlo]
[/FONT]
[COLOR=#703DAA][FONT=Menlo][COLOR=#bb2ca2]@interface[/COLOR][COLOR=#000000] SecondViewController : [/COLOR]UIViewController[COLOR=#000000] <[/COLOR]UITextFieldDelegate[COLOR=#000000]>[/COLOR][/FONT][/COLOR]
[FONT=Menlo]
[/FONT]
[COLOR=#BB2CA2][FONT=Menlo]@property[COLOR=#000000] ([/COLOR]weak[COLOR=#000000], [/COLOR]nonatomic[COLOR=#000000]) [/COLOR]IBOutlet[COLOR=#703daa]UITextField[/COLOR][COLOR=#000000] *TextField;[/COLOR][/FONT][/COLOR]
[COLOR=#BB2CA2][FONT=Menlo]@property[COLOR=#000000] ([/COLOR]weak[COLOR=#000000], [/COLOR]nonatomic[COLOR=#000000]) [/COLOR]IBOutlet[COLOR=#703daa]UIButton[/COLOR][COLOR=#000000] *button;[/COLOR][/FONT][/COLOR]
[FONT=Menlo]
[/FONT]
[FONT=Menlo]- ([COLOR=#bb2ca2]IBAction[/COLOR])button:([COLOR=#703daa]UIButton[/COLOR] *)sender;[/FONT]
[FONT=Menlo]
[/FONT]
[COLOR=#BB2CA2][FONT=Menlo]@end[/FONT][/COLOR]

Aber ich will ja jetzt auch nicht den Titel des Buttons, sondern den Text des Labels vom FirstViewController ändern. Ich füg mal Bilder des Projekts ein. Vielleicht hilft das ja ;)

http://abload.de/img/1ola2i.jpg
http://abload.de/img/20uzl1.jpg
 
Hallo Jörg,
Vielen Dank erstmal für deine Antwort und für den Tipp, ich werde mich daran halten ;)

Aber ich will ja jetzt auch nicht den Titel des Buttons, sondern den Text des Labels vom FirstViewController ändern. Ich füg mal Bilder des Projekts ein. Vielleicht hilft das ja ;)

Kein Problem! Das mit dem Button hatte ich mißverstanden - ich dachte, es sollte beides geändert werden. Wenn du am button nichts ändern willst, kannst du dir uch das @property sparen.

Wie sieht denn die .m Datei des SecondViewController inzwischen aus? Was hast du an der firstView Sache geändert?

Wie ich sehe wechselst du die VCs ja offensichtlich mit einem UITabBarController. Ich nehme einfach mal an, dass du den im AppDelegate definiert hast und da auch jeweils einen FirstVC und einen SecondVC angelegt hast und dann hinzugefügt hast (bitte korrigier mich, wenn ich mit diesen Annahmen falsch liege, sonst hat meine Erklärung nicht so viel Sinn ;) ).
Sollte das der Fall sein, dann erstell mal im SecondViewController-Header ein @property für einen FirstViewController (die import-Anweisung gehört trotzdem ins .m File ;) ). Im AppDelegate kannst du dann diese property auf den firstVC setzen, den du im AppDelegate erstellt hast. Dieses property darfst du dann auch in deiner button: Methode verwenden, um den Text zu ändern.

Vielleicht noch mal zum Verständnis, warum das so ist:
Aktuell hast du (nehme ich an) zunächst mal zwei View Controller, die du mittels TabBar auf den Bildschirm bringst. Wenn du nun in der button: Methode [[FirstViewController alloc] init] schreibst, bedeutet das, dass du einen weiteren View Controller anlegst. Dieser ist zwar vom gleichen Typ wie der, den der TabBar Controller kennt, ist aber ein anderes Objekt. Als Beispiel aus dem wahren Leben: Du kannst zwei Eichen pflanzen. Keine Eiche hat mit der anderen etwas zu tun - trotzdem sind beide die gleiche Baumart: Eiche.
 
Also das mit dem AppDelegate hab ich nicht so ganz verstanden. Das Projekt habe ich als "tabbed-Appilication" angelegt- sprich als vorgegebene Version von Apple.
Im SecondViewController.h hab ich jetzt
Code:
[COLOR=#BB2CA2][FONT=Menlo]@property[/FONT][/COLOR][COLOR=#000000][FONT=Menlo] ([/FONT][/COLOR][COLOR=#BB2CA2][FONT=Menlo]weak[/FONT][/COLOR][COLOR=#000000][FONT=Menlo], [/FONT][/COLOR][COLOR=#BB2CA2][FONT=Menlo]nonatomic[/FONT][/COLOR][COLOR=#000000][FONT=Menlo]) [/FONT][/COLOR][COLOR=#BB2CA2][FONT=Menlo]IBOutlet[/FONT][/COLOR][COLOR=#4F8187][FONT=Menlo]FirstViewController[/FONT][/COLOR][COLOR=#000000][FONT=Menlo] *firstVC;[\CODE] eingefügt. Ist das richtig so?

Das Projekt habe ich jetzt einfach mal als ZipDatei hochgeladen:
[/FONT][/COLOR][COLOR=#BB2CA2][FONT=Menlo][URL]https://www.dropbox.com/s/hm6yy3zaeiu76gt/NSTRing%C3%9Cbergabe.zip[/URL]

Danke für die Geduld :*[/FONT][/COLOR]
 
Hab's mir mal runtergeladen und "korrigiert" ;)

1) Den Hinweis, dass du FirstViewController nicht in der .h Datei importieren sollst, hast du ja schon insofern umgesetzt, dass du es in der .m Datei importiert hast.
Es ist hier wichtig zu wissen, dass dieser #import Befehl die dazugehörige Datei einfach an die Stelle des import Befehls kopiert (genaugenommen findet vorher noch eine Prüfung statt, ob die Datei bereits kopiert wurde, aber das soll nicht weiter interessieren). Deswegen schreibt man den import Befehl für ein File auch nur entweder in den Header oder in die Implementierungsdatei. Du darfst zwar in beiden import Befehle nutzen, aber innerhalb einer Klasse solltest du ihn nur einmal für jedes zu importierende File benutzen.
Abhilfe schafft der @class Befehl, um einen Klassennamen im Header bekannt zu machen.

2) Hinter das neue @property für den FirstViewController gehört NICHT IBOutlet. IBOutlet bedeutet für Xcode, dass dieses Objekt mit dem Interface-Builder verbunden werden kann. Es ist zwar an sich nicht schlimm, wenn man es trotzdem hinschreibt, aber es ist einfach wieder schlechter Stil es zu machen. Aber du lernst ja noch ;)

3) TextField wird genau wie "button" auch kleingeschrieben. Kein Variablenname sollte mit einem Großbuchstaben beginnen.

Das Problem an der ganzen Sache ist, dass du das Projekt mit einem Storyboard aufgezogen hast. Das wäre noch wichtig zu wissen gewesen, denn so ist meine Lösung von oben für dich tatsächlich erstmal nutzlos, wenn du noch neu in Xcode bist. Im Grunde habe ich zur Korrektur aber das gleiche getan wie vorher.

Zunächst musste ich mir über den TabBarController alle View Controller besorgen. Da du nur einen VC vom Typ FirstViewController hast, hat mir das als Kriterium gereicht den auszumachen (Zugegeben - als Anfänger dürfte es relativ schwer sein, von allein auf diesen Weg zu kommen). Danach läufts in etwa so, wie's vorher war.

Du musst also nun nur noch in der viewDidLoad: Methode des SecondViewControllers folgendes ergänzen (hinter dem Kommentar):

Code:
//Get the view controllers of your UITabBarController
    NSArray *viewControllers = [[self tabBarController] viewControllers];
    
    //Find the "FirstViewController"
    for (UIViewController *match in viewControllers) {
        if ([match isKindOfClass:[FirstViewController class]])
        {
            _firstVC = (FirstViewController*)match;
        }
    }

Die @property-Zeile im Header änderst du (der Ästhetik wegen) folgendermaßen:

Code:
@property (weak, nonatomic) FirstViewController *firstVC;

Nun sollte es laufen! :)
 
Boah Vielen Dank! Hat tatsächlich geklappt. Kapert was ich da mache hab ich zwar nicht, aber das kommt noch ;)

Deswegen auch folgende Frage:
Was, wenn ich jetzt kein tabbarController, sondern ein navigationController habe?
wenn ich in folgender Zeile das "tabbbarController" durch "navigationController" austausche funktioniert das nicht:
Code:
[COLOR=#703DAA][FONT=Menlo]NSArray[/FONT][/COLOR][COLOR=#000000][FONT=Menlo] *viewControllers = [[[/FONT][/COLOR][COLOR=#BB2CA2][FONT=Menlo]self[/FONT][/COLOR][COLOR=#000000][FONT=Menlo] [/FONT][/COLOR][COLOR=#3D1D81][FONT=Menlo]navigationController[/FONT][/COLOR][COLOR=#000000][FONT=Menlo]] [/FONT][/COLOR][COLOR=#3D1D81][FONT=Menlo]viewControllers[/FONT][/COLOR][COLOR=#000000][FONT=Menlo]];[\CODE]

Im "FirstViewController" kommt wieder nur "(null)" an :/
Muss da mehr angepasst werden?[/FONT][/COLOR]
 
wenn ich in folgender Zeile das "tabbbarController" durch "navigationController" austausche funktioniert das nicht:
[...]
Im "FirstViewController" kommt wieder nur "(null)" an :/
Muss da mehr angepasst werden?[/FONT][/COLOR]
Gern geschehen :)

Beim Navigation Controller komme es im Gegensatz zum TabBarController stark auf die Reihenfolge an. Zunächst musst du die View Controller ja in eine mehr oder weniger logische Reihenfolge bringen. Ich tippe auf Grund des Fehlers einfach mal darauf, dass du zuerst den Second View Controller anzeigst und dann zum FirstViewController kommst, richtig? In dem Fall hieße das, dass der FirstViewController noch gar nicht existiert, da dieser erst dann angelegt würde, wenn jemand ihn anzeigen möchte.
Aber das ist alles Spekulation.
Grundliegend funktioniert der Code auch für Navigation Controller - immerhin liefert die viewControllers Methode ja genau wie beim TabBarController alle viewController zurück. Die Frage ist nur, wie du den Rest des Codes oder das Storyboard verändert hast, um aus dem TabBarController einen NavigationController zu machen. Davon hängts dann auch ab, ob der Code so klappen kann oder nicht.

Wenn du mir das neue Projekt wieder in die Dropbox lädst, kann ich dir das morgen abend mal korrigieren, aber sofern die Dinge die ich da mache dir völlig unverständlich sind, bezweifle ich, dass dich das groß weiter bringen wird. Am ehesten würde ich dir empfehlen mal ein gutes Objective-C / iOS Buch zu lesen. Je nach Englischkenntnissen empfehle ich persönlich immer den Big Nerd Ranch Guide: iOS Programming. Ansonsten gibt's davon auch eine deutsche Übersetzung, aber die ist nicht unbedingt gut. Wenn es irgendwie geht (Sprachkenntnis) rate ich (generell bei Informatik Fachbüchern) immer zur englischen Fassung, da du dir so auch massenweise "eingedeutschte" Fachbegriffe ersparst.
Aber wenn du willst, kannst du's mir gern mal in die Dropbox stellen und ich schau mal drüber ;)
 
Das ist mir jetzt peinlich. Ich habe eine Zeile vergessen ins neue Projekt zu kopieren, deswegen hats nicht geklappt :D Aber jetzt funktionierts :)

Ich hatte auch schon überlegt mir ein Buch zu kaufen, aber die vielen negativen bzw. stark unterschiedlichen Rezensionen haben mich bisher zurückgehalten 30€+ auszugeben. Ich werde mir dein Buch auf jeden Fall mal anschauen. Englisch kann ich :p

Vielen Dank nochmal für deine Hilfe!
 
Zurück
Oben Unten