在iOS 7中展示UIImagePickerController的问题
我的应用程序仅以横向模式运行! 所以我知道UIImagePickerController
仅在纵向模式下呈现,所以在iOS 6中,我创建了一个UIImagePickerController
的子类,强制UIImagePickerController
以纵向模式打开:
@interface NonRotatingUIImagePickerController : UIImagePickerController @end @implementation NonRotatingUIImagePickerController - (BOOL)shouldAutorotate { return NO; } @end
//presenting picker controller : UIImagePickerController *ipc = [[NonRotatingUIImagePickerController alloc]init]; ipc.delegate = self; [self presentViewController:ipc animated:YES completion:nil];
这在iOS 6中运行良好,但现在在iOS 7中,我的应用程序因此崩溃:
2013-10-31 14:56:01.028 Medad[1731:60b] *** Terminating app due to uncaught exception 'UIApplicationInvalidInterfaceOrientation', reason: 'Supported orientations has no common orientation with the application, and shouldAutorotate is returning YES'
如果我在部署信息中检查Portrait
,则可以解决此问题:
问题是,如果我检查此选项,我的应用程序也会以纵向运行,但我不想要它!
我该如何解决这个问题?
我已经对它进行了测试,发现您不应该通过目标窗口中的复选框处理方向,如上图所示,因为它是您的整个应用程序方向所以请检查所有方框以获得所有方向支持。 如果你想要一些不同方向的视图和一些不同的视图,那么你必须通过ViewController
类中的编码来处理它,方法是返回YES
或NO
。
这是我的样品 。 我做的。 请检查。
下面的方法将处理ViewController
的方向
-(BOOL)shouldAutorotate { return YES; } -(NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight; } // Old Method -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) { return NO; } else { return YES; } }
因此,解决方案是:为UIImagePickerController
两个自定义类,另一个用于ViewController
(For All ViewControllers),并将它们用于特定方向,并将这些类分别用作UIImagePickerController
和所有ViewControllers
超类。
有一个简单的解决方案可以避免更改应用程序支持的方向,并使UIImagePickerController
正常工作:只有在必须显示选择器时才返回UIInterfaceOrientationMaskAll
。
您可以简单地为UIApplication创建子类并使用以下两种方法:
- (NSUInteger)supportedInterfaceOrientationsForWindow:(UIWindow *)window { UIViewController *topController = window.rootViewController; if ([self hasPicker:topController]) return UIInterfaceOrientationMaskAll; return [super supportedInterfaceOrientationsForWindow:window]; } -(BOOL)hasPicker:(UIViewController *)controller { BOOL hasPicker = NO; NSLog(@"Check Controller: %@", controller); if ([controller isKindOfClass:[UIImagePickerController class]]) return YES; for (UIViewController *child in controller.childViewControllers) { hasPicker = [self hasPicker:child]; if (hasPicker) return YES; } return NO; }
在第一种方法中,您将覆盖默认的supportedInterfaceOrientationsForWindows:
方法。 每次调用该方法时,都会检查层次结构中的所有视图控制器(通过hasPicker:
一种递归方法)。 如果找到UIInterfaceOrientationMaskAll
,则返回UIInterfaceOrientationMaskAll
,否则返回应用程序的默认设置。
我建议你的另一件事:不要将UIImagePickerController
子类化,因为Apple明确禁止它。 而是像我在这个例子中一样使用视图控制器包含:
景观选择器示例
注意:示例代码仅适用于UIImagePickerController
包含。 如果您将其子类化并通过presentViewController:
添加它presentViewController:
您可能必须调整hasPicker:
方法的行为。 您可以做的另一件简单的事情是:将一个实例变量添加到您的UIApplication
子类并在显示选择器时设置它,并在您解雇时取消设置
另一解决方案
在每个控制器中添加,甚至到具有选择器的控制器:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight) { return YES; } return NO; } - (BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskLandscape; }
将其添加到您的自定义选择器控制器:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { if (interfaceOrientation == UIInterfaceOrientationPortrait) { return YES; } return NO; } - (BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; }
在每个控制器添加:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight) { return YES; } return NO; } - (BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskLandscape; }
对于控制器,您有选择器:只设置纵向方向设计此视图。 因此,它将具有相同的选择器方向。 此视图将是纵向方向的唯一视图,而其他视图具有横向。
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { if (interfaceOrientation == UIInterfaceOrientationPortrait) { return YES; } return NO; } - (BOOL)shouldAutorotate { UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation]; if (orientation==UIInterfaceOrientationPortrait) { } return YES; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; }
其他解决方案也会在具有拾取器的视图中崩溃,因为它们不会返回纵向方向来处理拾取器方向。 虽然不向此视图控制器添加任何代码,但此视图将以横向和纵向方式运行。
所以,我建议的解决方案是在横向上运行所有视图,而在纵向中运行这个视图。 在纵向中具有该视图对于具有相同的拾取器方向而言更具设计逻辑性。
以下内容进入您的自定义选择器:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { if (interfaceOrientation == UIInterfaceOrientationPortrait) { return YES; } return NO; } - (BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; }
您还应该在子类中设置:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationLandscapeLeft ; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskLandscape; } - (BOOL)shouldAutorotate { return YES; }
现在您可以从“肖像”设置中删除
[编辑]由于UIImagePickerController只能以肖像forms呈现(根据Apple文档),可以采用相反的方式,实现纵向和横向,但是除了拾取器控制器外,还可以固定方向。 我从这里下载了一些样本。
实际上我遇到了同样的问题并以不同的方式解决了……实际上这被认为是IOS6中的一个错误,ImageViewController只支持Portrait方向…所以我花了很多时间并找到了解决方法。 …
希望这有助于首先……
在AppDelegate.h中添加一个属性
@property BOOL model;
然后在AppDelegate.m中
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. self.model=NO; return YES; }
也在AppDelegate.m中添加此方法
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { if(!self.model) return UIInterfaceOrientationMaskLandscape; //or needed orientation else return UIInterfaceOrientationMaskAllButUpsideDown; }
然后在你的视图控制器中呈现imagepicker
实现此代码……
AppDelegate *appdelegate=(AppDelegate*)[[UIApplication sharedApplication] delegate]; appdelegate.model=YES;
然后你只需在选择图像后返回时更改值,即委托方法
AppDelegate *appdelegate=(AppDelegate*)[[UIApplication sharedApplication] delegate]; appdelegate.model=NO;