iOS面试回答之OC篇
0、面向对象的三大特征
答:封装、继承、多态
封装:把具体的对象封装成抽象的类,隐藏内部实现,对象的属性和实现细节,仅对外公开接口,提高代码的安全性,实现模块化调用。为元素搞公有私有访问就是为了隐藏实现细节,只露一个干净的接口,让业务逻辑不被实现细节所污染,即所谓的封装
好处:1.使用者只关注接口而不必关注实现,在使用第三方框架的时候。2.代码的维护性好
继承:描述类与类的关系,一个类是另外一个类的子类,子类可以复用父类的方法和属性
子类继承父类就会拥有父类所有的属性和方法
如果对于方法不满意可以重写父类的方法
缺点:1.使程序变得复杂2.破坏了封装性3.降低了可维护性和可扩展性
多态:引用的多种形态,Polymorphism,父类指针指向子类对象,子类可以重写父类的方法。Animal子类有cat,dog,虽然都有Eat方法,但是父类不能用子类的方法,子类的方法可能各有不同。不同对象以自己的方式响应相同的消息的能力叫做多态。
1、Objective-C的类可以多重继承么?可以采用多个协议么?
答:不可以多重继承,只有Java这个变态可以多继承.oc中所有的类都是NSObject 的子类,可以用代理来代替多继承的功能
可以遵守多个协议,用逗号隔开<NSCoding,NSCoping>。
2、#import和#include的区别是什么?#import<> 跟 #import""有什么区别?
答:#include是C/C++中的,OC中要用#import避免头文件被重复包含的问题。比如class A,class B都引用了class C,class D若引用class A与class B,就会报头文件重复引用错误,如果非要用#import,要加上#define if的预编译指令剔除重复的头文件。在OC就乖乖用#import
#import<> 导入系统头文件, #import""自己的头文件
3、Category是什么?
答:
Category是分类,就是用来增强一个类的能力。
比如在开发中frame这样的结构体不可以直接修改属性,可以自己写个Category,UIView+Extension,在h里定义,在m里实现一些方法这样就可以导入头文件,直接可以修改属性了。当然系统的类和自定义的类都可以写分类。
所以说Category就是可以在不用知晓一个类的具体内容,不改变原来代码的情况下,给它添加一些方法。可以覆盖但不能修改或删除方法
可以将类的实现分散到多个不同文件或多个不同框架中
在分类中可以定义属性,实例变量,是公开的啦
4、 Extension是什么?
Extension是扩展,扩展是分类的一种特殊的形式,是没有名字的私有的分类。
比如我们在UIViewController里@interface和@end之间写的东西就是扩展啦。
@interface TRCat ()//没有分类名了
@property (nonatomic,strong)NSString* name;//此处声明属性
-(void)fly;//此处声明方法
@end
其实简言之,扩展就是用来声明私有的属性和方法,如果独立声明的话只有h文件没有m文件,甚至像上面那样的不用独立的文件都可以!
5、Protocol是什么?
Protocol是协议,只有.h文件,甚至可以不独立文件
使用时 遵守协议,在本类中实现方法就可以
协议有required和optional的,required是必须实现的协议方法。
6、继承是什么?扩展一个类的方式用继承好还是分类好?为什么?
继承是用来描述类与类之间的关系的。子类继承于父类,拥有父类的属性和方法。
扩展一个类用Category好。继承会破坏程序的封装性。
7、类实例(成员)变量的@protected,@private,@public声明各有什么含义?
答:@protected是受保护的,只能在本类及其子类中访问
@private是私有的,只能在本类访问
@public公开的
8、浅拷贝和深拷贝区别
答:平常的EVDog* dog1=dog2这样的都叫浅拷贝
EVDog* dog1=[dog2 copy]这样的叫深拷贝
所以浅拷贝只拷贝了地址(指针)并没有产生新对象。而深拷贝产生了新的对象
如果拷贝完后改变原对象的属性,深拷贝的对象的属性不变,浅拷贝的对象属性会变化
9、属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用
答:assign用于简单数据类型,如NSInteger,double,bool,
retain和copy用于对象,
readwrite是可读可写特性;需要生成getter方法和setter方法时
readonly是只读特性 只会生成getter方法 不会生成setter方法 ;不希望属性在类外改变
assign是赋值特性,setter方法将传入参数赋值给实例变量;仅设置变量时;
retain表示持有特性,setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1;
copy表示赋值特性,setter方法将传入对象复制一份;需要一份新的变量时。
nonatomic非原子操作,atomic原子性操作。原子性指的是一个操作不可以被中途cpu暂停然后调度, 即不能被中断, 要不就执行完, 要不就不执行,就是为了多线程安全的。
一般使用nonatomic。
10、@class的作用
答:告诉编译器有这么个类
在.h文件中, 一般只需要知道被引用的类的名称就可以了。 不需要知道其内部的实体变量和方法,所以在头文件中一般使用@class来声明这个名称是类的名称。 而在实现类里面,因为会用到这个引用类的内部的实体变量和方法,所以需要使用#import来包含这个被引用类的头文件。
@class还可以解决循环依赖的问题,例如A.h导入了B.h,而B.h导入了A.h,每一个头文件的编译都要让对象先编译成功才行
11、id 声明的对象有什么特性?
答:id类型的对象可以是任意类型的OC对象,与C中的void*万能指针相似。具有运行时的特点,在程序运行时才确定对象的类型。
12、frame和bounds有什么不同?
答:frame是在父视图坐标系下的位置和大小。bounds是自身坐标系下的位置和大小。
frame以父控件的左上角为坐标原点,bounds以控件本身的左上角为坐标原点
13、方法和选择器有何不同?
答:selector是方法的名字,通过它可以找到方法
方法是相对于对象来说的,包含名字和实现等。
14、lazy loading是什么
答:懒加载。直到要用的时候才去初始化。
15、是否可以在一个视图控制器中嵌入两个tableview控制器?(Can we use two tableview controllers on one viewcontroller?)
答:可以。
如果是视图的话,一个视图下当然可以有两个tableView
如果是控制器的话,tabBarController下就可以有两个呀
16、一个tableView是否可以关联两个不同的数据源?你会怎么处理?(Can we use one tableview with two different datasources? How you will achieve this?)
答:不明白。tableView的dataSource就是控制器啊,应该不能两个吧?没有意义
17、什么是KVO?什么是KVC
答:KVC:key-value-coding。键值编码。提供一种机制,直接通过字符串来标识对象的属性。可以用valueForKeyPath/setValue forKeyPath等来访问(读取或设置)对象的属性,而不是通过setter,getter方法。可以简化程序代码
KVO是基于KVC的。Key-value-observer 键值观察者。注册成为观察者后,可以动态地监控对象属性的变化。发生变化时可以收到通知。
18、Delegate的作用
答:代理是回调监听机制的一种,一个类做不了的事就交给其他类来做。
比如actionSheet本身是没办法处理用户交互事件的,所以要让控制器成为其代理来处理。当控制器遵守协议,实现方法,成为它的代理之后,就可以在特定的时间通知控制器进行处理,所以delegate方法里经常有did,should,will这样的词。
要注意Delegate的声明一定要是weak的,以避免循环引用内存泄漏
19、oc中可修改和不可以修改类型(What are mutable and immutable types in Objective C?)
答:可修改不可修改类。OC中的可变不可变类型
比如NSArray和NSMutableArray,NSDictionary和NSMutableDictionary能否动态添加和修改内容。前者在初始化后的内存控件就是固定不可变的,后者可以添加等,可以动态申请新的内存空间。
20、runtime是什么?
答:运行时是指在程序运行时才确定数据的类型,调用指定的方法。将数据类型的确定由编译时推迟到了程序运行时。可以通过字符串来创建对象NSClassFromString,创建方法,创建属性NSSelectorFromString
21、method和selector的区别?
答:方法和选择器的区别
selector是方法的名字,通过它可以找到方法
方法是相对于对象来说的,包含名字和实现等。
22、写一个委托的interface
答:先写个协议:
1.声明一个协议(只有.h文件)
import <Foundation/Foundation.h>
@protocal 协议名superMan<父协议NSObject>
@property NSString* name;
-(void)method;
@end
2.使一个类遵守协议
@interface TRMan:NSObject<superMan>
多个协议要用,隔开
3.使用协议
id<协议名superMan> obj=[[TRMan alloc]init];
@ protocol MyDelegate
@interface MyClass : NSObject
@property(nonatomic,weak)id<TRPassValue> delegate;
@end
协议也可以没有独立文件,写在类里
import <UIKit/UIKit.h>
@class MyClass;
@protocol MyClassDelegate <NSObject>
-(void)protocolMethod;
@end
@interface MyClass : NSObject
@property(nonatomic,weak)id<MyClassDelegate> delegate;
@end
23、写个单例
利用GCD构建
DataCenter.h
import <Foundation/Foundation.h>
@interface DataCenter : NSObject
+(id)sharedDataCenter;
@end
DataCenter.m
import "DataCenter.h"
@implementation DataCenter
+(id)sharedDataCenter{
static DataCenter *sharedDataCenter=nil;
static dispatch_once_t token;
dispatch_once(&token, ^{
sharedDataCenter = [[self alloc]init];
});
return sharedDataCenter;
}
@end
24、const/static/extern的作用
————————————————————————————————————————————————————————
通知NSNotification和协议protocol的区别
17.NSOperation queue?
答案:存放NSOperation的集合类。操作和操作队列,用于处理ios多线程开发
操作和操作队列,基本可以看成java中的线程和线程池的概念。用于处理ios多线程开发的问题。
网上部分资料提到一点是,虽然是queue,但是却并不是带有队列的概念,放入的操作并非是按照严格的先进现出。
这边又有个疑点是,对于队列来说,先进先出的概念是Afunc添加进队列,Bfunc紧跟着也进入队列,Afunc先执行这个是必然的,
但是Bfunc是等Afunc完全操作完以后,B才开始启动并且执行,因此队列的概念离乱上有点违背了多线程处理这个概念。
但是转念一想其实可以参考银行的取票和叫号系统。
因此对于A比B先排队取票但是B率先执行完操作,我们亦然可以感性认为这还是一个队列。
但是后来看到一票关于这操作队列话题的文章,其中有一句提到
“因为两个操作提交的时间间隔很近,线程池中的线程,谁先启动是不定的。”
瞬间觉得这个queue名字有点忽悠人了,还不如pool~
综合一点,我们知道他可以比较大的用处在于可以帮组多线程编程就好了。
- 说说响应链(What is responder chain?)
- 什么是推送消息?(What is push notification?)
什么是接口
可以调用的属性方法
10、试写出 @property中带retain和assign关键字,通过@synthesize自动生成的的合成存取方法(set、get方法)的实现代码
@property(nonatomic,retain)EVDog* dog;
@property(nonatomic,assign)EVCat cat;
iOS中有哪些回调机制,并作简单的比较.
target: action:
delegate
通知:notification
观察者模式:
block: