[英]Call Function in Underlying ViewController as Modal View Controller is Dismissed
I have a mainViewController.我有一个 mainViewController。 I call [self pushModalViewController:someViewController] which makes someViewController the active view.
我调用 [self pushModalViewController:someViewController] 这使 someViewController 成为活动视图。
Now I want to call a function in mainViewController as someViewController disappears with [self dismissModalViewController].现在我想在 mainViewController 中调用一个函数,因为 someViewController 消失了 [self deniedModalViewController]。
viewDidAppear does not get called probably because the view was already there, just beneath the modal view. viewDidAppear 没有被调用,可能是因为视图已经存在,就在模态视图的下方。 How does one go about calling a function in the mainViewController once the modalView dismisses itself?
一旦 modalView 自行解除,如何调用 mainViewController 中的函数?
Thanks a lot!非常感谢!
This answer was rewritten/expanded to explain the 3 most important approaches ( @galambalazs )这个答案被重写/扩展以解释 3 种最重要的方法( @galambalazs )
The simplest approach is using a callback block
.最简单的方法是使用回调
block
。 This is good if you only have one listener (the parent view controller) interested in the dismissal.如果您只有一个监听器(父视图控制器)对解雇感兴趣,这很好。 You may even pass some data with the event.
您甚至可以随事件传递一些数据。
In MainViewController.m在MainViewController.m 中
SecondViewController* svc = [[SecondViewController alloc] init];
svc.didDismiss = ^(NSString *data) {
// this method gets called in MainVC when your SecondVC is dismissed
NSLog(@"Dismissed SecondViewController");
};
[self presentViewController:svc animated:YES completion:nil];
In SecondViewController.h在SecondViewController.h
@interface MainViewController : UIViewController
@property (nonatomic, copy) void (^didDismiss)(NSString *data);
// ... other properties
@end
In SecondViewController.m在SecondViewController.m
- (IBAction)close:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
if (self.didDismiss)
self.didDismiss(@"some extra data");
}
Delegation
is the recommended pattern by Apple: Delegation
是 Apple 推荐的模式:
Dismissing a Presented View Controller
关闭呈现的视图控制器
If the presented view controller must return data to the presenting view controller, use the delegation design pattern to facilitate the transfer.
如果呈现的视图控制器必须将数据返回给呈现的视图控制器,请使用委托设计模式来方便传输。 Delegation makes it easier to reuse view controllers in different parts of your app.
委托可以更轻松地在应用程序的不同部分重用视图控制器。 With delegation, the presented view controller stores a reference to a delegate object that implements methods from a formal protocol .
通过委托,呈现的视图控制器存储对实现来自正式协议的方法的委托对象的引用。 As it gathers results, the presented view controller calls those methods on its delegate.
当它收集结果时,呈现的视图控制器在其委托上调用这些方法。 In a typical implementation, the presenting view controller makes itself the delegate of its presented view controller.
在典型的实现中,呈现视图控制器使自己成为其呈现的视图控制器的委托。
MainViewController主视图控制器
In MainViewController.h在MainViewController.h
@interface MainViewController : UIViewController <SecondViewControllerDelegate>
- (void)didDismissViewController:(UIViewController*)vc;
// ... properties
@end
Somewhere in MainViewController.m (presenting) MainViewController.m 中的某处(展示)
SecondViewController* svc = [[SecondViewController alloc] init];
svc.delegate = self;
[self presentViewController:svc animated:YES completion:nil];
Somewhere else in MainViewController.m (being told about the dismissal) MainViewController.m 中的其他地方(被告知解雇)
- (void)didDismissViewController:(UIViewController*)vc
{
// this method gets called in MainVC when your SecondVC is dismissed
NSLog(@"Dismissed SecondViewController");
}
SecondViewController第二个视图控制器
In SecondViewController.h在SecondViewController.h
@protocol SecondViewControllerDelegate <NSObject>
- (void)didDismissViewController:(UIViewController*)vc;
@end
@interface SecondViewController : UIViewController
@property (nonatomic, weak) id<SecondViewControllerDelegate> delegate;
// ... other properties
@end
Somewhere in SecondViewController.m SecondViewController.m 中的某处
[self.delegate myActionFromViewController:self];
[self dismissViewControllerAnimated:YES completion:nil];
(note: the protocol with didDismissViewController: method could be reused throughout your app) (注意:带有 didDismissViewController: 方法的协议可以在整个应用程序中重复使用)
Another solution is sending an NSNotification
.另一种解决方案是发送
NSNotification
。 This is a valid approach as well, it might be easier than delegation in case you only want to notify about the dismissal without passing much data.这也是一种有效的方法,如果您只想通知解雇而不传递大量数据,它可能比委托更容易。 But it's main use case is when you want multiple listeners for the dismissal event (other than just the parent view controller).
但它的主要用例是当您需要多个用于解雇事件的侦听器时(不仅仅是父视图控制器)。
But make sure to always remove yourself from NSNotificationCentre after you are done!但是请确保在完成后始终将自己从NSNotificationCentre 中移除! Otherwise you risk of crashing by being called for notifications even after you are deallocated.
否则,即使在您被解除分配后,您也可能因被调用通知而导致崩溃。 [editor's note]
[编者注]
In MainViewController.m在MainViewController.m 中
- (IBAction)showSecondViewController:(id)sender
{
SecondViewController *secondVC = [[SecondViewController alloc] init];
[self presentViewController:secondVC animated:YES completion:nil];
// Set self to listen for the message "SecondViewControllerDismissed"
// and run a method when this message is detected
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(didDismissSecondViewController)
name:@"SecondViewControllerDismissed"
object:nil];
}
- (void)dealloc
{
// simply unsubscribe from *all* notifications upon being deallocated
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)didDismissSecondViewController
{
// this method gets called in MainVC when your SecondVC is dismissed
NSLog(@"Dismissed SecondViewController");
}
In SecondViewController.m在SecondViewController.m
- (IBAction)close:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
// This sends a message through the NSNotificationCenter
// to any listeners for "SecondViewControllerDismissed"
[[NSNotificationCenter defaultCenter]
postNotificationName:@"SecondViewControllerDismissed"
object:nil userInfo:nil];
}
Hope this helps!希望这可以帮助!
When you're using storyboards and segues you can use a very handy approach with minimal code to dismiss a modal view controller and inform the underlying view controller that the modal view controller has been closed.当您使用故事板和转场时,您可以使用一种非常方便的方法以最少的代码关闭模态视图控制器并通知底层视图控制器模态视图控制器已关闭。
Using exit (unwind) segues you gain 3 advantages:使用 exit (unwind) segues 可以获得 3 个优势:
prepareForSegue:
prepareForSegue:
已经知道的相同的语义prepareForSegue:
Swift迅速
@IBAction func unwindFromSegue(segue: UIStoryboardSegue) {
print("Unwind from segue", segue.identifier)
}
Objective-C目标-C
- (IBAction)unwindFromSegue:(UIStoryboardSegue *)segue {
NSLog(@"Unwind from segue %s", segue.identifier);
}
unwindFromSegue:
to your button and select action .unwindFromSegue:
拖放到您的按钮并选择action 。 You're done!你完成了! Now the modal view controller closes when you click the
dismiss
button and unwindFromSegue:
informs your underlying view controller( Parent ) that the modal view controller( Child ) has closed.现在,当您单击
dismiss
按钮和unwindFromSegue:
时,模态视图控制器将关闭unwindFromSegue:
通知您的底层视图控制器(父级)模态视图控制器(子级)已关闭。
Here's a callback solution which takes less modifications to your modal and parent: In the Model's .h add:这是一个回调解决方案,它对您的模态和父级进行较少的修改:在模型的 .h 添加:
@property (nonatomic, copy) void (^dismissed)();
In the Model's .m put this in the completion when you dismiss the modal:在模型的 .m 中,当您关闭模态时,将其放入完成中:
[self dismissViewControllerAnimated:YES completion:^{
if(self.dismissed)
self.dismissed();
}];
In the parent view controller when you instantiate your modal set the dismissed callback:在父视图控制器中,当您实例化模态时,请设置已解除的回调:
Modal = //Init your modal
[Modal setDismissed:^{
//do stuff you wanted when it's dimissed
}];
[self presentViewController:Modal animated:YES completion:nil];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.