正确显示连续模量的方法
-
30-09-2019 - |
题
我有两个观点需要模仿,一个接一个地显示。如果我们这样解雇和表现出来,这无效:
[rootController dismissModalViewControllerAnimated: YES];
[rootController presentModalViewController: psvc animated: YES];
第二种模态视图根本不会显示。
我已经看到了这样的修复程序:
[rootController dismissModalViewControllerAnimated: YES];
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[self performSelector: @selector(seekModal) withObject: nil afterDelay: 0.5];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
问题在于,这不会一直工作(有时需要的延迟是优越的)。
另一个可能的解决方法是消除动画:
[rootController dismissModalViewControllerAnimated: NO];
[rootController presentModalViewController: psvc animated: YES];
但是,我真的很想保留动画,以保持感觉到第一种模式不在。有什么建议么?
解决方案
编辑: 在ios5+中执行此操作的“正确”机制将是使用 – dismissViewControllerAnimated:completion:
方法,并从完成块中显示顺序视图控制器。
即将显示的ViewController将具有其ViewDidDisappear:Animated:Animated:Modal-Dismissal-Animation完成的方法。 AFIK这是您唯一可以钩住后续presentModalViewController的地方:animated:call。
我有一个用于呈现模态视图控制器的课程,并且一旦解雇完成后,它会通过回调对呈现视图控制器的回调来实现您要寻找的逻辑。要使用此类,只需使用普通的PresentViewController:Animated:Call。在介绍视图控制器上实现以下方法:
- (void) modalViewControllerDidDismiss:(UIViewController *)modalViewController
将立即调用模态视图控制器,并且您目前可以提出一个新的模态视图控制器。
一件好事 - 由于此类是Uinavigation Controller的专业化,因此您可以根据需要配置NavigationBar。该课程还具有内置的逻辑,可以显示一个解雇按钮。
这是类定义:
@protocol TSModalViewControllerDelegate
- (void) modalViewControllerDidDismiss: (UIViewController*) modalViewController;
@end
@interface TSModalViewController : UINavigationController
{
UIViewController* _originalParentViewController;
}
@property BOOL dismissButtonHidden;
- (id) initWithViewController: (UIViewController*) vc;
- (id) initWithClass: (Class) c;
- (id) initWithClass: (Class) c nibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
@end
以及类实施:
@implementation TSModalViewController
@synthesize dismissButtonHidden;
- (id) initWithViewController: (UIViewController *)vc
{
return [super initWithRootViewController: vc];
}
- (id) initWithClass:(Class)c
{
UIViewController* vc = [[[c alloc] init] autorelease];
return [self initWithViewController: vc];
}
- (id) initWithClass: (Class) c nibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
UIViewController* vc = [[[c alloc] initWithNibName:nibNameOrNil bundle:nibBundleOrNil] autorelease];
return [self initWithViewController: vc];
}
- (void) viewDidAppear: (BOOL) animated
{
[super viewDidAppear: animated];
[_originalParentViewController release];
_originalParentViewController = [self.parentViewController retain];
if (!self.dismissButtonHidden)
{
UIBarButtonItem* dismissButton = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemStop
target: self
action: @selector(onDismiss:)] autorelease];
UIViewController* rootViewController = [self.viewControllers objectAtIndex:0];
rootViewController.navigationItem.leftBarButtonItem = dismissButton;
self.navigationBarHidden = NO;
}
}
- (void) viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear: animated];
if ( [_originalParentViewController respondsToSelector: @selector(modalViewControllerDidDismiss:)] )
{
[_originalParentViewController performSelector: @selector(modalViewControllerDidDismiss:) withObject: self];
}
}
- (void) dismissModalViewControllerAnimated:(BOOL)animated
{
return [self.parentViewController dismissModalViewControllerAnimated: animated];
}
- (void) onDismiss: (id) sender
{
[self.parentViewController dismissModalViewControllerAnimated: YES];
}
- (void) didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void) viewDidUnload
{
[super viewDidUnload];
}
- (void)dealloc
{
[_originalParentViewController release];
[super dealloc];
}
@end
而且,这是您可以使用它的方法(在某些普通视图控制器的上下文中):
- (void) onShowIt:(id)sender
{
TSModalViewController* mvc = [[[TSModalViewController alloc] initWithClass: [MyModalViewController class] nibName: @"MyModalViewController" bundle:nil] autorelease];
mvc.dismissButtonHidden = YES; // set to no if you don't want an "automatic" close button
[self presentModalViewController: mvc animated: YES];
}
而且,这是解雇回调方法,它提出了一个新的模态视图控制器:
- (void) modalViewControllerDidDismiss:(UIViewController *)modalViewController
{
MyModalViewController* vc = [[[MyModalViewController alloc] initWithNibName: @"MyModalViewController" bundle:nil] autorelease];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
TSModalViewController* mvc = [[[TSModalViewController alloc] initWithViewController: vc] autorelease];
[self presentModalViewController: mvc animated: YES];
}
其他提示
rootcontroller可以告诉它,它的最后一个模态视图控制器何时消失,因为它将接收一个ViewDidappear:。您是否尝试过链接presentModalViewController:后续视图控制器的内容?
如果您真的想将多个视图动画链在一起,我实际上建议您自己处理动画逻辑。这并不是太棘手了,然后您可以对观点的显示方式进行细粒度的控制。我只是在这里为另一个问题写了类似的东西:
您可以将视图动画,对视图进行动画,然后调用AnimationDidStop选择器时,将第二视图动画。好的部分是,您还可以使用视图不透明度和动画方向进行游戏,并确切确定何时应该出现视图。例如,当第一个视图滑动时,您可以让第二种视图在第一个视图上滑动;无需等待第一个完成动画。
您的问题与“在模态视图中显示模态视图”有关吗?我在这里发布了一个答案:iPhone模态视图在另一种模态视图中?
我发现这样的最佳解决方案(如果他们都是父母视图的平等孩子)是将其视图修补到启用分页的UISCrollView上(您可以在底部添加页面控件以使其清晰并进行导航)然后将控制器的视图添加到页面视图上时,将其在屏幕上删除时,将其删除。
如果控制器依赖于此,您可能还必须呼叫-ViewWillAppear和-ViewWillDisAppear。当您对其进行编码时,它有点感觉hack-ish,但是一旦您工作起作用,它看起来平稳和自然,并且没有任何与动画视图相关的等待,然后将下一个视图动画一次。离开了。
我发现使用模态视图的-ViewDidDissapear在呈现视图控制器工作中调用方法非常好。一个好处是能够在模态视图控制器上延迟Deadlocation。请发布我可以做出的任何改进。我创建此协议的灵感来自iOS 5的“ iviveViewControllerAnimimation:完成:” uiviewController的补充。我希望在iOS 4.3中使用此功能。
现在的ElegateProtocol.H
@protocol PresentorDelegateProtocol <NSObject>
@optional
/*
Extra protocol methods defined in protocol for flexibility.
Main methods are:
- (void)dismissPresentingModalViewController:(id)modalView animated:(BOOL)animated;
- (void)modalViewDissapeared:(id)modalView; //used in modal view's -viewDidDissapear
*/
- (void)dismissPresentingModalViewController:(id)modalView animated:(BOOL)animated;
- (void)modalViewDissapeared:(id)modalView;
// use the block in this method send messages to save state, etc. This is the one I like to use.
- (void)dismissPresentingModalViewController:(id)modalView animated:(BOOL)animated withBlock:(void(^)())block;
// use in other classes that are not controlling dismissal of the modal view
- (void)executeBlockOnModalDissapearance: (void(^)())block;
@end
呈现ViewController.h
#import "PresentorDelegateProtocol.h"
@interface PresentingViewController : UIViewController <PresentorDelegateProtocol>
- (void)showModalVC;
@end
modalviewController.h
#import "PresentorDelegateProtocol.h"
@interface ModalViewController : UIViewController
@property (nonatomic, assign) id <PresentorDelegateProtocol> presentorDelegate;
- (void)close;
@end
呈现ViewController.m
#import "PresentingViewController.h"
#import "ModalViewController.h"
@implementation PresentingModalViewController
- (void)showModalVC
{
ModalViewController *modalVC = [[ModalViewController alloc] initWithNibName:@"ModalViewController" bundle:nil];
modalVC.presentorDelegate = self;
[self presentModalViewController:modalVC animated:YES];
}
- (void)dismissPresentingModalViewController:(id)modalView animated:(BOOL)animated
{
if ([modalView isKindOfClass:[ModalViewController class]]) {
NSLog(@"Can invoke based on class");
}
[self dismissModalViewControllerAnimated:animated];
}
- (void)dismissPresentingModalViewController:(id)modalView animated:(BOOL)animated withBlock:(void(^)())block
{
block();
/* execute block before or after calling to dismiss modal view */
[self dismissPresentingModalViewController:modalView animated:animated];
//block();
}
- (void)modalViewDissapeared:(id)modalView
{
if ([modalView isKindOfClass:[ModalViewController class]]) {
NSLog(@"Do stuff based on class.");
}
}
- (void)executeBlockOnModalDissapearance: (void(^)())block
{
block();
NSLog(@"This delay's dealloc on modal view until block completes");
}
@end
modalviewcontroller.m
#import "ModalViewController.h"
@implementation ModalViewController
@synthesize presentorDelegate;
- (void)close
{
if (1 == 0 /*need to do something before dealloc*/){
[self.presentorDelegate dismissPresentingModalViewController:self animated:YES withBlock:^{
NSLog(@"Do stuff with block. Save, animate, etc");
}];
} else {
[self.presentorDelegate dismissPresentingModalViewController:self animated:YES];
}
}
- (void)viewDidDisappear:(BOOL)animated
{
if (1 == 0 /*stuff to do*/){
[self.presentorDelegate executeBlockOnModalDissapearance:^{
// do stuff before modal view is deallocated
}];
}
[self.presentorDelegate modalViewDissapeared:self];
presentorDelegate = nil;
[super viewDidDisappear:animated];
}
@end;
// present modal view inside another presented modal view
FirstViewController *firstVC = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController: firstVC];
// Note: you can use your viewcontroller instead self.window.rootViewController
[self.window.rootViewController presentViewController:navController animated:YES completion:^{
//code...
SecondViewController *secondVC = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
[navController presentViewController: secondVC animated:YES completion:nil];
}
}];