前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >记一次 contentInsetAdjustmentBehavior 引发的bug

记一次 contentInsetAdjustmentBehavior 引发的bug

作者头像
stringwu
发布2022-08-12 12:02:46
6480
发布2022-08-12 12:02:46
举报

1 背景

项目中使用到了UILable来展示相关的文本内容,但内容的大小不确定,有可能会超过屏幕的大小,因此需要在外层嵌套一个UIScrollView来保证内容可以被完全展现给用户,在UILabel确定相关的高度后,再通过设置UIScrollViewcontentSize 来限定UIScrollView的滚动范围,保证全部内容可被浏览到

2 实现代码

2.1 伪代码

代码语言:javascript
复制
class CustomView: UIView {
	let scrollView: UIScrollView
	let titleLabel: UILabel = UILabel()
	.......

	required init() {
		scrollView = UIScrollView.init(frame: CGRect.init(x: 0, y: 0, width: 350, height: screen.height ))
		.........
		self.addSubview(scrollView)
		self.scrollView.addSubview(titleLabel)
	}
	.....

	override func layoutSubviews() {
		super.layoutSubviews()
		//让titleLabel 距离顶部的距离为30
		titleLabel.frame = CGRect.init(x: 0, y: 30, width: self.scrollView.frame.width - 5, height: 80)
        titleLabel.textAlignment = NSTextAlignment.left
        titleLabel.lineBreakMode = NSLineBreakMode.byWordWrapping
        titleLabel.numberOfLines = 0
        titleLabel.sizeToFit()
        //设置scrollView的可滚动范围为 titleLabel的高度加上上面的距离30
        scrollView.contentSize = CGSize(width: 0, height:   titleLabel.frame.height + 30)
       	..............
	}
	............
}

2.2 现象

在按照2.1的方式实现之后,发现titleLabel距离顶部的距离远远不止30那么少,估计都有60了,根本没有达到实际想要的效果,而且不同机器上表现出来还不一样。

3 问题的分析

在发现实现的效果没有达到想要的效果后,就开始进入问题的分析排查阶段。

3.1 排查方向一

一开始就是怀疑自己代码实现有问题,可能是其他地方也设置了距离顶部的top值,因此就尝试缩减给予titleLable的初始的y

代码语言:javascript
复制
//titleLabel.frame = CGRect.init(x: 0, y: 30, width: self.scrollView.frame.width - 5, height: 80)
titleLabel.frame = CGRect.init(x: 0, y: 10, width: self.scrollView.frame.width - 5, height: 80)

titleLable的初始y值从30逐渐缩小于10,但测试发现不管怎样改这个初始的y值,实现的效果其实都差不多,根本没有办法缩小其距离顶部的距离。因此就排除了初始y值设置不对引起的距离过大的猜测。

3.2 排查方向二

在发现不是初始y值的影响后,就猜测大概率是父View的影响,仔细查看了父View的设置代码后,发现其并没有设置顶部Top的距离,一行行代码排查后,怀疑是ContentSize的设置引起的,故注释掉了设置ContentSize的那一行设置:

代码语言:javascript
复制
	override func layoutSubviews() {
		super.layoutSubviews()
		...........
        //设置scrollView的可滚动范围为 titleLabel的高度加上上面的距离30
        //scrollView.contentSize = CGSize(width: 0, height:   titleLabel.frame.height + 30)
       	..............
	}

注释掉这一行代码后,发现问题消失了,但由于没有设置scrollviewcontentSize,整体scrollView没有办法滚动了。这不科学啊,这个只是用来设置可滚动范围的接口啊,难道是我设置的高度太多了?但在尝试设置了多个不同的高度后,发现都没有解决问题。让我有点怀疑人生了。

3.3 排查方向三

在前面排查的方向都没有办法解决问题时,我已经没有其他任何的思绪了,只能去翻阅scrollView的接口文档,查看是否有其他接口会影响到子View的位置情况,发现了一个属性contentInsetAdjustmentBehavior,这个属性是在iOS11以上的系统才有的,并且在官方文档里的解释就是“决定内容偏移量的调整行为”,它的类型为UIScrollView.ContentInsetAdjustment,主要有几个值:

  • automatic :自动调整
  • scrollableAxes:只调整在可滚动方向的
  • never : 不调整
  • always :在调整内容时,自己调整

并且在iOS 11以上的系统,该属性的默认值为always,也就是说在你调整它的contentSize时,系统会自动帮你调整子View的偏移量,这其实也解释了在排查方向二时出现的现象:调整了contenSize时,整体的偏移量会多出很多的问题。

4 最终解决方式

在经历了多个怀疑方向的排查后,终于排查到了真正的问题所在,最终是通过禁用scrollviewcontentInsetAdjustmentBehavior 属性来解决问题:

代码语言:javascript
复制
    if #available(iOS 11.0, *) {
            scrollView.contentInsetAdjustmentBehavior = .never
        }

真正修复问题的代码其实就只有一行,但排查到问题实际花费了我一天的时间,在学习iOS的道路上还任重道远

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-05-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 stringwu的互联网杂谈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2 实现代码
    • 2.1 伪代码
      • 2.2 现象
      • 3 问题的分析
        • 3.1 排查方向一
          • 3.2 排查方向二
            • 3.3 排查方向三
            • 4 最终解决方式
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档