view.traitCollection.horizo​​ntalSizeClass在viewDidLoad中返回undefined(0)

我在UIPageViewController中使用UITextView,我想根据设备的大小类别来确定字体大小。

页面视图的第一张幻灯片像viewControllerAtIndex(0) )一样在ViewDidLoad中加载:

 override func viewDidLoad() { super.viewDidLoad() //Some unrelated code here // Page View Controller for Questions Slider questionPageVC = storyboard?.instantiateViewControllerWithIdentifier("QuestionPageView") as? UIPageViewController questionPageVC!.dataSource = self; questionPageVC!.delegate = self; let startingViewController : QuestionContentViewController = viewControllerAtIndex(0) as QuestionContentViewController var viewControllers = [startingViewController] questionPageVC!.setViewControllers(viewControllers, direction: .Forward, animated: true, completion: nil) let sliderHeight = view.frame.size.height * 0.5 questionPageVC!.view.frame = CGRectMake(20, 70, view.frame.size.width-40, sliderHeight) addChildViewController(questionPageVC!) view.addSubview(questionPageVC!.view!) questionPageVC?.didMoveToParentViewController(self) var pageControl : UIPageControl = UIPageControl.appearance() pageControl.pageIndicatorTintColor = UIColor.lightGrayColor() pageControl.currentPageIndicatorTintColor = UIColor.blackColor() pageControl.backgroundColor = UIColor.whiteColor() // Some more code here } 

然后,在viewControllerAtIndex:

 private func viewControllerAtIndex(index: Int) -> QuestionContentViewController { var pcvc : QuestionContentViewController = storyboard?.instantiateViewControllerWithIdentifier("QuestionContentView") as! QuestionContentViewController var fontSize = "" if (view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.Compact) { fontSize = "20" } else { fontSize = "28" } pcvc.questionString = TextFormatter(string: fontSize + questionsArray[index]).formattedString pcvc.questionIndex = index return pcvc } 

问题是在viewDidLoad中调用的第一张幻灯片始终使用“else”子句中的字体大小。

如果我打印view.traitCollection.horizontalSizeClass ,对于第一张幻灯片,我得到0( UIUserInterfaceSizeClassUnspecified ),对于后续的幻灯片,我得到正确的大小。

我尝试将整个事物移动到“viewWillAppear”,然后奇怪的事情发生在UIPageViewController(在其他幻灯片背后的大小错误的文字)

问题是, viewDidLoad太快会问关于视图的特征收集。 这是因为视图的特征集合是从视图层次结构获取的一个特征,它是它自己发现的环境。 但是在viewDidLoad ,视图没有任何环境:它不在视图层次结构中。 它已经加载 ,意味着它存在:视图控制器现在一个视图。 但是它还没有被join到界面中,直到viewWillAppear: 之后 ,它才会被放入界面。

但是,视图控制器也有一个trait集合,它有一个环境:在调用viewDidLoad的时候,视图控制器是视图控制器层次结构的一部分。 因此,最简单(也是正确)的解决办法是要求self而不是viewtraitCollection 。 只要说self.traitCollection你现在有view.traitCollection ,一切都会好的。

(你的解决scheme,询问屏幕的特征收集,可能会发生作用,但它不可靠,也不是正确的方法,这是因为父视图控制器可能改变它的子特征集合,如果你绕过正确的方法,并直接询问屏幕,你将无法获得正确的特征收集。)

我发现,如果我使用主屏幕的traitCollection,而不是当前的视图,我得到正确的大小类:

 if (UIScreen.mainScreen().traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.Compact) { fontSize = "20" } else { fontSize = "28" } 

将代码移动到viewWillAppear方法会更好,就像在viewDidLoad中一样,ViewController的视图还没有添加到层次结构中,您可能会得到一个空的trait集合。