iOS面试题-UI篇

36 篇文章 1 订阅
32 篇文章 0 订阅

http://www.360doc.com/content/20/0630/21/31460730_921535347.shtml

这里有关于面试方面汇总:关于iOS面试题汇总(栏目持续更新)https://www.jianshu.com/p/8af16aa3e48d

size Classes具体使用

对屏幕进行分类

uIView和CALayer是什么关系?

UIView显示在屏幕上归功于CALayer,通过调用drawRect方法来渲染自身的内容,调节CALayer属性可以调整UIView的外观,

UIView继承自UIResponder,比起CALayer可以响应用户事件,Xcode6之后可以方便的通过视图调试功能查看图层之间的关系

UIView是iOS系统中界面元素的基础,所有的界面元素都继承自它。它内部是由Core
Animation来实现的,它真正的绘图部分,是由一个叫CALayer(Core Animation Layer)的类来管理。UIView本身,更像是一个CALayer的管理器,访问它的跟绘图和坐标有关的属性,如frame,bounds等,实际上内部都是访问它所在CALayer的相关属性

UIView有个layer属性,可以返回它的主CALayer实例,UIView有一个layerClass方法,返回主layer所使用的类,UIView的子类,可以通过重载这个方法,来让UIView使用不同的
CALayer来显示,如:

-(class) 1ayerC1ass {
//使某个UIView的子类使用GL来进行绘制
return ([CAEAGLLayer c1ass]);
}

UIView的CALayer类似UIView的子View树形结构,也可以向它的layer上添加子layer,来完成某些特殊的显示。例如下面的代码会在目标View上敷上一层黑色的透明薄膜。
grayCover = [[CALayer a11oc]init] ;
grayCover. backgroudCo1or = [[UIco1or
b1ackColor]co1orWithA1phaComponent:0.2].ccCo1or;[se1f.1ayer addSubLayer :grayCover];

补充部分,这部分有深度了,大致了解一下吧,UIView的layer树形在系统内部被系统维护着三份copy

逻辑树,就是代码里可以操纵的,例如更改layer的属性等等就在这一份

动画树,这是一个中间层,系统正是在这一层上更改属性,进行各种渲染操作

显示树,这棵树的内容是当前正被显示在屏幕上的内容

这三棵树的逻辑结构都是—样的,区别只有各自的属性

loadView的作用?

loadView用来自定义view,只要实现了这个方法,其他通过xib或storyboard创建的view都不会被加载

看懂控制器view创建的这个图就行

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

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

IB中User Defined Runtime Attributes如何使用?

User Defined Runtime Attributes是一个不被看重但功能非常强大的的特性,它能够通过KVC的方式配置—些你在interface builder中不能配置的属性

当你希望在lB中作尽可能多得事情,这个特性能够帮助你编写更加轻量级的viewcontroller

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

Application:存放程序源文件,上架前经过数字签名,上架后不可修改
Documents:常用目录,iCloud备份目录,存放数据
Library
Caches:存放体积大又不需要备份的数据
Preference:设置目录,iCloud会备份设置信息
tmp:存放临时文件,不会被备份,而且这个文件下的数据有可能随时被清除的可能

pushViewController和presentViewController有什么区别

两者都是在多个试图控制器间跳转的函数

presentViewController提供的是一个模态视图控制器(modal)

pushViewController提供一个栈控制器数组,push/pop

请简述UITableView的复用机制

每次创建cell的时候通过dequeueReusableCellWithIdentifier:方法创建cell,它先到缓存池中找指定标识的cell,如果没有就直接返回nil

如果没有找到指定标识的cell,那么会通过initWithstyle:reuseldentifier:创建一个cell

当cell离开界面就会被放到缓存池中,以供下次复用

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

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

self.view.1ayer. cornerRadius = 5;
self.view.1ayer. masksToBounds = YES;
正确的解决方案:使用绘图技术
-(UIImage *)circ1eImage
{
l/ NO代表透明
UIGraphicsBeginImageContextWithOptions(self.size,NO,0.0);
//获得上下文
cGContextRef ctx = UIGraphicsGetCurrentContext() ;
// 添加一个圆
CGRect rect = CGRectMake(0,0, self.size.width,self.size.height);cGContextAddE11ipseInRect(ctx,rect) ;
/裁剪
cGContextClip(ctx);
1/将图片画上去
[self drawInRect:rect];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
l/关闭上下文
UIGraphicsEndImageContext() ;
return image;
}

还有一种方案:使用了贝塞尔曲线’切割’个这个图片,给UllmageView添加了的圆角,其实也是通过绘图技术来实现的

UIImageView *imageView = [[UIImageView a11oc] initWithFrame :CGRectMake(0,0,100,100)];
imageview.center = CGPointMake(200,300);

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

