Kontrolery widoku kontenera-powiadom rodzica o akcji

Powiedzmy, że mam własny kontroler widoku kontenera (MainViewController), gdzie robię coś takiego:

- (void)viewDidLoad
{
    [super viewDidLoad];        

    HomeViewController *homeVC = [[HomeViewController alloc] initWithNibName:@"HomeViewController" bundle:nil];
    [self addChildViewController:homeVC];
    [self.view addSubview:homeVC.view];

}

HomeViewController będzie miał przycisk, taki jak "go", który po naciśnięciu będzie musiał przejść do następnego kontrolera widoku. Muszę więc powiadomić Kontroler MainViewController o tej akcji. Jak najlepiej to zrobić?

Używam niestandardowego kontenera, ponieważ muszę wykonywać niestandardowe przejścia między kontrolerami widoku. Po naciśnięciu przycisku " go " niektóre z widoków na Kontroler HomeViewController będzie animował, podczas gdy widoki z nowego kontrolera będą animowane na swoim miejscu.

Oczywiście mógłbym dać HomeViewController właściwość typu MainViewController i wykonywać wywołania w ten sposób, ale mam nadzieję, że jest czystszy sposób z API container view controller.

Author: soleil, 2013-02-20

3 answers

Możesz użyć delegata lub bloku;

Korzystanie z delegata

Utwórz protokół:

@protocol SomeProtocol <NSObject>
- (void)someAction; 
@end 

Wystarczy zadeklarować delegata w HomeViewController.H Jak to:

id<SomeProtocol> delegate; 

A następnie w MainViewController ' s viewDidLoad ustaw to tak:

homeVC.delegate = self;
//some where in MainViewController implement the protocol method
-(void)someAction
{
    //do something
}

Następnie po naciśnięciu przycisku w homeVC, po prostu zadzwoń:

if ([self.delegate respondsToSelector:@selector(someAction)]) {
    [self.delegate someAction];
}

Użycie Bloku :

W HomeViewController.h deklaruje właściwość blokową:

typedef void (^ActionBlock)();

@property (nonatomic, copy) ActionBlock block;

Następnie w MainViewController ViewDidLoad:

homeVC.block = ^(){
    //do something
};

Następnie po naciśnięciu przycisku w homeVC, po prostu zadzwoń:

self.block();
 15
Author: Eric Qian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-09 15:23:40

Jest też inny sposób... Każdy kontroler widoku posiada właściwość parentViewController, dzięki czemu można to zrobić...

W MainViewController zdefiniuj metodę dla akcji, którą chcesz wykonać...

- (void)someMethod:(BOOL)someParam;

Wtedy w HomeViewController możesz to zrobić...

MainViewController* parent = (MainViewController*)[self parentViewController];
[parent someMethod:paramValue];

HTH:)

 10
Author: Pedro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-24 16:43:05

To bardzo powszechny wzorzec. Rodzic będzie rzeczywistą instancją, która będzie obsługiwać akcję, podając protocol i domyślne rozszerzenie .

W Swift 3:

Kontroler widoku nadrzędnego:

protocol SomeProtocol {
    func foo()
}

extension ParentViewController: SomeProtocol {
    func foo() {
        // Parent handles it
    }
}

Kontroler widoku potomnego:

 @IBAction func tapGo(_ sender: Any) {
    (parent as? SomeProtocol)?.foo()
 }
 4
Author: samwize,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-16 08:24:11