在 iOS 7 中呈现 UIImagePickerController 的问题
Posted
技术标签:
【中文标题】在 iOS 7 中呈现 UIImagePickerController 的问题【英文标题】:Issue with presenting UIImagePickerController in iOS 7 【发布时间】:2013-10-31 11:34:56 【问题描述】:我的应用程序仅在横向模式下运行!所以我知道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
,这个问题可以解决:
问题是,如果我选中此选项,我的应用程序也会纵向运行,但我不想要它!
我该如何解决这个问题?
【问题讨论】:
@Mc.Lover - 你试过我的解决方案了吗? 我通过示例添加了一个可行的解决方案 【参考方案1】:我已经对其进行了测试,发现您不应该通过目标窗口中的复选框来处理方向,如上图所示,因为它是您的整个应用程序方向,因此请选中所有框以支持所有方向。如果你想要一些不同方向的视图和一些不同的视图,那么你必须通过在 ViewController
类中的编码来处理它,方法是返回 YES
或 NO
用于方向。
这是我的Sample。我做的。请检查。
下面的方法将处理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
(适用于所有视图控制器)制作两个自定义类,并将它们用于特定方向并将这些类用作UIImagePickerController
的超类以及所有ViewControllers
。
【讨论】:
【参考方案2】:有一种简单的解决方案可以避免更改应用支持的方向,并使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:
,一种递归方法)。如果找到 UIImagePickerController,则返回 UIInterfaceOrientationMaskAll
,否则返回应用的默认设置。
我建议你的另一件事:不要继承UIImagePickerController
,因为Apple 明确禁止它。相反,像我在这个例子中所做的那样使用视图控制器包含:
Landscape Picker Example
注意:示例代码仅适用于 UIImagePickerController
遏制。如果您将其子类化并通过presentViewController:
添加它,您可能需要调整hasPicker:
方法的行为。您可以做的另一件简单的事情是:向您的 UIApplication
子类添加一个实例变量,并在您显示选择器时设置它,并在您关闭时取消设置
【讨论】:
【参考方案3】:另一种解决方案。
在每个控制器中添加,甚至添加到具有选择器的控制器:
- (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;
【讨论】:
我认为这个解决方案会为您解决问题。我更深入地研究了它。 如果这也崩溃了。你只有我提出的其他解决方案。 我终于找到了解决办法!我创建了一个自定义导航控制器并将其与主 ViewController 链接 而自定义导航控制器与选择器的关系如何?【参考方案4】:在每个控制器中添加:
- (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;
【讨论】:
除非选中肖像,否则仍然会崩溃! 答案没有崩溃你是指另一个吗? ios 7 中的选择器仅以纵向显示。你是风景。这个答案建议您将设计更改为仅包含选择器的视图的纵向。因为您也不希望视图方向与选择器方向不同。 这个答案有 3 个不同的代码。一个用于所有视图,一个用于包含选择器的视图。一个用于自定义选择器。你这样做了吗? 另一种解决方案,您将选择器放在具有纵向方向的单独视图控制器中。当您想显示选择器时,您会显示该视图,然后显示您的选择器。当用户选择时。隐藏选择器并关闭视图以返回原始视图。明白了吗?【参考方案5】:你还应该在子类中设置:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
return UIInterfaceOrientationLandscapeLeft ;
- (NSUInteger)supportedInterfaceOrientations
return UIInterfaceOrientationMaskLandscape;
- (BOOL)shouldAutorotate
return YES;
现在您可以从设置中删除“肖像”
[编辑] 由于 UIImagePickerController 只能以纵向显示(根据 Apple 文档),因此可以反其道而行之,启用纵向和横向方向,但将除选取器控制器之外的所有对象的方向固定为横向。我做了一个可以从here下载的小样本。
【讨论】:
您使用的是容器视图控制器吗?比如 UINavigationController 或 UITabbarController? 不,我不使用 UINavigationController 等.. 只是一个简单的 UIViewControleller 看起来 UIImagePickerController 确实不支持横向,如文档 ***.com/questions/14618546/… 中所述。你应该另谋出路。所以使用3方向,只需将上述方法添加到其他vcs中,不要子类化picker。 午餐选择器在纵向或横向模式下都没有关系!我只是不想在部署信息中检查纵向模式,因为所有视图控制器都在旋转!!!即使我仅使用代码将方向设置为横向模式 这就是重点,你检查它,然后在每个 VC(或者你创建一个抽象 VC 类)中,除了选择器(你没有子类化)你对其他 VC 说只在景观。是您想要做的相反的事情,但它会导致相同的结果。这样,选择器将以纵向正确打开,而另一个只是横向打开。【参考方案6】:其实我有同样的问题,并以不同的方式解决它...... 实际上,这被确定为 IOS6 中的一个错误,它发生在 ImageViewController 上,它只支持纵向方向......所以我花了很多时间找到了一种解决方法......
希望这会有所帮助,所以首先...
在您的 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;
然后在您的视图控制器中呈现图像选择器之前
实现此代码...
AppDelegate *appdelegate=(AppDelegate*)[[UIApplication sharedApplication] delegate];
appdelegate.model=YES;
然后你只需在选择图像后返回时更改值,即委托方法
AppDelegate *appdelegate=(AppDelegate*)[[UIApplication sharedApplication] delegate];
appdelegate.model=NO;
【讨论】:
以上是关于在 iOS 7 中呈现 UIImagePickerController 的问题的主要内容,如果未能解决你的问题,请参考以下文章
更改通过 UIPopOver (iPad) 呈现的 UIImagePicker 的大小
如何模态呈现一个视图来选择 UIImagePicker sourceType?
如何在 iOS 的某些文件输入字段上获取 UIWebView 中 UIImagePicker 选择的图像?