• 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

UINavigation Item BackButton "lauschen" um bei Betätigung eine Aktion auszuführen

denio

Empire
Registriert
23.01.10
Beiträge
88
Hey Leute, hab vor kurzem angefangen mich mit dem iPhone SDK auseinanderzusetzen und bin gerade dabei ein kleines Programm zu Übungszwecke zu schreiben.

Ich komme auch ganz gut voran. Ich habe das Programm als eine Navigation-based Applikation angelegt und ich erzeuge auch die Nachfolger Views inkl. Navigation Controller, das klappt auch soweit ganz gut.

Mein Problem ist nun folgendes:

Wenn ich mich über eine Row in TableView vom RootViewController in ein anderes View begebe, wird durch den Navigation Controller eine NavigationBar "automatisch" aufgebaut. In dieser NavigationBar kann man ja durch den "BackButton" ohne weiteres in das vorherige View zurück. Ich würde gerne einige Aktionen/Funktionen ausführen, sobald ich den "BackButton" angetippt habe, quasi bevor bzw. während die Applikation in das vorherige View zurückspringt.

Besteht die Möglichkeit, das antippen des "BackButtons" mit einer Methode zu verbinden, so wie dies z.B. bei einem normalen Button gemacht werden kann.

Habe leider nichts passendes zu meinem Problem hier im Forum gefunden. Ihr würdet mir echt helfen, wenn ihr eine Lösung hättet. Danke schon mal im voraus :)
 
Zuletzt bearbeitet:

John

Macoun
Registriert
08.06.09
Beiträge
119
Guten Morgen,
eine Möglichkeit wäre es den Backbutton programmatisch zu erzeugen:

Code:
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStyleBordered target:self action:@selector(backToMainView)];

und in deiner backMethode dann einfach die gewünschten Funktionen aufzurufen:

Code:
- (void)backToMainView {
	NSLog(@"Mach was");
	[self.navigationController popToRootViewControllerAnimated:YES];
}

Ich hoffe das geht in die Richtung, nach der du suchst :)
John
 

denio

Empire
Registriert
23.01.10
Beiträge
88
Hey John danke für die Rückmeldung :) klappt sehr gut :) sogar zu gut :D

Nach antippen des "Back" Knopfs springt das Programm in das Hauptmenü der Applikation, unabhängig davon in welchem Nachfolger View ich mich befinde :)

Ich vermute mal das liegt am "popToRootViewControllerAnimated", kennst du zufällig auch eine Möglichkeit lediglich zum Vorgänger des aktuellen View zu springen, anstatt alle Views zu überspringen? Bzw. soweit ich das verstanden habe werden die Views bei einer Navigation-Base-Applikation nach dem Stackprinzip übereinander gestapelt, also müsste es doch auch möglich sein, an eine bestimmt Stelle innerhalb des Stacks zu springen? Wenn ja wie müsste ich das anstellen? :)

Oder verstehe ich da etwas falsch :) bin noch relativ grün hinter den Ohren was Object-C anbelangt :D
 
Zuletzt bearbeitet:

Poljpocket

Salvatico di Campascio
Registriert
07.01.07
Beiträge
432
Ändere die Zeile:

Code:
[self.navigationController popToRootViewControllerAnimated:YES];

in

Code:
[self.navigationController popViewControllerAnimated:YES];

und du hast, was du willst.

Gruss ppocket

PS: Nebenbei: Das hat nichts mit Objective-C zu tun :) Das ist lediglich das UIKit-Framework, welches dir zum Programmieren von Apps mit Objective-C hilft. Du bist also grün hinter den Ohren, was UIKit (und vielleicht Objective-C) anbelangt.
 
Zuletzt bearbeitet:

denio

Empire
Registriert
23.01.10
Beiträge
88
und du hast, was du willst.
Danke, genau das was ich brauche/will :D

PS: Nebenbei: Das hat nichts mit Objective-C zu tun :) Das ist lediglich das UIKit-Framework, welches dir zum Programmieren von Apps mit Objective-C hilft. Du bist also grün hinter den Ohren, was UIKit ([und vielleicht Objective-C] anbelangt).

