美文网首页程序员
iOS面试总结 - 初级篇

iOS面试总结 - 初级篇

作者: 逾期的誓言 | 来源:发表于2018-09-25 15:39 被阅读48次

    个人博客地址

    1,为什么说Object-C 是一门动态语言?

    主要设计两个概念: 运行时与多态,即:对象类型,以及调用对象方法是在运行时决定;可以从三个方面描述,如下:

    • 动态类型

      对象类型的确定是在运行期间,

      如:id类型,可以赋不同类型的对象,在运行时决定具体类型;

      如:NSData *test = [[NSString alloc] init],编译时为NSData类型,运行时为NSString类型;

      如:父类指针指向子类对象,编译时为类型为父类,运行时为具体子类(简单工厂模式)

    • 动态绑定

      在运行时决定方法的调用,用于消息发送机制,向某个对象传递消息,就会使用动态绑定机制来决定需要调用的方法;
      objc_msgSend 会根据接收者选择子的类型,在接收者内搜索方法列表,如果找到就响应,本类找不到就沿着继承向上找,最后没有响应会执行消息转发机制;

      如:多态中的子类重写父类方法,在运行时确定确定调用方法;

      如:在.h文件声明方法,在.m不实现方法,让外界调用,编译时不报错,运行时报错;

    • 动态加载

      程序在运行时根据需要在加载可执行的代码和资源;

      如:利用runtime动态添加属性,添加方法,替换方法;

      如:不同机型适配,@2x,@3x资源的加载;

    2,说说Object-C内存管理

    OC内存管理分为MRC(手动引用计数),ARC(自动引用计数),遵循谁创建,谁释放,谁retain谁release原则;

    • MRC

      需要程序员自己管理内存,使用alloc, copy, retain 使引用计数加一,对应的要使用release引用计数减一,或者autorealease 标记释放;

    • ARC

      由系统自动管理内存,在合适的时间释放已经失去作用的内存空间.

    • 引用计数

      引用计数就是管理对象生命周期的的方式,当我们创建一个新对象的时候,它的引用计数为1,当有一个新的指针指向这个对象时,其引用计数加一,当某个指针不指向这个对象的时候,其引用计数减一,当对象的引用计数变为0时,说明对象不再被任何指针指向了,这时候就可以将对象销毁,回收内存;

    3,属性的实质是什么?包括哪几个部分?属性默认的关键字有哪些?@dynamic关键字和@synthesize关键字是
    做什么的?

    • 属性的本质

      属性的本质就是: 成员变量+存取方法 即: ivar+setter+getter

    • 属性关键字

      strongassginweakunsafe_unretaindnonatomicatomic, readwritereadonly,等等,各自作用不一一赘述
      注意:循环引用中常使用weak解决, IBOutlet使用weak,因为父空间在可视化操作时已经强引用了
      assign可用于非OC对象,而weak必须用于OC对象,并且对象销毁时,会自动置为nil

    • @dynamic与@synthesize

      使用@dynamic关键字,需要手动添加getter、setter方法,@synthesize自动生成setter、getter方法

    4,说说代理,Block,通知

    • delegate

      1,一对一的通讯交互,防止循环引用, 用weak,释放自动置为nil.

      2,需要@protocol 定义协议方法,指定代理,代理对象需要实现协议方法.

      3,更注重过程,类似tableView的代理方法,需要设置行数,设置cell 等,通讯较多推荐delegate

    • Block(闭包)

      1,一对一的通讯交互,防止循环引用,用copy, 栈区拷贝到堆区.

      2,写法简洁,注重结果,如尾随闭包,回调结果,适用于通讯单一.

      3,__block作用:将外部变量的传递形式由值传递,变为指针传递,从而可以获取并修改外部变量的值

    • NotificationCenter

      1,一对多的通讯,通讯对象之间不需要建立关系,发送通知,注册通知,接收通知后,注意移除通知;

      2,代码可读性差.

    5,可变集合类 和 不可变集合类的 copy 和 mutablecopy有什么区别

    copy返回的都是不可变对象(调用可变对象方法会crash),mutableCopy返回的是可变对象

    只有对不可变的对象进行copy,是浅拷贝,其他情况都是深拷贝

    • 浅拷贝

      浅拷贝是指针拷贝,不生成新的指针地址

    • 深拷贝

      深拷贝是内容拷贝,开辟新内存,会生成行的指针地址,修改拷贝对象对原对象没有影响

    • copy 与 mutablecopy

      不可变集合类(NSArray) 进行copy 是浅拷贝,指针复制, 进行mutableCopy是深拷贝

      可变集合类(NSMutableArray) 进行copy,mutableCopy都是深拷贝

    6,如何使自己写的对象具有拷贝功能

    • 遵守NSCopying,NSMutableCopying协议

    • 实现协议方法

      - (id)copyWithZone:(NSZone *)zone

      - (id)mutableCopyWithZone:(nullable NSZone *)zone

    7,Category,Extension,继承的作用,区别

    • Category

    不需要创建子类就能为现有类(系统类,自定义类)添加新方法;

    • 作用

      1,可以将类的实现分散到多个不同的文件中.

      2,创建对私有方法的向前引用(类别中的声明方法未实现,编译器不会产生警告)

      3,向对象添加非正式协议

    • 局限

      1,类别中只能添加方法,不能添加属性,(可以通过runtime添加)

      2,方法名冲突,类别中方法名,与原始类方法名相同时,类别具有更高的优先级,先调用类别方法,覆盖原始类方法

    • Extension

    extension是延展,匿名分类,一般用于声明私有属性,成员变量,私有方法.

    • Category的区别

      1,extension可以添加属性,而Categary不可以添加属性(可以通过runtime添加)

      2,extension不能单独存在,必须寄生于类的.m中,即:需要源码,而categary可以单独存在,不需要源码.

      3,extension在编译器决议,它是类的一部分,而categary,是在运行期决议.

    • 继承

    继承是面向对象语言的特性,子类可以继承父类的属性与方法,如BaseController

    • 使用条件

      1,当需要扩展的方法与原方法同名时,并且需要调用父类的同名方法,则需要继承。若此时使用分类,则分类的方法的实现 会覆盖原方法的实现,不会访问到原方法。

      2,当需要扩展属性时。

    8,Object-C的反射机制

    OC的反射机制分为Class反射和SEL反射

    • class反射

      通过类名字符串获取类

      Student *stu = [[NSClassFromString(@"Student") alloc]init]

      将类名,转化成字符串

      NSString *stuString = NSStringFromClass([Student class])

    • SEL反射

      通过方法字符串,实例化方法

      [stu performSelector:NSSelectorFromString(@"setName") withObject:nil]

      将方法变成字符串

      NSStringFromSelector(@selector*(setName:))

    9,常见的系统单利类有哪些?如何实现完整的单利?

    • 系统单利类

      1,应用程序实例 [UIApplication sharedApplication]

      2,消息中心 [NSNotificationCenter defaultCenter]

      3,文件管理 [NSFileManager defaultManager]

      4,应用程序设置 [NSUserDefaults standardUserDefaults]

      5,应用程序cookies池 [NSHTTPCookieStorage sharedHTTPCookieStorage]

    • 完整的单利类

      实现了单例的初始化之后,一定要重写三个方法

      +(id) allocWithZone:(struct _NSZone *)zone

      -(id) copyWithZone:(NSZone *)zone

      -(id) mutablecopyWithZone:(NSZone *)zone

    10,NSTimer一定准确么?怎么解决

    • 主线程

      NSTimer添加在主线程中,模式是NSDefaultRunLoopMode, 主线程处理所有添加在主线程中的事件,例如UI界面的刷新,复杂的运算,等等,过多主线程事件的处理,导致线程阻塞;当滑动ScrollView的时候,Runlop会将Model切换到TrackingRunLoopMode,这时候的NSTimer事件就不会回调,所以不准

      解决:将NSTimer添加到runloop的特定NSRunLoopCommonModes模式中

      [[NSRunLoop currentRunLoop] addTimer:timer1 forMode:NSRunLoopCommonModes];

    • 子线程

      子线程RunLoop默认关闭,需手动开启,否则定时器不准,

      [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
      [[NSRunLoop currentRunLoop] run];
      

      子线程定时器结束的时候,需要干掉,否则会造成资源的浪费

      [_timer invalidate];
      _timer = nil;
      

    相关文章

      网友评论

      本文标题:iOS面试总结 - 初级篇

      本文链接:https://www.haomeiwen.com/subject/ixdloftx.html