推广

2. iOS面试题UI篇

iseeyu2年前 (2024-02-22)推广166

ViewControllerfiview olft.png

IBOutlet连出来的视图属性为什么可以被设置成weak?

  • 因为父控件的subViews数组已经对它有一个强引用

IB中User Defined Runtime Attributes如何使用?

  • User Defined Runtime Attributes是一个不被看重但功能非常强大的的特性,它能够通过KVC的方式配置一些你在interface builder中不能配置的属性
  • 当你希望在IB中作尽可能多得事情,这个特性能够帮助你编写更加轻量级的viewcontroller

沙盒目录结构是怎样的?各自用于那些场景?

  • Application:存放程序源文件,上架前经过数字签名,上架后不可修改

  • Documents:常用目录,iCloud备份目录,存放数据

  • Library

  • Caches:存放体积大又不需要备份的数据

  • Preference:设置目录,iCloud会备份设置信息

  • tmp:存放临时文件,不会被备份,而且这个文件下的数据有可能随时被清除的可能

pushViewController和presentViewController有什么区别

  • 两者都是在多个试图控制器间跳转的函数
  • presentViewController提供的是一个模态视图控制器(modal)
  • pushViewController提供一个栈控制器数组,push/pop

请简述UITableView的复用机制

  • 每次创建cell的时候通过dequeueReusableCellWithIdentifier:方法创建cell,它先到缓存池中找指定标识的cell,如果没有就直接返回nil
  • 如果没有找到指定标识的cell,那么会通过initWithStyle:reuseIdentifier:创建一个cell
  • 当cell离开界面就会被放到缓存池中,以供下次复用

如何高性能的给 UIImageView 加个圆角?

  • 不好的解决方案

  • 使用下面的方式会强制Core Animation提前渲染屏幕的离屏绘制, 而离屏绘制就会给性能带来负面影响,会有卡顿的现象出现

self.view.layer.cornerRadius = 5;
 self.view.layer.masksToBounds = YES;
  • 正确的解决方案:使用绘图技术
- (UIImage *)circleImage

{

  // NO代表透明

 UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0);

  // 获得上下文

 CGContextRef ctx = UIGraphicsGetCurrentContext();

  // 添加一个圆

 CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);

 CGContextAddEllipseInRect(ctx, rect);

  // 裁剪

 CGContextClip(ctx);

  // 将图片画上去

 [self drawInRect:rect];

 UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

  // 关闭上下文

 UIGraphicsEndImageContext();

 return image;

}
  • 还有一种方案:使用了贝塞尔曲线”切割”个这个图片, 给UIImageView 添加了的圆角,其实也是通过绘图技术来实现的
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];

imageView.center = CGPointMake(200, 300);

UIImage *anotherImage = [UIImage imageNamed:@"image"];

UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);

[[UIBezierPath bezierPathWithRoundedRect:imageView.bounds

 cornerRadius:50] addClip];

[anotherImage drawInRect:imageView.bounds];

imageView.image = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

[self.view addSubview:imageView];

使用drawRect有什么影响?

  • drawRect方法依赖Core Graphics框架来进行自定义的绘制
  • 缺点:它处理touch事件时每次按钮被点击后,都会用setNeddsDisplay进行强制重绘;而且不止一次,每次单点事件触发两次执行。这样的话从性能的角度来说,对CPU和内存来说都是欠佳的。特别是如果在我们的界面上有多个这样的UIButton实例,那就会很糟糕了
  • 这个方法的调用机制也是非常特别. 当你调用 setNeedsDisplay 方法时, UIKit 将会把当前图层标记为dirty,但还是会显示原来的内容,直到下一次的视图渲染周期,才会将标记为 dirty 的图层重新建立Core Graphics上下文,然后将内存中的数据恢复出来, 再使用 CGContextRef 进行绘制

描述下SDWebImage里面给UIImageView加载图片的逻辑

  • SDWebImage 中为 UIImageView 提供了一个分类UIImageView+WebCache.h, 这个分类中有一个最常用的接口sd_setImageWithURL:placeholderImage:,会在真实图片出现前会先显示占位图片,当真实图片被加载出来后在替换占位图片

  • 加载图片的过程大致如下:

  • 首先会在 SDWebImageCache 中寻找图片是否有对应的缓存, 它会以url 作为数据的索引先在内存中寻找是否有对应的缓存

  • 如果缓存未找到就会利用通过MD5处理过的key来继续在磁盘中查询对应的数据, 如果找到了, 就会把磁盘中的数据加载到内存中,并将图片显示出来

  • 如果在内存和磁盘缓存中都没有找到,就会向远程服务器发送请求,开始下载图片

  • 下载后的图片会加入缓存中,并写入磁盘中

  • 整个获取图片的过程都是在子线程中执行,获取到图片后回到主线程将图片显示出来

