UIKit中父视图无法显示子视图内容问题排查
问题:添加子控制器后界面黑屏,无法显示8X8棋盘
我尝试在主控制器MainView中以代码方式添加子控制器BoardViewController,期望展示8X8棋盘,但界面仅显示黑屏,Xcode无报错提示。以下是相关代码:
子控制器BoardViewController代码
import UIKit class BoardViewController: UIViewController { private let boardGame: UICollectionView = { let layout = UICollectionViewFlowLayout() let board = UICollectionView(frame: .zero, collectionViewLayout: layout) board.allowsSelection = true board.translatesAutoresizingMaskIntoConstraints = false return board }() override func viewDidLoad() { super.viewDidLoad() view.addSubview(boardGame) boardGame.frame = view.bounds NSLayoutConstraint.activate([ boardGame.centerXAnchor.constraint(equalTo: view.centerXAnchor), boardGame.centerYAnchor.constraint(equalTo: view.centerYAnchor), boardGame.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16), boardGame.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16), boardGame.topAnchor.constraint(equalTo: view.topAnchor, constant: 16), boardGame.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -16) ]) boardGame.delegate = self boardGame.dataSource = self } init() { super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } extension BoardViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 64 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "unique", for: indexPath) let chessRow = indexPath.row / 8 if chessRow % 2 == 0 { if indexPath.row % 2 == 0 { cell.backgroundColor = UIColor.white }else{ cell.backgroundColor = UIColor.black } } else{ if indexPath.row % 2 == 0 { cell.backgroundColor = UIColor.black }else{ cell.backgroundColor = UIColor.white } } return cell } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let width = collectionView.frame.size.width / 8.0 let height = width return CGSize(width: width, height: height) } }
父控制器MainView代码
import UIKit class MainView: UIViewController { let BoardView = BoardViewController() override func viewDidLoad() { super.viewDidLoad() addBoardView() } func addBoardView(){ addChild(BoardView) view.addSubview(BoardView.view) BoardView.didMove(toParent: self) } }
SceneDelegate代码
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let scene = (scene as? UIWindowScene) else { return } let window = UIWindow(frame: scene.coordinateSpace.bounds) let navVC = UINavigationController(rootViewController: MainView()) window.rootViewController = navVC self.window = window }
遗漏的关键点及修复方案
1. 未注册UICollectionViewCell
使用dequeueReusableCell之前必须先注册cell类型,否则无法创建cell,导致CollectionView无内容显示。在BoardViewController的viewDidLoad中添加注册代码:
override func viewDidLoad() { super.viewDidLoad() view.addSubview(boardGame) // 添加cell注册代码 boardGame.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "unique") // ... 其余代码不变 }
2. 子控制器View未设置约束
在MainView的addBoardView方法中,添加子控制器View后未设置约束,导致子控制器View无法正确铺满父View。修改代码如下:
func addBoardView(){ addChild(BoardView) view.addSubview(BoardView.view) // 关闭自动布局转义并添加约束 BoardView.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ BoardView.view.topAnchor.constraint(equalTo: view.topAnchor), BoardView.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), BoardView.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), BoardView.view.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) BoardView.didMove(toParent: self) }
3. SceneDelegate未激活Window
创建Window后没有调用makeKeyAndVisible(),导致Window无法显示。在SceneDelegate方法末尾添加激活代码:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let scene = (scene as? UIWindowScene) else { return } let window = UIWindow(frame: scene.coordinateSpace.bounds) let navVC = UINavigationController(rootViewController: MainView()) window.rootViewController = navVC self.window = window // 激活Window window.makeKeyAndVisible() }
4. 约束冲突优化(可选)
BoardViewController中同时设置了centerX/Y和四边约束,会导致约束冲突。建议保留四边约束即可,删除centerX/Y的约束:
NSLayoutConstraint.activate([ // 移除这两行冲突约束 // boardGame.centerXAnchor.constraint(equalTo: view.centerXAnchor), // boardGame.centerYAnchor.constraint(equalTo: view.centerYAnchor), boardGame.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16), boardGame.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16), boardGame.topAnchor.constraint(equalTo: view.topAnchor, constant: 16), boardGame.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -16) ])
内容的提问来源于stack exchange,提问作者willd
相关产品推荐
相关产品推荐

