01-基础+UI面试题

简单说一下APP的启动过程,从main文件开始说起

程序启动分为两类:1.有storyboard 2.没有storyboard

有storyboard情况下:
1. main函数
2. UIApplicationMain
    创建UIApplication对象
    创建UIApplication的delegate对象
3. 根据Info.plist获得Main.storyboard的文件名,加载Main.storyboard 
4. 创建UIWindow
5. 创建和设置UIWindow的rootViewController
6. 显示窗口

没有storyboard情况下:
1. main函数
2. UIApplicationMain
    创建UIApplication对象
    创建UIApplication的delegate对象
3. delegate对象开始处理(监听)系统事件
4. 调用application:didFinishLaunchingWithOptions:方法并在其中创建UIWindow
5. 创建和设置UIWindow的rootViewController
6. 显示窗口

简述一下UIViewController的生命周期?

  • loadView 正在加载
  • viewDidLoad 加载完成
  • viewWillAppear 界面即将出现
  • viewWillLayoutSubviews 界面将布局子控件
  • viewDidLayoutSubviews 界面已经布局子控件
  • viewDidAppear 界面已经出现
  • viewWillDisappear 界面即将消失
  • viewDidDisappear 界面已经消失
  • dealloc 界面被销毁

loadView的作用?

  • 用于自定义Controller的View
  • 代码示例:
- (void)loadView
{ 
    self.view = [[UIImageView alloc] init];
}

控制器通过Storyboard或者Xib创建时的注意事项?

详细blogLink

  • 控制器通过storyboard加载,则根据storyboard的描述创建view
  • 控制器view通过xib加载,则根据nibName对应的xib创建view
  • 若没有指定nibName,则根据与控制器同名的xib创建view
  • 没有同名的xib,则根据与控制器名前缀相同不带controller的xib创建view
  • 如果都没有,则创建一个空白的xib

xib如何动态处理view布局

  • 不使用自动布局时, xib根据控件在xib上的位置来布局
  • 使用自动布局时, xib通过约束条件来布局views
  • 使用自动布局时, 若只给控件添加了位置约束, 控件的宽高会根据内容动态调整

frame和bounds的区别 ?

  • 相同点
    • 两者都可以用来改变View的大小
  • 不同点
    • frame还能改变View的位置, 但是bounds不能改变View的位置
    • 改变View的frame, 其子视图的坐标不变; 改变bounds, 子视图的坐标会变!
  • Demo解释:
    UIView *v1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
    v1.backgroundColor = [UIColor redColor];
    [self.view addSubview:v1];
    
    UIView *v2 = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
    v2.backgroundColor = [UIColor greenColor];
    [v1 addSubview:v2];

以上代码得出的效果图:

01-基础+UI面试题_第1张图片
改变v1的bounds前

添加代码v1.bounds = CGRectMake(0, 0, 200, 200)后的效果图:

01-基础+UI面试题_第2张图片
改变v1的bounds后
  • 解释
    • 通过以上两张效果图可以看出, v1看似改变了位置, 但如果留意两者的center点, 两者
    • 改变v1的bounds时, v1是在Center点保持不变的前提下改变尺寸的, 因而子视图的位置也会跟着一起改变
  • 为了避免对子视图的影响, 一般不建议修改bounds

drawRect 和 layoutSubViews 有什么区别 ?

  • drawRect能够获取上下文, 主要用于绘图
  • layoutSubviews 用于布局子视图的

iOS有几种动画,各自是什么?

动画详解Link

  • 转场动画 (CATransition)
  • 帧动画 (CAKeyFrameAnimation)
  • 隐式动画 (CABasicAnimation)

如何实现一个图形沿一个固定路径移动 ?

  • 步骤
    • 创建CALayer对象
    • 创建动画
    • 创建路径
    • 动画捆绑路径
    • CALayer捆绑动画
    • 释放路径
  • 代码示例:
 CALayer *redLayer = [CALayer layer];
    redLayer.backgroundColor = [UIColor redColor].CGColor;
    redLayer.frame = CGRectMake(150, 0, 100, 100);
    redLayer.cornerRadius = 50;
    [self.view.layer addSublayer:redLayer];
    
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    animation.duration = 3.f;
    animation.repeatCount = MAXFLOAT;
    
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddEllipseInRect(path, NULL, CGRectMake(0, 0, 300, 600));
    
    animation.path = path;
    [redLayer addAnimation:animation forKey:nil];
    
    CGPathRelease(path);

ScrollView的contentSize能在viewDidLoad里设置么,为什么?

  • 一般情况下是可以的
  • 在使用AutoLayout的时候设置了也没用, 因为:
    • 系统会在viewDidLayoutSubviews中根据subviews的约束条件重新计算scrollview的contentSize, 并把之前的值覆盖掉

页面间传值的方式有哪些