设计个简单的图片内存缓存器

  • 类似上面SDWebImage实现原理即可
  • 一定要有移除策略:释放数据模型对象

控制器的生命周期

  • 就是的view的生命周期,下面已经按方法执行顺序进行了排序
// 自定义控制器view,这个方法只有实现了才会执行

- (void)loadView

{

 self.view = [[UIView alloc] init];

 self.view.backgroundColor = [UIColor orangeColor];

}

// view是懒加载,只要view加载完毕就调用这个方法

- (void)viewDidLoad

{

 [super viewDidLoad];

 NSLog(@"%s",__func__);

}

// view即将显示

- (void)viewWillAppear:(BOOL)animated

{

 [super viewWillAppear:animated];

 NSLog(@"%s",__func__);

}

// view即将开始布局子控件

- (void)viewWillLayoutSubviews

{

 [super viewWillLayoutSubviews];

 NSLog(@"%s",__func__);

}

// view已经完成子控件的布局

- (void)viewDidLayoutSubviews

{

 [super viewDidLayoutSubviews];

 NSLog(@"%s",__func__);

}

// view已经出现

- (void)viewDidAppear:(BOOL)animated

{

 [super viewDidAppear:animated];

 NSLog(@"%s",__func__);

}

// view即将消失

- (void)viewWillDisappear:(BOOL)animated

{

 [super viewWillDisappear:animated];

 NSLog(@"%s",__func__);

}

// view已经消失- (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; NSLog(@"%s",__func__); } // 收到内存警告- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; NSLog(@"%s",__func__); } // 方法已过期,即将销毁view- (void)viewWillUnload { } // 方法已过期,已经销毁view- (void)viewDidUnload {}

你是怎么封装一个view的

  • 可以通过纯代码或者xib的方式来封装子控件
  • 建立一个跟view相关的模型,然后将模型数据传给view,通过模型上的数据给view的子控件赋值
/**

* 纯代码初始化控件时一定会走这个方法

 */

- (instancetype)initWithFrame:(CGRect)frame

{

 if(self = [super initWithFrame:frame])

 {

 [self setup];

 }

  return  self;

}
  • 通过xib初始化控件时一定会走这个方法

- (id)initWithCoder:(NSCoder *)aDecoder

{

 if(self = [super initWithCoder:aDecoder])

 {

 [self setup];

 }

  return  self;

}

- (void)setup

{

  // 初始化代码

}

如何进行iOS6、7的适配

  • 通过判断版本来控制,来执行响应的代码
  • 功能适配:保证同一个功能在6、7上都能用
  • UI适配:保证各自的显示风格

// iOS版本为7.0以上(包含7.0)

define iOS7 ([[UIDevice currentDevice].systemVersion doubleValue]>=7.0)

如何渲染UILabel的文字?

  • 通过NSAttributedString/NSMutableAttributedString(富文本)

UIScrollView的contentSize能否在viewDidLoad中设置?

  • 因为UIScrollView的内容尺寸是根据其内部的内容来决定的,所以是可以在viewDidLoad中设置的

  • 补充:(这仅仅是一种特殊情况)

  • 前提,控制器B是控制器A的一个子控制器,且控制器B的内容只在控制器A的view的部分区域中显示

  • 假设控制器B的view中有一个UIScrollView这样一个子控件

  • 如果此时在控制器B的viewDidLoad中设置UIScrollView的contentSize的话会导致不准确的问题

  • 因为任何控制器的view在viewDidLoad的时候的尺寸都是不准确的,如果有子控件的尺寸依赖父控件的尺寸,在这个方法中设置会导致子控件的frame不准确,所以这时应该在下面的方法中设置子控件的尺寸

-(void)viewDidLayoutSubviews;

触摸事件的传递

  • 触摸事件的传递是从父控件传递到子控件

  • 如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸事件

  • 不能接受触摸事件的四种情况

  • 不接收用户交互,即:userInteractionEnabled = NO

  • 隐藏,即:hidden = YES

  • 透明,即:alpha <= 0.01

  • 未启用,即:enabled = NO

  • 提示:UIImageView的userInteractionEnabled默认就是NO,因此UIImageView以及它的子控件默认是不能接收触摸事件的

