ios viewWillAppear: 和 viewDidAppear 之间的视图框架变化:
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17637523/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
View frame changes between viewWillAppear: and viewDidAppear:
提问by Jumhyn
I have discovered a strange behavior in my application, where a connected IBOutlet
has its connected view's frame between the calls in my view controller to viewWillAppear:
and viewDidAppear:
. Here is the relevant code in my UIViewController
subclass:
我在我的应用程序中发现了一个奇怪的行为,IBOutlet
在我的视图控制器中对viewWillAppear:
和的调用之间,连接有其连接视图的框架viewDidAppear:
。这是我的UIViewController
子类中的相关代码:
-(void)viewWillAppear:(BOOL)animated {
NSLog(@"%@", self.scrollView);
}
-(void)viewDidAppear:(BOOL)animated {
NSLog(@"%@", self.scrollView);
}
and the resulting log output:
以及由此产生的日志输出:
MyApp[61880:c07] <UIScrollView: 0x1057eff0; frame = (0 0; 0 0); clipsToBounds = YES; autoresize = TM+BM; gestureRecognizers = <NSArray: 0x10580100>; layer = <CALayer: 0x1057f210>; contentOffset: {0, 0}>
MyApp[61880:c07] <UIScrollView: 0x1057eff0; frame = (0 44; 320 416); clipsToBounds = YES; autoresize = TM+BM; gestureRecognizers = <NSArray: 0x10580100>; layer = <CALayer: 0x1057f210>; contentOffset: {0, 0}>
Which clearly shows that the frame is changing between the two calls. I wanted to do setup with the view in the viewDidLoad
method, but if the content is not available for me to change until it is on the screen, that seems pretty useless. What could be happening?
这清楚地表明帧在两次调用之间发生了变化。我想使用viewDidLoad
方法中的视图进行设置,但是如果内容在屏幕上显示之前我无法更改,那似乎没什么用。会发生什么?
回答by George Sachpatzidis
From the documentation:
从文档:
viewWillAppear:
Notifies the view controller that its view is about to be added to a view hierarchy.
通知视图控制器它的视图即将添加到视图层次结构中。
viewDidAppear:
Notifies the view controller that its view was added to a view hierarchy.
通知视图控制器其视图已添加到视图层次结构中。
As a result the frames of the subviews aren't yet set in the viewWillAppear
:
因此,子视图的框架尚未设置在viewWillAppear
:
The appropriate method to modify your UI before the view is presented to the screenis:
在视图显示到屏幕之前修改 UI的适当方法是:
viewDidLayoutSubviews
Notifies the view controller that its view just laid out its subviews.
通知视图控制器它的视图刚刚布局了它的子视图。
回答by Andrea
Autolayout
made a huge change in how we design and develop the GUI of our views. One of the main differences is that autolayout
doesn't change our view sizes immediately, but only when is triggered, that means at a specific time, but we can force it to recalculate our constraints immediately or mark them as "in need" of layout. It works like -setNeedDisplay
.
The big challenge for me was to understand and accept that, we do not need to use autoresizing masks anymore, and frame has become a useless property in placing our views. We do not need to think about view position anymore, but we should think how we want to see them in a space related to each other.
When we want to mix old autoresizing mask and autolayout is when problems arise. We should think about autolayout implementation really soon and try to avoid to mix the old approach in a view hierarchy based on autolayout.
Is fine to have a container view that uses only autoresizing masks, such as a main view of a view controller, but is better if we do not try to mix.
I never used storyboard, but most proably it is correct. Using Autolayout, frame of your views are set when the autolayout engine starts its calculation. Try to ask the same thing right after super of - (void)viewDidLayoutSubviews
method of your view controller.
This method is called when the autolayout engine has finished to calculate your views' frames.
Autolayout
对我们设计和开发视图 GUI 的方式进行了巨大的改变。主要区别之一是autolayout
不会立即更改我们的视图大小,而是仅在触发时更改,这意味着在特定时间,但我们可以强制它立即重新计算我们的约束或将它们标记为“需要”布局。它的工作原理类似于-setNeedDisplay
.
对我来说最大的挑战是理解并接受这一点,我们不再需要使用自动调整大小的蒙版,并且框架在放置我们的视图时已成为无用的属性。我们不再需要考虑视图位置,但我们应该考虑我们希望如何在彼此相关的空间中看到它们。
当我们想要混合旧的自动调整大小蒙版和自动布局时,就会出现问题。我们应该尽快考虑自动布局的实现,并尽量避免在基于自动布局的视图层次结构中混合旧方法。
有一个只使用自动调整大小掩码的容器视图是很好的,例如视图控制器的主视图,但如果我们不尝试混合会更好。
我从未使用过故事板,但最有可能它是正确的。使用自动布局,当自动布局引擎开始计算时,你的视图框架就被设置了。尝试- (void)viewDidLayoutSubviews
在视图控制器的方法super 之后立即询问相同的问题。
当自动布局引擎完成计算视图的帧时调用此方法。
回答by andrei
call
称呼
self.scrollView.layoutIfNeeded()
self.scrollView.layoutIfNeeded()
in your viewWillAppear
method. Afterwards you can access it's frame and it will have the same value as you print in viewDidAppear
在你的viewWillAppear
方法中。之后您可以访问它的框架,它将具有与您打印相同的值viewDidAppear
回答by Siddhesh Mahadeshwar
In my case, moving all frame related methods to
就我而言,将所有与帧相关的方法移动到
override func viewWillLayoutSubviews()
worked perfectly(I was trying to modify constraints from storyboard).
工作完美(我试图从故事板修改约束)。