UIGraphicsBeginImageContextWithOptions(imageView.bounds.size,N0,1.0);[[UIBezierPath bezierPathWithRoundedRect :imageview. bounds
cornerRadius:50] addc1ip];
[anotherImage drawInRect :imageview.bounds] ;
imageView.image = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();
[self.view addSubview:imageView];

这里有一个iOS交流圈:891 488 181 不管你是大牛还是小白都欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长!

使用drawRect有什么影响?

drawRect方法依赖Core Graphics框架来进行自定义的绘制

缺点:它处理touch事件时每次按钮被点击后,都会用setNeddsDisplay进行强制重绘;而且不止一次,每次单点事件触发两次执行。这样的话从性能的角度来说,对CPU和内存来说都是欠佳的。特别是如果在我们的界面上有多个这样的UIButton实例,那就会很糟糕了

这个方法的调用机制也是非常特别.当你调用setNeedsDisplay方法时, UIKit将会把当前图层标记为dirty,但还是会显示原来的内容,直到下一次的视图渲染周期,才会将标记为dirty 的图层重新建立Core Graphics上下文,然后将内存中的数据恢复出来,再使用CGContextRef进行绘制

描述下SDWeblmage里面给UllmageView加载图片的逻辑

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

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

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

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

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

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

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

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

类似上面SDWeblmage实现原理即可

—定要有移除策略:释放数据模型对象

控制器的生命周期

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

  • (void)1oadView
    {
    self.view = [[UIView al1oc] init];
    self.view.backgroundColor = [UICo1or orangeCo1or];}
    l / view是懒加载,只要view加载完毕就调用这个方法
    -(void)viewDidLoad
    {
    [super viewDidLoad] ;
    NSLog(@’%s’,func);
    }
    i / view即将显示
    -(void)viewWi11Appear : (BOOL)animated
    {
    [super viewWi11Appear : animated] ;
    NSLog(@’%s’,func_);
    }
    l / view即将开始布局子控件
    -(void)viewWi11LayoutSubviews
    {
    [super viewWi11LayoutSubviews];
    NSLog(@’%s’,_func);
    }

i l view已经完成子控件的布局
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews] ;
NSLog(@’%s’,func);
}
i l view已经出现
-(void)viewDidAppear : (BOOL)animated
{
[super viewDidAppear : animated] ;
NSLog(@’%s’,func);
}
i / view即将消失
-(void)viewFi11Disappear : (BOOL)animated
{
[super viewWi11Disappear : animated] ;
NSLog(@’%s’,_func);
}
l / view已经消失
-(void)viewDidDisappear : (BOOL)animated
{
[super viewDidDisappear : animated] ;
NSLog(@’%s’,func);
}
/收到内存警告
-(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
NSLog(@’%s’,func
);
}
//方法已过期,即将销毁view
-(void)view亚i11Un1oad
{

}
1/方法已过期,已经销毁view
-(void)viewDidUn1oad
{

}

你是怎么封装一个view的

可以通过纯代码或者xib的方式来封装子控件

建立一个跟view相关的模型,然后将模型数据传给view,通过模型上的数据给view的子控件赋值

/**
纯代码初始化控件时一定会走这个方法/
-(instancetype)initWithFrame : (CGRect)frame
{
if(self = [super initwithFrame :frame])
{
[self setup];
}
return se1f ;
}
/**
*通过xib初始化控件时一定会走这个方法
*/
-(id)initWithCoder : (NSCoder *) aDecoder
{
if(self = [super initWithCoder: aDecoder])
{
[self setup] ;
}

return se1f;
}
-(void)setup
{
// 初始化代码
}

如何进行ioS6、7的适配

通过判断版本来控制,来执行响应的代码

功能适配:保证同—个功能在6、7上都能用

UI适配:保证各自的显示风格

// ios版本为7.0以上(包含7.0)
#define i0S7 ([[UIDevice currentDevice].systemVersion doubleValue]>=7.0)

如何渲染UILabel的文宁?

通过NSAttributedString/NSMutableAttributedString(富文本)

UlScrollView的contentSize能否在viewDidLoad中设置?

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

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

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

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

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

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

-(void)viewDidLayoutSubviews;

触摸事件的传递

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

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

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

下接收用户交互,即: userlnteractionEnabled = NO

隐藏,即: hidden = YES

透明,即: alpha <= 0.01

未启用,即: enabled = NO

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

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

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

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

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

对应方法pointInside:withEvent:

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

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

事件响应者链

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

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

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

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

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

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

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

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

-end -

有想要的面试资料或者其他资料也可以找我,欢迎咨询!需要的可自行下载,还有其他整理好的面试题资料可咨询管理,还有其他面试真题与资料。




文章到这里就结束了,你也可以私信我及时获取最新资料以及面试相关资料。如果你有什么意见和建议欢迎给我留言。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值