* 如何找到最合适处理事件的控件:

  • 首先,判断自己能否接收触摸事件

  • 可以通过重写hitTest:withEvent:方法验证

  • 其次,判断触摸点是否在自己身上

  • 对应方法pointInside:withEvent:

  • 从后往前(先遍历最后添加的子控件)遍历子控件,重复前面的两个步骤

  • 如果没有符合条件的子控件,那么就自己处理

事件响应者链

  • 如果当前view是控制器的view,那么就传递给控制器

  • 如果控制器不存在,则将其传递给它的父控件

  • 在视图层次结构的最顶层视图也不能处理接收到的事件或消息,则将事件或消息传递给UIWindow对象进行处理

  • 如果UIWindow对象也不处理,则将事件或消息传递给UIApplication对象

  • 如果UIApplication也不能处理该事件或消息,则将其丢弃

  • 补充:如何判断上一个响应者

  • 如果当前这个view是控制器的view,那么控制器就是上一个响应者

◦ 如果当前这个view不是控制器的view,那么父控件就是上一个响应者

Application.png

如何实现类似QQ的三角形头像

  • Quartz2D
  • 使用coreGraphics裁剪出一个三角形

核心动画里包含什么?

  • 基本动画
  • 回头自己总结吧

如何使用核心动画?

  • 创建
  • 设置相关属性
  • 添加到CALayer上,会自动执行动画

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/56444.html

相关文章

高端网站Html 5前端性能优化指南。

高端网站Html 5前端性能优化指南。

高端网站Html 5前端性能同样需要优化,主要有PC优化手段在Mobile侧同样适用、在Mobile侧我们提出三秒种渲染完成首屏指标、基于第二点,首屏加载3秒完成或使用Loading等优化方法,下面和小编一起看看吧。 概述 PC优化手段在Mobile侧同样适用 在Mob...

快速站内文章优化排名方法。

快速站内文章优化排名方法。

高质量的文章带给网站的不止是良好的排名,同样的也是打好网站基础的条件之一。我们在写文章的时候,对于文章的内容相关性也要非常重视,内容营销的时代已经来临,无论是搜索引擎还是用户,都开始注重内容的质量,什么才是高质量文章,并不是所有的原创文章就是高质量。还需要注意文章的内容是否符合搜索引擎的规则,是否满...

B站上可以引流的方法有哪些如何实现站内站外引流。

B站上可以引流的方法有哪些如何实现站内站外引流。

大纲如下: 1、B站是什么?有什么价值? 2、B站上可以引流的方法有哪些? 3、如何利用B站视频进行站内站外引流? 4、如何利用B站专栏文章百度关键词排名引流? B站是什么?有什么价值? B站是什么,并不是每个人都知道吧。它类似和知乎、豆瓣等一个小众产品。 百科介绍是:哔...

企业做私域,如何做业务模型梳理和设计?

企业做私域,如何做业务模型梳理和设计?

编辑导语:现在有越来越多的企业开始重视私域,甚至不少已经开始布局私域。但是真正能做好的却很少。 我在给不少企业提供运营咨询服务的时候发现,有相当一部分的企业,一上来就开始尝试布局私域,包括搭建社群、搭建小程序,做用户引流、裂变等等。确实,私域基建的搭建是私域开始阶段的重点,引流...

如何评价B站(Bilibili)2021百大up主名单?

啊吗粽阿特警官布锅锅宝剑嫂拜托了小翔哥翠花不太脆才疏学浅的才浅DarkCarrot朵朵花林多多poi丶大漠叔叔大碗拿铁倒悬的橘子大象放映室大祥哥来了盗月社食遇记导演小策电影最TOPEdmundDZhang二二酸酸凤凰传奇附魔星Fms泛式hanser火柴人AlanBecker...

岳阳SEO代理谈网站SEO优化严重降权该如何处理。

岳阳SEO代理谈网站SEO优化严重降权该如何处理。

岳阳SEO代理谈SEO优化严重降权该如何处理。2019年对于优化来讲,算是非常难的一年,尤其是9月开始,国庆之后,大量的网站出现降权等情况,排名一下子全没了,这到底是什么原因呢?为什么会出现这样的情况呢? 2020搜索引擎的算法和规则确实发生了一些变化。它们对新站点的优化更加谨慎...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片