如何通过故事板,initWithCoder,viewDidLoad和viewDidLayoutSubviews有效管理屏幕大小更改和重绘?

时间:2018-02-04 01:02:50

标签: objective-c iphone storyboard initwithcoder viewdidlayoutsubviews

我正在使用故事板布局来设置视图布局。

我支持iPhone和iPad布局。

使用initWithCoder:创建视图时,最初使用我最后在Interface Builder中查看的设备的帧大小创建它。

如果我在界面构建器中使用iPhone X布局设计,然后在iPad上构建和运行,则最初使用iPhone X屏幕尺寸创建视图。然后调用viewDidLayoutSubviews:并将屏幕尺寸更新为正确的iPad尺寸。

  1. 子视图在UIViews中使用drawRect来绘制视图图形。我这样做,所以我可以通过代码更改图形颜色。我更改了颜色变量,然后在视图上调用setNeedsDispay,使用CGGraphicsContext命令用新颜色重绘视图。

  2. 它还允许我绘制任何大小的任何图形图像。并且有很多图形意味着我不必在我的包中包含1x,2x和3x尺寸的所有不同图像。这些都是动态绘制的。

  3. 其中一些图像是在加载视图时布局的,而不是在Interface Builder中布局的。所以我检查屏幕尺寸并相应地绘制按钮大小和位置。

  4. 会发生什么,viewDidLoad被调用,它会根据初始屏幕尺寸绘制图形。

    然后调用viewDidLayoutSubviews并且我必须更新我手动根据新屏幕尺寸重新定位它们的子视图的绘图,然后调用它们上的drawRect。我觉得这只是该设备不必要的额外工作。

    除此之外,由于其他原因调用viewDidLayoutSubviews,然后只是在viewController的初始加载时调整视图大小。因此,每次调用它时,它都会重绘子视图,即使它们不需要它。

    而且,如果我运行的设备与我在Interface Builder中使用的设备相同,则它不会调用viewDidLayoutSubviews。我不能让视图布局子视图,因为无法保证它将被调用。

    到目前为止我的解决方案是创建一个跟踪屏幕宽度的变量。我在viewDidLoad中设置变量。如果它以iPhone X大小创建视图,我的screenWidthTracker = 1125。调用viewDidLayoutSubviews时,我将当前屏幕大小与screenWidthTracker进行比较。

    if (self.view.frame != screenWidthTracker) {
         [[NSNotificationCenter defaultCenter] postNotificationName:@"updateView" object:self];
    };
    

    如果视图已更改大小,则会向重绘视图发送消息。我作为子视图手动放置的任何视图都被注册为侦听@“updateView”。

    有没有更好的方法来管理它?是否有一种方法只在屏幕尺寸发生变化时调用,而不是在更新其他子视图的位置时调用?我应该使用viewDidAppear吗?我觉得好像在链中太晚了,我不希望用户看到按钮大小更新。

1 个答案:

答案 0 :(得分:0)

一般来说,从你给出的描述来看,我说最多,你应该通过使用autolayout(你可以在故事板中完全配置)然后实现尽可能多的工作量。仅限drawRectviewDidLayoutSubviews - 后者仅在您需要时才使用。

一个非常常见的策略是使用布尔标志在第一次调用viewDidLayoutSubviews中设置初始条件,之后不再使用它。屏幕大小更改启动后(不是启动时),例如轮换,通过实施willTransition(to:with:)检测到 - 甚至那时你应该检查一下尺寸和新尺寸不一样(180度旋转),如果它们没有任何作用。