为什么我通过代码添加的iOS UI组件仅按钮在模拟器中正常显示
问题原因定位
你代码里的核心错误有以下几个:
- 重复初始化UI组件,导致加入StackView的是无效实例
你在类属性声明时已经创建了productImageView、productLabel、paymentTextField的实例,但在对应的setup方法里又重新创建了新的实例:
// 错误写法 func setupProductImage(){ // 这里重新赋值了新的UIImageView,原来加到stackView里的还是最开始声明的空实例 self.productImageView = UIImageView(frame: CGRect(x: 50, y: 50, width: 275, height: 200)) self.productImageView.image = UIImage(named: "stripe press") self.productImageView.contentMode = .scaleAspectFit }
后续你加到StackView里的是类初始化时创建的空实例,配置了属性的新实例根本没有被加入视图层级,所以不会显示。
- StackView尺寸和子视图尺寸不匹配,布局冲突导致组件被压缩/隐藏
你给productStackView设置的高度只有150,但里面的productImageView高度就设置了200,远超过StackView的容纳范围,StackView的equalSpacing分布规则会直接把超出边界的子视图压缩到不可见。另外StackView会自动管理子视图的布局,你给加入StackView的子视图设置的frame都会被覆盖,不会生效。 - viewDidLoad阶段获取的view尺寸不准确
你在setup方法里用self.view.frame.width计算组件宽度,但viewDidLoad调用时view的布局还没有完成,拿到的尺寸是xib/Storyboard里的默认尺寸,不是当前设备的实际尺寸,会导致组件位置偏移或者超出屏幕边界。 - paymentTextField宽度超出StackView容器范围
你给paymentTextField设置的宽度是330,但它的父容器paymentStackView宽度只有300,超出的部分默认不会显示。
修复建议
- 删掉setup方法里的重复初始化代码,直接修改类属性的属性即可:
// 正确写法示例 func setupProductImage(){ // 不要重新创建UIImageView,直接配置已有的实例 self.productImageView.frame = CGRect(x: 50, y: 50, width: 275, height: 200) self.productImageView.image = UIImage(named: "stripe press") self.productImageView.contentMode = .scaleAspectFit }
setupProductLabel、setupPaymentTextField方法也要做同样的修改,去掉重新赋值新实例的代码。
2. 调整StackView的尺寸,或者给加入StackView的子视图添加宽高约束,不要直接给子视图设置frame。比如给productImageView添加宽275、高200的约束,给productLabel添加高50的约束,再把productStackView的高度调整到大于等于260,保证子视图可以正常显示。
3. 涉及到用view尺寸计算的布局逻辑,移到viewDidLayoutSubviews方法里执行,保证拿到的是当前设备的实际尺寸。
4. 调整paymentTextField的宽度不超过父容器paymentStackView的宽度,或者给paymentStackView的宽度调整到330以上。
内容的提问来源于stack exchange,提问作者askit
相关产品推荐
相关产品推荐