Hehe deine Korrektur meiner Aussage bestätigt nur, das ich noch einiges zu lesen habe ;) danke auf jeden fall für den Tip :)

Vielleicht könntest du mir noch bei meiner "letzteren" Frage helfen :)

Ich habe mein RootView (Index=0) von dem ich mich in die anderen Views begebe, wenn ich nun im RootView "Nachfolger" (Index=1) bin, rufe ich diesen "Rekursiv" mehrmals hintereinander auf. Bei dem View handelt es sich um ein simples Textfeld dessen Inhalt ich auslese und in einer Datei speichere. Wenn ich mich nun z.B. in dem "3" "Nachfolger" View (Index=4) befinde, möchte ich nun z.B. an den ersten RootView-Nachfolger (Index=1) "springen".

Nach folgendem Prinzip
RootView -> View0 (selbstaufruf) -> View1 (selbstaufruf) -> View2 (selbstaufruf) -> View3 (selbstaufruf) -> "Back"-Button betätigen -> View0 (selbstaufruf) -> etc.

Eigentlich ging ich davon aus, das ich mit folgendem Aufruf

Code:
     [self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
genau das hinbekommen :) aber leider spring ich damit direkt in das RootView ;)

weißt du was ich falsch mache bzw. fehlt mich noch etwas?

Besten Dank und Gruß denio
 

Poljpocket

Salvatico di Campascio
Registriert
07.01.07
Beiträge
432
Ich kenne das UIKit nicht (dafür Cocoa) und hab das selber eigentich noch nie benutzt. Aber soviel ich mich jetzt da reingelesen habe, sollte eigentlich alles stimmen. Die Doku sagt nur:

The root view controller is at index 0 in the array, the back view controller is at index n-2, and the top controller is at index n-1, where n is the number of items in the array.
-> go to...

Das sagt mir jetzt nicht, ob die Controller innerhalb des Arrays geordnet sein müssen. So wie man Apple kennt, ist genau das, was da steht, gegeben und der Rest nicht unbedingt, obwohl eine Ordnung eigentlich naheliegend wäre.

Trotzdem hat das jetzt nicht viel mit deinem Problem zu tun! Du holst ja den Controller an Index 1 raus, was ja nicht der rootController sein kann, der ist ja explizit an Stelle 1, also Index 0. Also denke ich, sollte alles andere als der rootController rausspringen. Daraus lässt sich wohl schliessen, dass sonst irgendetwas nicht funktioniert.

Bist du dir sicher, dass an Stelle 2 ein viewController exisitert?

Gruss ppocket

PS: Überlege dir, wie du den mittels "Back" gewünschten viewController direkt (ohne den Umweg über das Array) erreichen kannst. Zum Beispiel machst du eine neue Klasse (Subklasse von UIViewController), welche einen 'backController' als Instanzvariable (und property) halten kann. So, wie ich dich verstanden habe, willst du eine Reihe von Eingaben auf verschiedenen Screens machen und an irgendeiner Stelle immer die ganze Aktion auf einmal abbrechen können. Dann erstellst du diese ViewController aus der neuen Klasse und weist jedem beim (oder nach) der Initialisation den 'backController' zu. Ich würde es in diesem Fall zumindest so machen. Wenn du Probleme damit hast, ich mache dir gerne ein Beispiel.
 

denio

Empire
Registriert
23.01.10
Beiträge
88
Trotzdem hat das jetzt nicht viel mit deinem Problem zu tun! Du holst ja den Controller an Index 1 raus, was ja nicht der rootController sein kann, der ist ja explizit an Stelle 1, also Index 0. Also denke ich, sollte alles andere als der rootController rausspringen.

So dachte ich das verstanden zu haben :)

Daraus lässt sich wohl schliessen, dass sonst irgendetwas nicht funktioniert.

Bist du dir sicher, dass an Stelle 2 ein viewController exisitert?

Ich vermute mal das es so ist wie du sagt und das ich an einer anderen Stelle im Code etwas falsch mache, in meinem rootView steht folgendes bzw. wird eine XIB geladen, wenn der Button für das nächste View (Input) angetippt wird

