iOS 笔记

一. 点击uiscrollview的子视图,即使不产生滑动,总是会走- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

测试发现:

  • 如果是代码创建的scrollview,在scrollview上面添加子视图button,点击button,不产生滑动,并不会走scrollViewDidEndDecelerating
  • 如果是xib创建的scrollview,点击button,即使不产生任何滑动,总是会走scrollViewDidEndDecelerating,即使添加的是其他子视图uiview,也是一样。这种情况,只需要取消scrollview.pagesnable=yes,就可以了。是不是xib多设置了什么东西,没搞明白。

二. xib自定义的控件,用纯代码加载,报错找不到xib控件拉好的IBOutlet属性

  • 报错:
    *** Terminating app due to uncaught exception   'NSUnknownKeyException',
    reason: '[<UIView  0x12e80adb0> setValue:forUndefinedKey:]: 
    this class is  not key value coding-compliant for the key searchBtn
    
  • xib控件File`s Owner关联的类取消,改由view关联对应的类
  • xib的属性全部重新拉线(由File`s Owner改为view关联,拉线的属性不改还是会报错)
  • xib控件是作为另一个xib的子视图,不是由代码加载,不用改

三. scrollview滑动卡住,也不崩溃。

  • (void)layoutSubviews不要做任何frame的更新,因为scrollview滑动会一直调用- (void)layoutSubviews,里面做frame更新,又会反过来调用- (void)layoutSubviews,就会一直卡在这个方法里

四.scrollview里面添加button或者其他控件,不能点击

  • 是因为scrollview加了撑开的contentview,button又加载contentview上,contentview高度或者宽度显示不下button,导致点击传递事件到了contentview就找不到下层的button了。
  • 层级关系: scrollview-> contentview->button,contentview的size装载不下button。传递事件断裂

