iOS面试iOS精品文章-面试iOS-面试题

iOS基础面试题

2015-10-31  本文已影响1819人  findM

搜集于互联网,如有侵权,删之。

1.属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况下用?

  1. readwrite 是可读可写特性;需要生成getter方法和setter方法时;
  2. readonly 是只读特性 只会生成getter方法 不会生成setter方法 ;不希望属性在类外改变时;
  3. assign 是赋值特性,setter方法将传入参数赋值给实例变量;仅设置变量时,一般用于基础数据类型;
  4. retain 表示持有特性,setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1,也就是说release旧值,retain新值;一般用于OC对象;
  5. copy 表示赋值特性,setter方法将传入对象复制一份;需要完全一份新的变量时,也就是release旧值,copy新值;一般用于NSString\NSMutableString\block;
    6.nonatomic 非原子操作,决定编译器生成的setter getter是否是原子操作,atomic表示多线程安全,一般使用nonatomic。

2.#import 跟#include、@class有什么区别?#import<> 跟 #import”"又什么区别?
1.#import和#include都能完整地包含某个文件的内容,#import能防止同一个文件被包含多次。

  1. @class和#import
    作用上的区别:
    #import会包含引用类的所有信息(内容), 包括引用类的变量和方法;
    @class仅仅是告诉编译器有这么一个类, 具体这个类里有什么信息, 完全不知;
    效率上的区别:
    如果有上百个头文件都#import了同一个文件,或者这些文件依次被#import,那么一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍 , 编译效率非常低;
    相对来讲,使用@class方式就不会出现这种问题了
  2. import <> 用来包含系统自带的文件,#import “”用来包含自定义的文件。

3.OC有多继承吗?没有的话用什么代替?
OC中没有多继承,可以用委托代理Protocol来实现。

4.Objective-C如何对内存管理的?内存管理的原则是?
Objective-C的内存管理主要有三种方式ARC(自动引用计数)、MRC(手动内存计数)、autorelease(自动释放池)。
每个对象都有一个引用计数器,每个新对象的计数器是1,当对象的计数器减为0时,就会被销毁。
内存管理原则(配对原则):只要出现了 new/alloc/retain,就一定配对出现一个release/autorelease。

5、Object C中创建线程的方法是什么?如果在主线程中执行代码,方法是什么?如果想延时执行代码、方法又是什么?
线程创建有三种方法:使用NSThread创建、使用GCD的dispatch、使用子类化的NSOperation,然后将其加入NSOperationQueue;在主线程执行代码,方法是performSelectorOnMainThread,如果想延时执行代码可以用performSelector:onThread:withObject:waitUntilDone:;

6、浅复制和深复制的区别?
浅复制:只复制指向对象的指针,而不复制引用对象本身。
深复制:复制引用对象本身。
意思就是说我有个A对象,复制一份后得到A_copy对象后,对于浅复制来说,A和A_copy指向的是同一个内存资源,复制的只不过是是一个指针,对象本身资源还是只有一份,那如果我们对A_copy执行了修改操作,那么发现A引用的对象同样被修改,这其实违背了我们复制拷贝的一个思想。深复制就好理解了,内存中存在了两份独立对象本身。
用通俗的话讲就是:浅复制好比你和你的影子,你完蛋,你的影子也完蛋;深复制好比你和你的克隆人,你完蛋,你的克隆人还活着。

7、分类的作用?分类和继承的区别?
分类可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修改,并且如果分类和原来类中的方法产生名称冲突,则分类将覆盖原来的方法,因为分类具有更高的优先级。
继承可以增加,修改或者删除方法,并且可以增加属性;但是分类只能添加方法,不能删除修改,也不能增加属性。

8、frame和bounds有什么不同?
frame指的是:该view在父view坐标系统中的位置和大小。(参照点是父亲的坐标系统)
bounds指的是:该view在本身坐标系统中 的位置和大小。(参照点是本身坐标系统)

9、HTTP协议中,POST和GET的区别是什么?
1.GET 方法:

11、block和代理的区别,哪个更好?
代理回调更面向过程,block更面向结果。如果需要在执行的不同步骤时被通知,你就要使用代理。如果只需要请求的消息或者失败的详情,应该使用block。block更适合与状态无关的操作,比如被告知某些结果,block之间是不会相互影响的。但是代理更像一个生产流水线,每个回调方法是生产线上的一个处理步骤,一个回调的变动可能会引起另一个回调的变动。要是一个对象有超过一个的不同事件,应该使用代理。一个对象只有一个代理,要是某个对象是个单例对象,就不能使用代理。要是一个对象调用方法需要返回一些额外的信息,就可能需要使用代理。

12、自动释放池常见面试代码

