0

我正在使用情节提要布局来设置视图布局。

我同时支持 iPhone 和 iPad 布局。

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

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

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

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

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

发生的事情是,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 吗?我觉得这在链条中为时已晚,我不希望用户看到按钮大小的更新。

4

1 回答 1

0

一般来说,根据您给出的描述,我想说的是,您最多应该通过使用自动布局(您可以完全在情节提要中配置)来做尽可能多的工作,然后只drawRect实现viewDidLayoutSubviews-后者仅在您需要时。

一个非常常见的策略是在第一次调用时使用布尔标志来设置初始条件viewDidLayoutSubviews,然后不再使用它。启动后(不是启动时)屏幕尺寸发生变化,例如旋转,可以通过实施来检测willTransition(to:with:)——即使这样,您也应该检查旧尺寸和新尺寸是否不同(180 度旋转),如果它们不同,则什么也不做.

于 2018-02-04T01:41:44.200 回答