(详细博客)

  • 正向传值
    • 定义属性来传值
  • 反向传值
    • 通过delegate使用代理方法
    • 使用block
    • 通过通知中心
      • 使用通知中心时, 谁要监听值的变化, 谁就注册通知
      • 特别要注意,通知的接受者必须存在
  • 正向反向都可以使用
    • 使用单例(通过单例的属性传值)

如何自动计算Cell的高度

  • iOS8以下需要手动计算高度,然后缓存高度。
  • iOS8以上可以用self sizing cells, 完全不需要任何计算
    • 核心代码
tableView.estimatedRowHeight = xx
tableView.rowHeight = UITableViewAutomaticDimension

CALayer和UIView的区别

  • 从属的库不同
    • UIView是UIKit的(只能iOS使用)
    • CALayer是QuartzCore的(iOS和mac os通用)。
  • 继承关系不同(==>表示继承于)
    • CALayer==>NSObject
    • UIView==>UIResponder==>NSObject,
  • 用户触摸功能不同
    • 因为UIView继承于UIResponder, 所以可以处理用户触摸功能
    • CALayer不能处理用户处理功能
  • 其他
    • UIView来自CALayer,是对CALayer的高层实现和封装
    • CABasicAnimation,CAAnimation,CAKeyframeAnimation等动画类都要加到CALayer上

UITableview的复用机制的原理

  • 通过dequeueReusableCellWithIdentifier方法,先从复用队列里面通过Identifier查找是否有Cell可以复用
  • 如果有就复用,否则就创建新的Cell。

UIButton与UITableView的层级结构

  • UIButton ==> UIControl ==> UIView
  • UITableView => UIScrollView ==> UIView
  • 拓展
    • 展示性的控件一般都直接继承于UIView, 例如UILabel, UIImageView
    • 响应性的控件一般先继承于UIControl, 再继承于UIView

同一个Lable的Text如何显示不同字体和颜色

  • 使用富文本 (NSAttributedString()
  • 代码示例:
   NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"hello"];  
// 第一个文字显示蓝色  
    [str addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(0, 1)];
//最后两个文字显示红色  
    [str addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(2, 2)];
      
// 在不同位置设置不同字体  
    [str addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:30] range:NSMakeRange(1, 3)];  
    self.label.attributedText = str;  

说下webview与js的交互

  • UIWebView提供有直接调用JS方法,但是没有提供JS调用OC的方法
  • 可以用第三方实现JS调用OC,比如JavaScriptBridge,EasyJS,Coradova

如果需要一个有序的NSDictionary应该怎么处理?

  • 取出字典所有的key, 对key进行排序
  • 按照key值顺序输出所有的Value值

断言的使用

  • NSAssert(url != nil, @"URL不能为空");
    • 当url == nil时, 程序会报错, 报的错为"URL不能为空"

深浅拷贝的区别和使用场景

  • 区别
    • 深拷贝是对象拷贝 -> (会创建新对象)
    • 浅拷贝是指针拷贝 -> (拷贝的是对象的地址)
  • 代码示例:
    [NSString copy];           (浅拷贝)
    [NSMutableString copy];    (深拷贝)
    
    [NSString mutableCopy];    (深拷贝)
    [NSMutableString mutableCopy]; (深拷贝)

weak的使用情景?

  • 在 ARC 中,在有可能出现循环引用的时候,通过使用weak修饰来解决
  • 自身已经对它进行一次强引用,没有必要再强引用时也会使用 weak
    • 例如自定义 IBOutlet 控件属性

assign和weak的区别?

详细博客第12题

  • 使用领域不同
    • assign既可以用于MRC,也可以用于ARC
    • weak只用于ARC
  • 在ARC中修饰的变量类型不同
    • aasign用于修饰简单的数据类型, 如Int, BOOL等
    • weak用于修饰对象
  • 在ARC中修饰后的作用不同
    • assign修饰的变量在释放时不会置为nil, 修饰的对象会变为僵尸对象, 再次引用会引起崩溃
    • weak修饰的对象在释放时会置为nil, 再次引用不会引起崩溃

说说 __block__weak的区别

  • 定义

    • __block告诉block拦截变量时, 拦截其地址
    • __weak 告诉block, 不要对引用的对象进行强引用(即不要对其进行retain)
  • 作用

    • 在MRC中使用__block可以解决循环引用问题, 因为截获的是对象的地址, 不会对其进行retain
    • 在MRC和ARC中使用__block, 由于引用是的地址, 因此可以在block内部修改外部的值
    • 在ARC中使用__weak可以解决循环引用问题

instancetype与id的区别

  • 在ARC环境下:
    • 使用Instancetype时, 在编译的时候就会检查实例的类型
    • 使用id的话, 编译时不检查类型, 运行时才检查类型
  • 在MRC环境下:
    • instancetype和id一样,不做具体类型检查
  • id可以创建对象, 可以作为方法的参数类型, 但instancetype不可以
  • instancetype只适用于作为方法返回值类型

