У меня есть кнопка на панели инструментов, с которой связан поповер. В поповере я настроил навигационный контроллер. Я пытаюсь добиться того, чтобы контроллер представления был на два или три уровня ниже в стеке навигационного контроллера, чтобы изменить состояние кнопки, которая первоначально называлась поповер. Мне удалось это сделать, но для этого требуется пара делегатов, и это кажется очень неуклюжим; моя причина публикации здесь - выяснить, есть ли более элегантное и эффективное решение.
Итак, для начала:
//ProtocolDeclaration.h
@protocol ADelegate <NSObject>
- (void)changeButtonState;
@end
@protocol BDelegate <NSObject>
- (void)passTheBuckUpTheNavChain;
@end
Тогда для моего MainController, который удерживает кнопку:
// MainController.h
#import "A_TableController.h"
#import "ProtocolDeclaration.h"
@class A_TableController;
@interface MainController : UIViewController <ADelegate>
...
@end
// MainController.m
- (IBAction)buttonPressed:(id)sender {
A_Controller *ac = [[[A_Controller alloc] init] autorelease];
ac.ADelegate = self;
UINavigationController *nc = [[[UINavigationController alloc] initWithRootViewController:ac] autorelease];
UIPopoverController *pc = [[[UIPopoverController alloc] initWithContentViewController:nc] autorelease];
[pc presentPopoverFromBarButtonItem...]
}
// ADelegate Method in MainController.m
- (void)changeButtonState
{
self.button.style = ....
}
Теперь для A_Controller мой rootViewController для моего navController:
//A_Controller.h
#import "B_Controller.h"
#import "ProtocolDeclaration.h"
@class B_Controller;
@interface A_Controller : UITableViewController <BDelegate>
{
id<ADelegate> delegate;
...
}
@property (assign) id<ADelegate> delegate;
...
@end
//A_Controller.m
//In the method that pushes B_Controller onto the stack:
B_Controller *bc = [[[B_Controller alloc] init] autorelease];
bc.BDelegate = self;
[self.navigationController pushViewController:bc animated:YES];
//In the BDelegate Method in A_Controller:
- (void)passTheBuckUpTheNavChain
{
[ADelegate changeButtonState];
}
Наконец, в B_Controller:
//B_Controller.h
#import "ProtocolDeclaration.h"
@interface A_Controller : UITableViewController
{
id<BDelegate> delegate;
...
}
@property (assign) id<BDelegate> delegate;
...
@end
//B_Controller.m
//Where it's necessary to change the button state back up in MainController:
[BDelegate passTheBuckUpTheNavChain];
Так вот, это работает, но это похоже на своего рода способ Рубе-Голдберга. Я попытался инициализировать оба A_Controller и B_Controller в MainController и установить делегат B_Controller на MainController прямо там, а затем использовать NSArray двух контроллеров представления для установки стека navcontroller, но он действительно испортил способ отображения контроллеров представления в контроллере navcon: Я получил бы кнопку «Назад» даже на корневом контроллере navcontroller, и вы могли бы просто продолжать нажимать кнопку «Назад» и вращаться вокруг стека navcontroller вместо того, чтобы останавливаться в корне. Есть идеи, как лучше это сделать?