2013-04-29 24 views
6

任何人都可以给我一个详细的解释,为什么iOS正在处理它的横向方向,它的方式和框架和转换?iOS的风景定位处理在幕后

我正在谈论的是通过登录各视图的生命周期方法的观点说明显示此以下行为:

viewDidLoad: "UIView: 0x1edb5ba0; frame = (0 0; 568 320); autoresize = W+H; layer = <CALayer: 0x1edb5c50>" 

viewWillAppear: "UIView: 0x1edb5ba0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x1edb5c50>" 

viewDidAppear: "UIView: 0x1edb5ba0; frame = (0 0; 320 568); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x1edb5c50>" 

这样做的影响是微妙的,但很有趣。

例如,我启动我的应用程序的初始界面取向,和支持的接口取向都设置为“风景(右home键)”

然后我显示我的RootViewController的像这样:

self.viewController = [[MyViewController alloc] initWithNibName:nil bundle:nil]; 
self.window.rootViewController = self.viewController; 

这个.xib将其方向设置为横向,并将帧设置为0,0,568,320。它正确显示,并且我可以触摸屏幕上的所有点。

当我提出像这样一个子视图的问题然后是:

SomeView *someView = [[SomeView alloc] initWithFrame:self.view.frame]; 
[self.view addSubview:someView]; 

在这个时间点,self.view.frame被报告为(0,0; ​​320 568)和self.view.transform被报告为transform = [0,1,-1,0,0,0]。最好的情况下,最终的结果是我只能触摸我刚刚显示的视图的左侧320像素,最糟糕的情况是视图的布局被屠杀。

由于各种做题,我已经学会了这样做的正确方法如下:

SomeView *someView = [[SomeView alloc] initWithFrame:self.view.bounds]; 
[self.view addSubview:someView] 

我还没有学到过什么是为什么,我对此感到非常好奇。

我更加好奇的是为什么在实例化和显示过程中操纵视图。

自从我与横向专用应用程序纠结已经有一段时间了,但由于某种原因,我认为当前这种实现与早期版本的iOS不同,这是否正确?

回答

0

根据苹果,默认情况下,应用程序支持肖像和风景的方向。当基于iOS的设备的方向发生变化时,系统会发出UIDeviceOrientationDidChangeNotification通知,让任何感兴趣的相关方知道发生了变化。默认情况下,UIKit框架监听此通知并使用它自动更新界面方向。这意味着,除了少数例外,您根本不需要处理此通知。

为什么你必须给框架而不是框架很简单。与纵向视图相比,一旦应用处于横向状态,它的宽度和高度就会互换。所以这导致了损坏的行为。但是,当给出界限时,它会考虑视图的方向并相应地考虑高度和宽度。

当你有看法非常接近视图层次结构(或者实际上在顶部),你可以发现你得到的宽度和高度的这种“交换”的效果顶部控制器。交换通常表现在框架上,但不在视图的边界上。这是因为边界实际上是应用于帧的一些转换 - 有时这些转换包括90度旋转(由于设备处于横向模式)。 请注意,检查框架属性时的确切时间也很重要。如果您在视图加载之后但在屏幕出现之前检查属性,则可能会得到“错误”结果。

0

从王子很好的回答。我只是想从docs附加一条关于UIViewframe物业报价:

警告:如果transform属性不是恒等变换,这个属性的值是不确定的,因此应被忽略。

bounds财产,而另一方面,则认为自己的坐标系中表达,所以它永远不会改变的,不管你设置哪个transform

更新:关于你的最后一段,是什么让你觉得这种行为很奇怪或已经改变了? iOS可以旋转视图层次结构的唯一方法是更改​​视图变换。所以如果你想让不同视图控制器中的所有视图都以相同方式定向,则应该使用某种导航视图控制器或以模态方式呈现控制器。这样,每个控制器将根据相同的规则旋转其视图,而不必手动管理视图间转换。

在早期的日子里,你可以看到像这样的代码:

UIViewController *ctrl = ...; 
[window addSubview.ctrl.view]; 

这是以前windowrootViewController性质,人们往往会滥用这种对自己的看法,这将导致在令人惊讶的结果设备旋转。如果你说你不再看到这些代码,那肯定是一种改变,而且改变的更好,因为代码被破坏了。所以人们只需学会编写能够在方向变化的情况下正确工作的代码。

如果您的游戏的所有UI由游戏引擎呈现,您只需要一个(根)视图控制器。在这种情况下,你根本不需要担心转换。只需查询glView的界限并相应地调整您的glViewport和游戏元素。由于glView将具有不同设备的不同边界,因此只要您不对实际屏幕大小和视图的当前方向作出任何假设,您的游戏就可以在所有设备上进行优雅比例缩放。