#import和#include的区别, #import<>和 #import ""的区别, #import和@class的区别?

  • #import#include的区别
    • #include是C/C++中使用的,#import是OC中使用的
    • #include不能避免头文件被重复包含的问题, #import可以解决这个问题
  • #import<>#import ""的区别
    • #import<> 用于导入系统头文件,#import ""用于导入自己的头文件
  • #import@class的区别
    • #import会包含这个类的所有信息,包括变量和方法,而@class只是告诉编译器,其后面声明的名称是类的名称,不包括变量和方法
    • .h文件中一般使用@class来声明类。 而在.m文件中,因为会用到这个类内部的变量和方法,所以需要使用#import
    • @class的编译效率比 #import
    • 如果有循环依赖关系,如:A–>B, B–>A, 使用#import来相互包含,会出现编译错误,如果使用@class在两个类的头文件中相互声明,则不会有编译错误出现。

Objective-C中类别, 类扩展和继承的区别?

  • 作用不同
    • 类别可以用来添加新的方法, 不能添加新的属性
    • 类扩展可以添加新的属性(私有), 不能添加新方法
    • 继承可以添加新的属性, 可以重写父类的方法, 还可以添加新的方法
  • 对类的影响不同
    • 类别可以根据功能的不同, 把不同的方法分开放在几个不同的类别, 以可以减少单个文件的体积。
    • 类扩展是类的一部分,在编译时随类的生成而生成。
    • 继承相当于为原来的父类创建了一个新的子类

如何进行代码做自动布局

  • 使用苹果自带的类NSLayoutConstranit
  • 使用可视化格式语言 (VFL)
  • 使用第三方框架 (Masonry)

简述assign、retain、copy、weak和strong分别在什么情况下使用?

  • strong和weak在ARC中用过来修饰对象属性, 表示强弱引用
  • retain, assign在MRC中用来修饰对象属性, 表示是否进行retain(引用计数+1)
  • assign在ARC中还可以用来修饰普通类型变量
  • copy可以用来拷贝对象
  • copy用来修饰NSString变量Str, 通过浅拷贝使其他类可修改Str的值
  • copy在MRC中通过修饰Block属性, 可以使block被保存到堆上

delegate用什么属性修饰,ARC下与MRC下有何不同,为什么?

详细博客第8题

  • ARC中用weak, 可防止循环引用, 对象销毁后还可以将其置nil
  • MRC中用assign, 可防止循环引用

NSString,NSArray,NSMutableArray分别用什么属性修饰,原因是什么?

详细博客

  • NSString和NSArray用 copy, 浅拷贝, 允许外部引用时同步修改变量的值
  • NSMutableArray 用 strong进行强引用, 若使用copy, 在深拷贝的作用下反而会破坏变量的封装性

谈一下关键字const, static和extern的作用?

详细blogLink

  • const用于声明常量, 修饰后的变量都是只读的
int const a = 10;
a = 20
//因为变量a被const修饰,就成为了只读,不能被修改赋值了,
所以上面a = 20这行代码是错误的
  • static用于声明静态变量(在内存中只创建一次)
  • 注意, static声明的静态变量的作用域只存在于当前作用域 (方法/文件)
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   static int i = 0; 
   i ++; 
   NSLog(@"i=%d",i);}
//打印结果 (因为变量i在内存中只存在一份!)
   i = 1, i = 2, i = 3 ....
}
  • extern用于声明外部全局变量或常量
  • 在.h中声明全局常量
//声明一些全局常量
extern NSString * const name;
extern NSInteger const count;
  • 在.m中初始化常量, 这样只要导入头文件,就可以全局的使用定义的变量或常量
#import 
//实现
NSString * const name = @"王五";
NSInteger const count = 3;

@property本质是什么

详细blog链接

  • @property = ivar + getter + setter
  • 使用@property, 系统默认为完成以下操作:
    • 创建属性的“偏移量” (offset),表示该变量距离存放对象的内存区域的起始地址有多远。
    • 创建method_list (方法列表), 保存setter方法和getter方法
    • 创建ivar_list (成员变量列表)
    • 创建prop_list (属性列表)

OC语言三大特性的定义和特点以及各自的适用场景

封装

  • 特点
    • 可以模块化代码
  • 使用场景
    • 需要做性能优化时
    • 需要减少代码量时

继承

  • 特点
    • 子类拥有父类的(非私有)属性+方法
  • 使用场景
    • 装饰者模式

多态

  • 特点
    • 父类指向之类, 动态创建对象
  • 使用场景
    • 工厂模式

在OC里面,给指定类动态添加行为的方法有哪些

  • 继承
  • 协议
  • 类别

你可能感兴趣的:(01-基础+UI面试题)