YOU'VE MADE A BRAVE DECISION, WELCOME.

每一个不曾起舞的日子都是对生命的辜负。

iOS面试题一(转)

[转][http://www.jianshu.com/p/9179e5d780c8]

  • Category是什么?重写一个类的方式用继承好还是分类好?

    • Category是类别,一般情况用分类好,用category重写类的方法,仅对本Category有效,不会影响到其他类与原有类的关系
  • ‘#import和#include有什么区别,@class呢?#import<>和#import””有什么区别

    • ’#import是OC导入头文件的关键字,‘#include是C/C++导入头文件的关键字,使用#import头文件会自动只导入一次,相当于’#include和’#pragma once;
    • @class是告诉编译器某个类的声明,当执行时,才去查看类的实现文件,可以解决头文件的相互包含;
    • ‘’#improt<>用来包含系统的头文件,‘#import””用来包含用户头文件
  • 属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况下用?

    • readwrite 是可读可写特性;需要生成getter方法和setter方法时
    • readonly 是只读特性,只会生成getter方法,不会生成setter方法;不希望属性在类外改变
    • assign 是复制特性,setter方法将传入参数赋值给实例变量;仅设置变量时
    • retain 表示持有特性,setter方法将传入参数先保留,再赋值,传入参数的retaincount+1;
    • copy 表示赋值特性,setter方法将传入对象复制一份;需要完全一份新的变量。
    • nonatomic 非原子操作,并决定编译器生成的setter getter是否是原子操作,atomic表示多线程安全,一般使用nonatomic;
  • OC的理解与特性

    • 封装、继承、多态
    • 动态类型(Dynamic typing):即运行时再决定对象的类型,简单来说就是id类型,静态类型是强类型,而动态类型属于弱类型
    • 动态绑定(Dynamic binding):基于动态类型,在某个实例对象被确定后,其类型便被确定了
    • 和动态加载(Dynamic loading):根据需求加载所需要的资源,最基本就是不同机型的适配
  • 简述内存管理基本原则

    • OC内存管理遵循“谁创建,谁释放,谁引用,谁管理”的机制,当创建或引用一个对象的时候,需要向她发送alloc、copy、retain消息,当释放该对象时需要发送release消息,当对象引用计数为0时,系统将释放该对象,这是OC的手动管理机制(MRC)。

    • 自动引用计数(ARC),管理机制与手动机制一样,只是不再需要调用retain、release、autorelease;它引用strong和weak关键字,strong修饰的指针变量指向对象时,当指针指向新值或者指针不复存在,相关联的对象就会自动释放,而weak修饰的指针变量指向对象,当对象的拥有者指向新值或者不存在时weak修饰的指针会自动置为nil。

    • 如果使用alloc、copy(mutableCopy)或者retian一个对象时,你就有义务,向它发送一条release或者autorelease消息。其他方法创建的对象,不需要由你来管理内存

    • 向一个对象发送一条autorelease消息,这个对象并不会立即销毁, 而是将这个对象放入了自动释放池,待池子释放时,它会向池中每一个对象发送 一条release消息,以此来释放对象.

    • 向一个对象发送release消息,并不意味着这个对象被销毁了,而是当这个对象的引用计数为0时,系统才会调用dealloc方法,释放该对象和对象本身它所拥有的实例。

    • 如果一个对象有一个_strong类型的指针指向着,找个对象就不会被释放

    • 如果一个指针指向超出了它的作用域,就会被指向nil。如果一个指针被指向nil,那么它原来指向的对象就被释放了;不管全局变量还是局部变量用_strong描述就行

    • 局部变量:出了作用域,指针会被置为nil。

      方法内部创建对象,外部使用需要添加_autorelease;

      连线的时候,用_weak描述。

      代理使用unsafe_unretained就相当于assign;

      block中为了避免循环引用问题,使用_weak描述;

  • 如何理解MVC设计模式

    • M表示Model,V表示视图View,C表示控制器Controller:
    • Model负责存储、定义、操作数据;
    • Controller是Model和VIew的协调者,Controller把Model的数据拿过来给VIew用。Controller可以直接和View、Model通信,而View不能直接和Controller通信。它们之间需要利用代理协议的方式,当有数据更新时,Model也要与Controller通信,这个时候就要用Notification和KVO。
  • 如何理解MVVM设计模式

    • ViewModel层是一个放置用户输入验证逻辑、视图显示逻辑、发起网络请求和其他各样代码的地方,其实就是把ViewController层的业务逻辑和页面逻辑剥离出来放到ViewModel层。
    • View层就是ViewController层,任务是从ViewModel层获取数据,然后显示
  • Objective-C 中是否支持垃圾回收机制

    • OC支持垃圾回收机制GC,但是apple移动终端不支持GC,Mac桌面系统开发中支持
    • 移动终端开发支持ARC,它不需要向对象发送release或者autorelease,也不可以调用dealloc,编译器会在自动位置生成release(autorelease)
  • 协议的基本概念和协议中方法默认为什么类型

    • OC中协议是一个方法列表,可以被任何类实现,
  • 简述类目category优点和缺点

    • 优点
      • 不需要增加子类而增加现有类的方法,且类目中的方法与原始类方法基本没有区别
      • 通过类目可以将一个大的类进行划分,从而便于代码的维护
    • 缺点
      • 无法添加实例变量,如要添加,只能通过定义子类的方式
      • 类目中的方法与原始类以及父类相比具有更高优先级,如果覆盖父类,可能导致super消息断裂,因此最好不要覆盖
  • 类别的作用

    • 原始类添加方法,不能扩展属性,优先级高
    • 声明私有方法,某一个方法只实现,不声明,相当于私有方法
    • 类别不声明变量,类别不可以添加属性,property描述setter方法就不会报错
  • 循环引用的产生原因,以及解决方法

    • 对象A、B相互引用了对方作为自己的成员变量,只有自己销毁的时候才能将成员变量引用计数减1.
    • 多个对象间依然会存在循环引用问题,形成一个环。
    • 事先知道存在循环引用的地方,在合理的位置主动断开一个引用,是对象回收
    • 使用弱引用方法
  • 键路径(keyPath)

    • 一个实体,同个属性具有相同的数据类型
    • 用于查找,间接访问对象属性的机制。键路径是分隔符的键组成的字符串,用于指定一个连接在一起的对象性质序列,第一个键的性质由先前的性质决定,接下来每个键的值也是相对于前面的性质
    • 键路径可以独立于模型实现的方式指定相关对象的性质。通过键路径,可以指定对象图中的一个任意深度的路径,使其指向相关对象的特定属性
  • 键值编码KVC

    • 键值编码是一种间接访问对象的属性使用字符串来标识属性,而不是通过调用存取方法,直接或通过实例变量访问的机制,非对象类型的变量将被自动封装或者解封成对象
    • 一旦使用 KVC 你的编译器无法检查出错误,即不会对设置的键、键路径进行错误检查,且执行效率要低于合成存取器方法和自定的 setter 和 getter 方法。因为使用 KVC 键值编码,它必须先解析字符串,然后在设置或者访问对象的实例变量
  • 键值观察(KVO)

    • 键值观察机制是一种能使得对象获取到其他对象属性变化的通知 ,极大的简化了代码
    • 实现 KVO 键值观察模式,被观察的对象必须使用 KVC 键值编码来修 改它的实例变量,这样才能被观察者观察到。因此,KVC是KVO的基础
  • 在 Objective-C 中如何实现 KVO

    • 注册观察者- (void)addObserver:
    • 接受变更通知- (void)observeValueForKeyPath:
    • 移除对象的观察者身份- (void)removeObserver:
    • KVO中,谁要监听谁注册,然后对响应进行处理,使得观察者与被观察者完全解耦。只检测类中的属性,通过NSString查找
  • 代理的作用

    • 委托,设计模式,对象与对象之间的通信交互,解除了对象之间的耦合性
    • 改变或传递控制链。允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针
    • 代理可以理解为java中的回调监听机制
    • assign:防止循环引用,以致对象无法得到正确的释放
  • NSNotification、Block、Delegate和KVO的区别

    • 代理是一种回调机制,一对一;通知是一对多
    • delegate比NSNotification效率高
    • block也是一对一通信
    • delegate需要定义协议方法,代理对象实现协议方法,需建立代理关系
    • block简洁,如通信事件多使用delegate好
  • Objective-C中可修改和不可以修改类型

    • 可修改不可修改的集合类,就是可动态添加修改和不可动态添加修改
    • 比如NSArray和NSMutableArray,前者在初始化后的内存控件就是固定不可变的,后者可以添加等,可以动态申请新的内存空间
  • 当我们释放我们的对象时,为什么需要调用[super dealloc]方法,它的位置又是如何的呢?

    • 因为子类的某些实例是继承自父类的,因此需要调用[super dealloc]方法, 来释放父类拥有的实例,其实也就是子类本身的。一般来说我们优先释放子类拥 有的实例,最后释放父类所拥有的实例。
  • 对谓词的认识

    • Cocoa提供了一个NSPredicate类,该类主要用于指定过滤器的条件,每一个对象通过谓词进行筛选,判断条件是否匹配。
  • static、self、super关键字的作用

    • 函数体内static的作用范围为该函数体,不同于auto,该变量的内存只被分配一次,在下次调用是仍维持上次的值
    • 在模块内的static全局变量可以被模块内所有函数访问。
    • 模块内static函数只可被这一模块内的其他函数调用,这个函数使用范围被限制在声明
    • 在类中static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝
    • self:当前消息的接受者
    • super:向父类发送消息者
  • isMemberOfClass 和 isKindOfClass 联系与区别

    • 两者都能检测一个对象是否是某个类的成员
    • isKindOfClass 不仅用来确定一个对象是否是一个类的成员,也可以用来确定一个对象是否派生自该类的类的成员 ,而isMemberOfClass 只能做到第一点
  • iOS 开发中数据持久性有哪几种?

    • 数据存储核心就是写文件
    • 属性列表:NSString、NSArray、NSDictionary、NSData可以riteToFile;存储依旧是plist文件。
    • plist:array、dictionary、string、bool、data、date、number
    • 对象序列化:对象序列化通过序列化的形式,键值关系存储到本地,转化成二进制流。通过runtime实现自动化归档/解档(NSCoding)
      • 编码(对象序列化):把不能直接存储到plist文件中得到数据,转化为二进制数据,NSData,可以存储到本地
      • 解码:(对象反序列化):二进制数据转化为本来的类型
    • SQLite数据库:大量有规律的数据使用数据库
    • CoreData:通过管理对象进行操作。
  • CoreData

    • 面向对象的API,数据存储的基础
    • 持久化数据映射为内存对象,CoreData可以将Objective-C对象转换成数据,保存到SQL中,然后将保存后的数据还原成OC对象
    • 提供NSFetchResultsController类用于管理表视图的数据
    • 管理undo/redo操纵
    • 检查托管对象的属性值是否正确
    • NSManageObject:这个模型包含实体(Entity)、特性(Property)、读取请求(Fetch Request)等
    • NSManageObjectContext:管理对象上下文,持久性存储模型对象,参与数据对象进行各种操作的全过程,并监测数据对象的变化,以提供对undo/redo的支持及更新绑定到数据的UI
    • NSPersistentStoreCoordinator:数据文件管理器,处理底层的对数据文件的读取和写入
    • NSManagedObjectModel:被管理的数据模型、数据结构
    • NSFetchRequest:数据请求
    • NSEntityDescription:表格实体结构,还需知道.xcdatamodel文件编译后为.momd或者.mom文件。
  • 自动释放池工作原理

    • 自动释放池是NSAutorelease类的一个实例,当向一个对象发送autorelease消息时,该对象会自动入池,待池销毁时,将会向池中所有对象发送一条release消息,释放对象
    • [pool release]、 [pool drain]表示的是池本身不会销毁,而是池子中的临时对象都被发送release,从而将对象销毁
  • 解释self = [super init]方法

    • 容错处理,当父类初始化失败,会返回一个nil,表示初始化失败。由于继承的关系,子类是需要拥有父类的实例和行为,因此,我们必须先初始化父类,然后再初始化子类
  • 堆和栈的区别

    • 栈区由编译器自动分配释放,存放方法的参数值、局部变量的值等,向低地址扩展的数据结构、连续
    • 堆区由程序员分配释放,若程序员不释放,程序结束时由OS回收,向高地址扩展、不连续
    • 碎片问题:对于堆来讲,频繁的new/delete会造成内存空间的不连续,从而造成大量的碎片;对于栈来讲,不会存在这个问题,因为先进后出
    • 分配方式:堆是动态分配;栈有动态和静态。
    • 分配效率:栈效率高