zoukankan      html  css  js  c++  java
  • 记一次 contentInsetAdjustmentBehavior 引发的bug

    注:本文同步发布于微信公众号:stringwu的互联网杂谈记一次 contentInsetAdjustmentBehavior 引发的bug

    1 背景

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

    2 实现代码

    2.1 伪代码

    class CustomView: UIView {
    	let scrollView: UIScrollView
    	let titleLabel: UILabel = UILabel()
    	.......
    
    	required init() {
    		scrollView = UIScrollView.init(frame: CGRect.init(x: 0, y: 0,  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,  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( 0, height:   titleLabel.frame.height + 30)
           	..............
    	}
    	............
    }
    

    2.2 现象

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

    3 问题的分析

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

    3.1 排查方向一

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

    //titleLabel.frame = CGRect.init(x: 0, y: 30,  self.scrollView.frame.width - 5, height: 80)
    titleLabel.frame = CGRect.init(x: 0, y: 10,  self.scrollView.frame.width - 5, height: 80)
    

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

    3.2 排查方向二

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

    	override func layoutSubviews() {
    		super.layoutSubviews()
    		...........
            //设置scrollView的可滚动范围为 titleLabel的高度加上上面的距离30
            //scrollView.contentSize = CGSize( 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 属性来解决问题:

        if #available(iOS 11.0, *) {
                scrollView.contentInsetAdjustmentBehavior = .never
            }
    

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

  • 相关阅读:
    火狐中添加selenium IDE
    loadrunner 手动添加关联
    loadrunner11完整卸载
    phpstudy后门交互式shell
    selenium+python Douyu弹幕机器人
    HTTP头sleep延迟注入
    DDCTF-2019
    感知器
    校园网破解
    pwn-格式化字符串漏洞
  • 原文地址:https://www.cnblogs.com/WoodJim/p/14787228.html
Copyright © 2011-2022 走看看