for (int i = 0; i < 10; ++i) 
{    
      NSString *str = @"Hello World";    
      str = [str stringByAppendingFormat:@" - %d", i];    
      str = [str uppercaseString];    NSLog(@"%@", str);
}

问:以上代码存在什么样的问题?如果循环的次数非常大时,应该如何修改?

1.有多少组
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
2.第section组头部控件有多高
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
3.第section组有多少行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
4.indexPath这行的cell有多高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
5.indexPath这行的cell长什么样子
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 6.第section组头部显示什么控件
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

代理方法:

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView   //右侧索引
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath   //行点击事件
NSIndexPath *path = [self.tableView indexPathForSelectedRow];     //获得被选中的indexPath可以得到section,row
[self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForSelectedRows] withRowAnimation:UITableViewRowAnimationNone];    //刷新table指定行的数据       
[self.tableView reloadData];       //刷新table所有行的数据

17、UITableViewCell表格优化?
UITableViewCell对象的重用原理:当滚动列表时,部分UITableViewCell会移出窗口,UITableView会将窗口外的UITableViewCell放入一个对象池中,等待重用。当UITableView要求dataSource返回UITableViewCell时,dataSource会先查看这个对象池,如果池中有未使用的UITableViewCell,dataSource会用新的数据配置这个UITableViewCell,然后返回给UITableView,重新显示到窗口中,从而避免创建新对象。
还有一个非常重要的问题:有时候需要自定义UITableViewCell(用一个子类继承UITableViewCell),而且每一行用的不一定是同一种UITableViewCell(如短信聊天布局),所以一个UITableView可能拥有不同类型的UITableViewCell,对象池中也会有很多不同类型的UITableViewCell,时可能会得到错误类型的UITableViewCell那么UITableView在重用UITableViewCell。解决方案:UITableViewCell有个NSString *reuseIdentifier属性,可以在初始化UITableViewCell的时候传入一个特定的字符串标识来设置reuseIdentifier(一般用UITableViewCell的类名)。当UITableView要求dataSource返回UITableViewCell时,先通过一个字符串标识到对象池中查找对应类型的UITableViewCell对象,如果有,就重用,如果没有,就传入这个字符串标识来初始化一个UITableViewCell对象。
18、在一个对象的方法里面:self.name = @"object";name =@"object";有什么不同吗?
self.name = @"object";会调用对象的setName()方法,name =@"object";会直接把@"object"赋值给当前对象的name 属性。
19、为什么很多内置类如UITableViewController的delegate属性都是assign而不是retain的?
会引起循环引用
所有的引用计数系统,都存在循环应用的问题。例如下面的引用关系:
• 对象a创建并引用到了对象b.
• 对象b创建并引用到了对象c.
• 对象c创建并引用到了对象b.这时候b和c的引用计数分别是2和1。
当a不再使用b,调用release释放对b的所有权,因为c还引用了b,所以b的引用计数为1,b不会被释放。b不释放,c的引用计数就是1,c也不会被释放。从此,b和c永远留在内存中。这种情况,必须打断循环引用,通过其他规则来维护引用关系。我们常见的delegate往往是assign方式的属性而不是retain方式 的属性,赋值不会增加引用计数,就是为了防止delegation两端产生不必要的循环引用。如果一个UITableViewController 对象a通过retain获取了UITableView对象b的所有权,这个UITableView对象b的delegate又是a, 如果这个delegate是retain方式的,那基本上就没有机会释放这两个对象了。自己在设计使用delegate模式时,也要注意这点。
20、什么是Notification?
观察者模式,controller向defaultNotificationCenter添加自己的notification,其他类注册这个notification就可以收到通知,这些类可以在收到通知时做自己的操作(多观察者默认随机顺序发通知给观察者们,而且每个观察者都要等当前的某个观察者的操作做完才能轮到他来操作,可以用NotificationQueue的方式安排观察者的反应顺序,也可以在添加观察者中设定反映时间,取消观察需要在viewDidUnload 跟dealloc中都要注销)。
21、单例模式的作用?程序中有哪些常见的单例?单例的实现步骤?

  1. 为Singleton Object实现一个静态实例, 初始化, 然后设置成nil.
  2. 实现一个实例构造方法(通常命名为 sharedInstance 或者 sharedManager)检查上面声名的静态实例是否为nil, 如果是则新建并返回一个本类实例.
  3. 重写 allocWithZone: 方法来保证当其他人直接使用 alloc 和 init 试图获得一个新实例的时候不会产生一个新的实例.
  4. 适当的实现 copyWithZone:, release, retain, retainCount 和 autorelease.
    22、block使用时的注意点?
    Block可以使用在定义之前声明的局部变量;
int i = 10;
void(^myBlock)() = ^{
     NSLog(@"%d", i);
};
i = 100;
myBlock();

注意:

上一篇下一篇

猜你喜欢

热点阅读