五. tablefooterview的按钮不能点击

  • 很多帖子讲是tabletooterview``的高度不够,这其实是个很明显的问题,跟上面第四条```道理一样。
  • 但其实,我有次明显设置了footerview的高度,也看了层级关机,没有被遮挡。后来发现,原来是设置了渐变色的原因,因为渐变色是用layer去实现的,直接把渐变色layer加在button上,会遮挡button文字显示。所以写了个分类,渐变色layer加载一个bgview上,再把bgview加在button的最底层。这样就可以实现渐变色背景的按钮。但是!!!!我们点击的响应,也直接点击在bgview上,所以button接收不到响应链。解决办法,bgView.isUserInteractionEnabled = false/或者self.colorView.userInteractionEnabled = NO。部分代码如下:
    let gradientLayer = CAGradientLayer()
    gradientLayer.frame = self.bounds
    gradientLayer.colors = array
    gradientLayer.locations = [0.0,1.0]
    gradientLayer.startPoint = CGPoint.init(x: 0, y: 0.5)
    gradientLayer.endPoint = CGPoint.init(x: 1, y: 0.5)
              
    let bgView = UIView(frame: self.bounds)
    bgView.isUserInteractionEnabled = false //不设置这句,button的点击是点击在bgview上
    self.addSubview(bgView)
    self.sendSubviewToBack(bgView)
    bgView.layer.addSublayer(gradientLayer)
    

五. tableview.tableFooterView和tableview.tableHeaderView的高度或者宽度有问题。

  • tableview.tableFooterView要初始化frame
  • tableview.tableFooterView不能直接=self.footerView,解决办法,先赋值一个view,再让view addsubview,如下:
  UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 700)];
  [view addSubview:self.footerView];
  tableview.tableFooterView = view
  • tableview.tableHeaderView同理

六.@property (getter=isActive) BOOL active,设置yes/no,不生效

  • 我遇到的情景是,做聊天气泡时,xib上拉label的left和right约束,根据内容决定label的left或者right约束的active是yes还是no,从而决定label是靠左还是右。然后有时候会出现label左右位置混乱。解决:
    • 拉lable的left或者right作为属性时,是weak修饰,改为strong就可以了(个人猜测,当active=no时,约束不生效的原因,其实就是移除了该约束,然而因为是weak修饰,当再次设置该约束active=yes时,其实该约束已经不存在了,所以更改strong修饰后,再次修改active=yes,还是能生效)。

七。更改状态栏颜色问题(-(UIStatusBarStyle)preferredStatusBarStyle不调用问题)

  • 在info.plist 中 View controller-based status bar appearance 一定要改为为 YES

  • navigationcontroller中添加:

    - (UIViewController *)childViewControllerForStatusBarStyle {
     return self.topViewController;
    }
    
  • 每个Viewcontroller中添加:

    -(UIStatusBarStyle)preferredStatusBarStyle
     {
     return UIStatusBarStyleDarkContent;
     }
    
  • 需要注意,如果有导航栏navigationcontroller,状态栏颜色由导航栏统一管理,事实上由导航栏管理也最好。如果需要单独改变某个状态栏,就单独在那个控制器实现preferredStatusBarStyle

  • 状态一直是白色,怎么也改不到黑色:暗黑模式下无法设置为黑色,关闭暗黑模式 info.plist-->Appearance = Light。关闭之后再检查preferredStatusBarStyle返回的是深色字体还是白色字体。

八。使用UINavigationController,控制器self.view距离顶部的距离,一会高,一会低。(UICollectionView/UITableView顶部会留白的解决办法)

  • 场景:从控制器A,进入控制器C,C的self.view是全屏,距离顶部是0。从控制器B,进入控制器C,C的self.view距离顶部有个一导航栏的高度。这就导致控制器C写这样的布局,也会变化:
  [_headerView mas_makeConstraints:^(MASConstraintMaker *make) {
     make.top.equalTo(self.view).offset(0);
  }];
  • 原因:设置.translucent这个属性,会影响UIViewcontroller的布局:
    • .translucent = NO,导航栏取消毛玻璃效果(导航栏设置什么颜色就是什么颜色,可以理解为会遮挡下一层的self.view),self.view的原点是从导航栏左下角开始计算。
    • .translucent = YES,导航栏显示毛玻璃效果(导航栏会有一层模糊的半透明的毛玻璃效果,可以理解为,即使第一层从导航栏滚过,也会看到一点点,不会遮挡self.view),self.view的原点是从导航栏左上角开始计算。
  • 解决:在哪个控制器设置过self.navigationController.navigationBar.translucent = NO,就在这个控制器viewWillDisappear中,设置回来(self.navigationController.navigationBar.translucent = YES)
  • 或者直接设置:(self.collectionview/self.tableview顶部会留白的解决办法)
    if (@available(iOS 11, *)) {
     self.collectionView.contentInsetAdjustmentBehavior  =     UIScrollViewContentInsetAdjustmentNever;
    }else{
     self.automaticallyAdjustsScrollViewInsets = NO;
    }
    

九。两个UICollectionView嵌套,都使用MJRefresh。滑动方向冲突

  • 场景:UICollectionView(A)和UICollectionView(B)A是横向滚动,每个cell是当前控制器的view大小。B是纵向滚动的瀑布流布局,加载A的cell上。
    这个时候在屏幕上斜方向滑动,会产生AB同时一起斜方向滑动。按照场景需求,应该是要么纵向滚动瀑布流,要么横向滚动页面。
  • 原因:后来看了MJRefresh源码,大概是,他给UICollectionView加了一个滑动手势,滑动时候,把scrollviewcontentInset还是contentOffset来着,把它的值改变,形成继承于scrollview的视图也跟着手势滑动的效果。
    • 至于为什么一个collectionview不会斜方向滑动,两个嵌套就会斜方向滑动,就没有深入追究了
  • 解决:
    • 要么AB,只留一个使用MJRefresh。上拉刷新下拉加载的功能也就只能添加在A或者B上。
    • 要么就把A或者Bmj_headermj_footer给移除掉,其实产生的效果等同于上面。

十.UITableView,用masnory布局约束,发现底部往下偏移了,也就是底部有部分显示不了

  • 场景:这个情况比较特殊,不具备普遍化,自己碰到过,记下来。因为上面第条原因,所以自己在自定义TableView基类的时候,会用一个方法禁止掉MJRefresh功能:
    self.mj_header?.scrollView?.bounces = false
    self.mj_footer?.scrollView?.bounces = false
    self.mj_header?.scrollView?.contentInset = .zero
    self.mj_footer?.scrollView?.contentInset = .zero
    self.mj_header?.endRefreshing()
    self.mj_footer?.endRefreshing()
    self.mj_footer?.removeFromSuperview()
    self.mj_header?.removeFromSuperview()
    

然而,在不需要刷新功能的界面,为了防止出现布局混乱,调用了上面这个方法,结果就出现tableview底部,被屏幕遮住了。而检查约束条件make.edges.equalToSuperview(),这完全没问题。

  • 原因:打开层级显示,定位TableView,发现这段话:
baseClass = UITableView; frame = (0 64; 375 603); clipsToBounds = YES; 
contentOffset: {0, 198}; contentSize: {375, 845}; adjustedContentInset: {0, 0, -44, 0}; 

contentOffset: {0, 198},这说明tableview无缘无故往下移动了198。这是什么原因?

  • 解决:无意中,注释掉上面说的基类tableview中的禁止MJRefresh功能方法中的,两行代码,解决了!而且层级定位发现contentOffset: {0, 0}
       就是注释了这两行代码
       //self.mj_header?.scrollView?.contentInset = .zero
       //self.mj_footer?.scrollView?.contentInset = .zero
    
  • 思考:为什么,MJRefresh中的mj_header/mj_footer,禁止scrollView?.contentInset,会导致UITableView的contentOffset: {0, 198},MJRefresh做了什么?
  • 探究:
    • 原来self.mj_header?.scrollView?等于self.mj_header?.superView等于self(tableView)
    • 然而,断点打印如下:
      (lldb) po self.mj_header?.scrollView?.contentInset
      ▿ Optional<UIEdgeInsets>
      ▿ some : UIEdgeInsets
      - top : 0.0
      - left : 0.0
      - bottom : 44.0
      - right : 0.0       
      
    • 所以,注释掉那两行代码,就是让tableview.contenInset,由系统建立的距离底部的值bottom=44(正常显示)变成bottom=0(被遮挡一部分),可不就是遮挡了嘛
  • 最后:至于为什么不注释那两行,contentOffset: {0, 0},注释掉就变成contentOffset: {0, 198}。有待考证

十一.UICollectionView截屏,显示不全问题

  • 场景: 自定义布局的UICollectionView,cell是xib,一个section只有一个item。需要截取全部collectionView,生成图片分享。截屏代买如下:
    let frame = collectionView.frame
    UIGraphicsBeginImageContextWithOptions(collectionView.contentSize, false, 0)
    collectionView.layer.frame = CGRect(x:0, y:0, width:kUIScreenWidth, height:collectionView.contentSize.height)
    collectionView.layer.render(in: UIGraphicsGetCurrentContext()!)
    let collectionViewImg = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    collectionView.frame = frame
    return  collectionViewImg
    
  • 问题:上面代码,只会截取已经出现在屏幕的cell,对于未出现的cell,截取的空的。
  • 原因:
    • 原来在基类控制器设置过:
      self.navigationController?.navigationBar.isTranslucent = false
      
    • isTranslucent = false 设置带来的直接结果是,控制器的顶部屏幕的顶部距离一个导航栏的高度
    • 也会导致截屏时,对于未展示过的cell,不会调用datasource去加载cell,所以未展示过的cell的layer,自然是空白的。(为什么会这样,不得而知)
    • isTranslucent 其他的影响

十二. UICollectionView反向序列排列

  • 场景:layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;下,collectionview滚动是从右往左滚动的,那么如果从坐往右滚动呢?比如滑动翻日历,往往进去就是默认最近的日历,往前翻,就需要反向排列了。
  • 解决:自定义UICollectionViewFlowLayout,全部代码如下:
    #import "RCalendarLayout.h"
    
    @implementation RCalendarLayout
    ///决定flowyout是否能主动选择其他滚动方向,默认NO
    - (BOOL)flipsHorizontallyInOppositeLayoutDirection
    {
      return YES;
    }
    ///决定flowyout的滚向,默认是LeftToRight
    - (UIUserInterfaceLayoutDirection)developmentLayoutDirection
    {
      return UIUserInterfaceLayoutDirectionRightToLeft;
    }
    @end
    
  • 这两个方法的理解可能有误,最好点进原方法,看注释。

十三. UICollectionView的UICollectionElementKindSectionHeader,设置在Cell的背后。

  • 默认自定义UICollectionElementKindSectionHeader的时候,会在cell的上层,如果要cell遮挡sectionHeader的效果,就要自定义UICollectionViewFlowLayout,具体方法如下:
     - (NSArray<__kindof UICollectionViewLayoutAttributes *>  *)layoutAttributesForElementsInRect:(CGRect)rect
    {
        NSArray *attributes  = [[super layoutAttributesForElementsInRect:rect] copy];
        for (UICollectionViewLayoutAttributes *attr in attributes) {
        CGRect frame = attr.frame;
        if (frame.size.height < 300) {
            CGPoint origin = frame.origin;
            origin.y = origin.y - 60;
            frame.origin = origin;
            attr.frame = frame;
            attr.zIndex = attr.indexPath.row + 1;///此属性是关键,cell.zIndex 最小值是1,依次递增
        }else{
            attr.zIndex = 0;///此属性是关键,sectionheader.zIndex 永远是0
         }
       }
      return  attributes; }
    

十四. UITableView的tableHeaderView | sectionHeaderView留白解决方法

  • 方法1:tableHeaderView: 一般解决办法(带有导航栏)

    ///self=UIViewController
    ///tableView.tableViewStyle = UITableViewPlan
    
    if #available(iOS 11.0, *) {
             tableView.contentInsetAdjustmentBehavior = .never
         } else {
             self.automaticallyAdjustsScrollViewInsets = false
         }
    
  • 方法2: 我的场景是:没有导航栏tableView.tableViewStyle = UITableViewGroup设置方法1后,还是留白。

    • 需要再加上以下属性:
      其实就是要设置tableView的sectionHeaderViewtableHeaderView的高度
       tableView.tableHeaderView = UIView(frame:.zero)
       # 如果上面不生效,则用下面方法试试
      self.tableView.tableHeaderView = UIView(frame:CGRect(x:0, y:0, width:0.01, height: 0.01))
      self.tableView.tableFooterView = UIView(frame:CGRect(x:0, y:0, width:0.01, height: 0.01))
      
  • 方法3: 我的场景是:顶部空白高度=22,(没有导航栏,tableView.tableViewStyle = UITableViewPlain),iphone8,ios16.1,

     if #available(iOS 15.0, *) {
            self.tableView.sectionHeaderTopPadding = 0
     } else { }
    
  • 其他类似的问题,可能会误导致顶部有一段小留白的:

    • sectionHeaderView: 也有个类似的场景:tableview的style = .group时,sectionHeaderView的高度,会有默认的一段高度。即使设置了delegatesectionHeaderView的高度return 0不生效。return = 0.01生效。
    • sectionFooderView同上。
    • 小结:在某些iOS版本中,tablestyle = .group场景下,无论是tableHeaderView还是sectionHeaderView,对其相应的方法设置高度=0,都无效,需要设置高度=0.01

十五.关于切圆角不生效问题

  • 下面代码不生效问题:
     cell.contentView.cornerRadius = 10;
     cell.contentView.layer.masksToBounds = YES;
    
  • 检查cell的颜色,color会影响layer。某种情况下发现,xib设置的cell,如果背景颜色是默认的,上面呢代码不会生效。
  • 设置圆角加阴影,用以上方法,会产生离屏渲染,用下面方法:
    let bounds = CGRect(x:0, y: 0, width:w, height: 216.0/162*w)
    self.layer.shadowPath = UIBezierPath(roundedRect:bounds, byRoundingCorners:[.topLeft,.topRight,.bottomLeft,.bottomRight], cornerRadii: CGSize(width:4, height: 4)).cgPath
    self.layer.shadowColor = "#CFCFCF".color().cgColor
    self.layer.shadowOffset = CGSize(width: 0, height: 0)
    self.layer.shadowRadius = 4
    self.layer.shadowOpacity = 1
    self.layer.cornerRadius = 4
    self.layer.masksToBounds = false ///一定要设置这个
    

十六.UITextView带link的富文本,下划线和link字符串颜色设置问题

let text = "By clicking start, you agree to our Terms and Conditions and Privacy Statement.".attri(UIFont.systemFont(ofSize: 14), "#E2665C".color())
var attri = [.underlineStyle:NSUnderlineStyle.single.rawValue,.underlineColor:"#E2665C".color(),.link:"privacy"] as [NSAttributedString.Key : Any]
var attri2 = [.underlineStyle:NSUnderlineStyle.single.rawValue,.underlineColor:"#E2665C".color(),.link:"agreement"] as [NSAttributedString.Key : Any]

text.addAttributes(attri, range: NSRange(location:36, length: 20))
text.addAttributes(attri2, range: NSRange(location: 61, length: 18))
        
self.agreement.attributedText = text
self.agreement.linkTextAttributes = [.foregroundColor:"#E2665C".color()]

十七.XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphoneos.a

  • error:
SDK does not contain 'libarclite' at the path
'/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphonesimulator.a';
try increasing the minimum deployment target 
  • 原因: Xcode 14.3移除了arc目录,因为Xcode 14支持的最低部署目标iOS 11, 最低部署版本的系统都已经内置了ARC相关的库, 我们只需要将第三方库部署目标的iOS版本设置成和应用最低部署目标的iOS版本即可
  • 解决方法1: 原方法摘自这试过,并不能统一解决第三方库的目标最低部署版本
post_install do |installer|
  installer.generated_projects.each do |project|
    project.targets.each do |target|
        target.build_configurations.each do |config|
            config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' #9.0
         end
    end
  end
end

但是,我的Podfile,加上上面方法,会报很多错误!!!

  • 解决方法2: 根据上面所说,将第三方库的最低部署iOS的版本,改到ios11以上就可以了
    • Xcode 左侧文件栏最顶部,有个⚠️号的按钮,点击,找到报错的第三方库
    • 左侧文件栏,点击Pods.xcodeproj->Targets->对应三方库->General->修改Minimum Deployments = iOS11以上
  • 解决方法3: 既然最新的xcode没有这arc个文件夹,那 下载arc文件夹,放到对应路径下就可以了

    • 进入路径/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/
    • 下载arc文件夹,放到lib/下
    • 如果有arc文件夹,那么就下报错对应的libarclite_iphonesimulator.a,放到arc文件夹下
    • arc文件夹和对应的x x x.a库文件,到别的xcode路径下粘贴复制

十八.Command PhaseScriptExecution failed with a nonzero exit code

  • 该报错有一定概率是cocoapods 的问题,可以试试升级版本:
    • 更新gem:sudo gem update --system

    • 下载最新版本:sudo gem install -n /usr/local/bin cocoapods --pre

19. Showing Recent Errors Only Sandbox: rsync.samba(93467) deny(1) file-write-create

  • 现象:Showing Recent Errors Only Sandbox: rsync.samba(93467) deny(1) file-write-create /../../../xxxx类似的问题。
  • 解决:Xcode ->target->building setting:ENABLE_USER_SCRIPT_SANDBOXING=
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容

  • *7月8日上午 N:Block :跟一个函数块差不多,会对里面所有的内容的引用计数+1,想要解决就用__block...
    炙冰阅读 2,460评论 1 14
  • 1、禁止手机睡眠 [UIApplication sharedApplication].idleTimerDisab...
    小小夕舞阅读 1,428评论 1 1
  • 1、登录(文本输入、按钮交互、基于网络的交互) 2、刷新界面:(表视图) 1>小部分应用程序数据来源于本地 2>更...
    炙冰阅读 734评论 0 1
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,945评论 4 60
  • 1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是...
    失忆的程序员阅读 621评论 0 1