Code:
inputView *anotherViewController =
[[SearchContactView alloc] initWithNibName:@"inputView" bundle:nil];
[self.navigationController pushViewController:anotherViewController  animated:YES];
[anotherViewController release];
in den der inputView.m geh ich mal davon aus, das ich mit folgenden Code den inputNavigationController und den inputViewController erzeuge

Code:
- (InputViewController *)inputViewController
{
    NSLog(@"SAV inputViewController");
    if (inputViewController == nil)
    {
        inputViewController = [[InputViewController alloc]  initWithStyle:UITableViewStylePlain];
    }
    return inputViewController;
}

- (UINavigationController *)inputNavigationController
{
    NSLog(@"SAV inputNavigationController");
    if (inputNavigationController == nil)
    {
        inputNavigationController = [[UINavigationController alloc]  initWithRootViewController:self.inputViewController];
    }
    return inputNavigationController;
}
und innerhalb der inputView.m an der entsprechend Stelle mit folgendem Code das View selber nochmals lade

Code:
[self.navigationController  presentModalViewController:self.inputNavigationController animated:YES];
weiterhin befindet sich unteranderem folgender Code innerhalb der inputView.m

Code:
- (void)viewDidLoad {
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]  initWithTitle:@"Restart" style:UIBarButtonItemStyleBordered target:self  action:@selector(startAgain)];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]  initWithTitle:@"MainMenu" style:UIBarButtonItemStyleBordered target:self  action:@selector(backToMainView)];
}

- (void)startAgain{
[self.navigationController  popToViewController:[self.navigationController.viewControllers  objectAtIndex:1] animated:YES];
}

- (void) backToMainView{
[self.navigationController popToRootViewControllerAnimated:YES];
}
Überlege dir, wie du den mittels "Back" gewünschten viewController direkt (ohne den Umweg über das Array) erreichen kannst. Zum Beispiel machst du eine neue Klasse (Subklasse von UIViewController), welche einen 'backController' als Instanzvariable (und property) halten kann. So, wie ich dich verstanden habe, willst du eine Reihe von Eingaben auf verschiedenen Screens machen und an irgendeiner Stelle immer die ganze Aktion auf einmal abbrechen können. Dann erstellst du diese ViewController aus der neuen Klasse und weist jedem beim (oder nach) der Initialisation den 'backController' zu. Ich würde es in diesem Fall zumindest so machen. Wenn du Probleme damit hast, ich mache dir gerne ein Beispiel.

Jup genauso wollte ich es haben, quasi ein "Neuanfang" :). Aber ich habe mich eigentlich mit den beiden Methoden angefreundet :)

Code:
[self.navigationController popViewControllerAnimated:YES];
[self.navigationController  popToRootViewControllerAnimated:YES];
die erste Methode nutze ich um zum direkten Vorgänger des aktuellen Views zu gelangen und die entsprechenden Aktionen durchzuführen und die zweite Nutze ich um in das RootView zu springen, da es sich beim inputView um einen direkten "Nachfolger"-View des rootViews handelt :), ist der Weg nicht allzu lang :D. Für zukünftige Zwecke wäre die Variante mit der Subklasse (oder die Methode popToViewController mit Index) dennoch hilfreich:), da ich jedoch die Software diese Woche fertig kriegen will und noch ein paar andere "Baustellen" habe, werde ich mir mal Ende dieser Woche anschauen wie das mit der Subklasse gemacht wird.

Ich kann mir zwar vorstellen wie du das mit der Subklasse meinst, wäre aber nett wenn du es an Hand eines kleinen Beispiels zeigen könntest :) sofern es sich hierbei nur um ein paar Zeilen Code handelt :) bzw. wie gesagt ich würde mich Ende der Woche noch mal ran setzen und mich bei entsprechenden Problemen noch mal melden, bzw. meine Lösung posten für den Fall das jemand diesbezüglich Hilfe benötigt :)

Danke auf jeden Fall für die Hilfe :D gruss denio :)
 
Zuletzt bearbeitet:

Poljpocket

Salvatico di Campascio
Registriert
07.01.07
Beiträge
432
Denke mal bei dieser Zeile darüber nach, was du da eigentlich machst:

Code:
[self.navigationController  presentModalViewController:self.inputNavigationController animated:YES];

da lässt du einen modalen ViewController, also ein View, welches die darunterliegenden solange blockiert, bis es wieder entfernt wird, darüberschalten. Aber diese Methode ist nicht vom NavigationController, sondern von UIViewController. Also wird diese View weder vom NavigationController kontrolliert, noch ist sie dann natürlich in der stack -> In dem Array existiert nur der rootController.

Dann kann also der NavigationController nur das rootView 'popen', die modalen Views sind dem egal. Du musst also dann das View des inputNavigationController wieder entfernen, nicht den darunterliegenden navigationController ein View popen lassen.

Gruss ppocket

PS: das popen hat nichts mit popen() zu tun. Ich will es nur nicht mit drei p schreiben :p
 
Zuletzt bearbeitet:

denio

Empire
Registriert
23.01.10
Beiträge
88
Denke mal bei dieser Zeile darüber nach, was du das eigentlich machst:

Code:
[self.navigationController presentModalViewController:self.inputNavigationController animated:YES];
da lässt du einen modalen ViewController, also ein View, welches die darunterliegenden solange blockiert, bis es wieder entfernt wird, darüberschalten. Aber diese Methode ist nicht vom NavigationController, sondern von UIViewController. Also wird diese View weder vom NavigationController kontrolliert, noch ist sie dann natürlich in der stack -> In dem Array existiert nur der rootController.

Dann kann also der NavigationController nur das rootView 'popen', die modalen Views sind dem egal. Du musst also dann das View des inputNavigationController wieder entfernen, nicht den darunterliegenden navigationController ein View popen lassen.

Accch man :) jetzt wo du mich darauf hinweißt :). Wenn die Abfragen beendet sind, wird über ein weiteren Button mithilfe des "presentModalViewController" ein weiteres anderes View gelegt was auch die Kontrolle haben soll :) anfangs gabs nur diesen Button und ich habe den Button mit den Selbstaufruf später hinzugefügt und dann einfach per Copy-Paste die relevanten Teil aus dem vorherigen übernommen und dabei hab dabei wohl ein wenig gepennt ;) hab jetzt an der entsprechenden Stelle des Selbstaufrufs des inputViews das "presentModalViewController" durch "pushViewController" ersetzt und nun funktioniert auch der Rücksprung via

Code:
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
einwandfrei :D. Jetzt hab ich alle drei Funktionen (Back to RootView, Back to PreviewView, und Back to FirstView) herzlichen Dank :D

Eine Frage hätte ich dennoch :) was passiert z.B. mit den Views im Index=1/2-n wenn ich mich in RootView begeben oder an den Index=1? werden die dann released? bzw. werden die vom Stack runter "gepopt" ? oder muss ich mich noch darum kümmern? :D

PS: das popen hat nichts mit popen() zu tun. Ich will es nur nicht mit drei p schreiben :p

Haha, ja das nette Denglisch ;D immer wieder gut für ein paar Schmunzerle :D
 

Poljpocket

Salvatico di Campascio
Registriert
07.01.07
Beiträge
432
Im Normalfall werden bei einer Stack die gepopten Elemente entfernt. Auf Cocoaisch würde das dann wohl release heissen, ja! Die Elemente werden also gelöscht, solange sie nicht sonstwo geretaint wurden.

Ich weiss das aber nicht mit Sicherheit!

Gruss ppocket
 

denio

Empire
Registriert
23.01.10
Beiträge
88
Im Normalfall werden bei einer Stack die gepopten Elemente entfernt. Auf Cocoaisch würde das dann wohl release heissen, ja! Die Elemente werden also gelöscht, solange sie nicht sonstwo geretaint wurden.

Ich weiss das aber nicht mit Sicherheit!

Gruss ppocket

Hehe das reicht mir :) Ich werde mir mal nächste Woche Instruments genau anschauen und dabei mal checken ob die Views wieder released/gepopt/freigegeben werden ;) Dank auf jeden Fall für die freundliche und kompetente Hilfe :D

Gruss denio :)