iOS面试题整理

1.谈谈Object-C的内存管理方式及过程?

 Objective-C的内存管理主要有三种方式ARC(自动内存计数)、手动内存计数、内存池。

 解决方法的话: 谁持有,谁释放。

我们之前使用Objective-C中内存管理规则时,往往采用下面的准则
  •    生成对象时,使用autorelease
  •    对象代入时,先autorelease后再retain
  •    对象在函数中返回时,使用return [[object retain] autorelease];

2.#import和#include的区别,@class代表什么?

@class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文件中还是需要使用#import

而#import比起#include的好处就是不会引起重复包含

这两种的方式的区别在于:

 1、#import方式会包含被引用类的所有信息,包括被引用类的变量和方法;@class方式只是告诉编译器在A.h文件中 B *b 只是类的声明,具体这个类里有什么信息,这里不需要知道,等实现文件中真正要用到时,才会真正去查看B类中信息;

 2、使用@class方式由于只需要只要被引用类(B类)的名称就可以了,而在实现类由于要用到被引用类中的实体变量和方法,所以需要使用#importl来包含被引用类的头文件;

 3、通过上面2点也很容易知道在编译效率上,如果有上百个头文件都#import了同一 个文件,或者这些文件依次被#improt(A->B, B->C,C->D…),一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,这样的效率也是可想而知的,而相对来 讲,使用@class方式就不会出现这种问题了;

 4、对于循环依赖关系来说,比方A类引用B类,同时B类也引用A类,

当程序运行时,编译会报错, 

由上可知,@class是放在interface中的,只是在引用一个类,将这个被引用类作为一个类型,在实现文件中,如果需要引用到被引用类的实体变量或者方法时,还需要使用#import方式引入被引用类。

所以,一般来说,@class是放在interface中的,只是为了在interface中引用这个类,把这个类作为一个类型来用的。 在实现这个接口的实现类中,如果需要引用这个类的实体变量或者方法之类的,还是需要import在@class中声明的类进来.

 

@class

 

一个.h声明几个类时,互相使用时。

@class

@interface A

{

  B *B;

}

@interface B{}

3.Object-C有私有方法吗?私有变量呢

Objective-C中的类本身并没有私有方法这个概念,声明在 .h 文件中的方法都是公有的。不过,要想实现私有方法的效果还是有办法的,就是用Category。

// Hello.h

 

#import <Cocoa/Cocoa.h>
@interface Hello : NSObject {
    //变量声明
}
// 方法声明
@end
//




// Hello.m
#import "Hello.h"
@interface Hello () //=>此处Hello命名一致,后边跟括号
//=>@property (某种) aType ivarName ; 可实现私有变量

 

// 私有方法声明

- (void)test;
@end

@implementation Hello
// 私有方法实现

 

//=>@synthesize ivarName; 有私有变量的话

 

- (void)test {
// ..
}
// 方法实现
@end
在上面这个例子中,test 就是 Hello 类的“私有方法”了。再次证明,Category这个东东真的很强大~

 

4.Object-C有多继承吗?没有的话用什么代替?cocoa 中所有的类都是NSObject 的子类 

没有,用1.消息转发  2.delegate和protocol  3.类别  

5.浅拷贝和深拷贝区别是什么
简单的来说就是,在有指针的情况下,浅拷贝只是增加了一个指针指向已经存在的内存,而深拷贝就是增加一个指针并且申请一个新的内存,使这个增加的指针指向这个新的内存,采用深拷贝的情况下,释放内存的时候就不会出现在浅拷贝时重复释放同一内存的错误   retain +1 浅拷贝  copy 深拷贝
6.C和obj-c 如何混用
7. Objective-C中类别和类扩展的区别。

答案:category和extensions的不同在于后者可以添加属性。另外后者添加的方法是必须要实现的。

extensions可以认为是一个私有的Category。

 分类和类扩展的相似之处是: 都可以为类添加一个额外的方法

 不同之处在于:要添加额外方法,分类必须在第一个@interface中声明方法,并且在@implementation中提供实现,不然运行时出错。而类扩展,你添加的方法是一个required API,如果不去实现,编译器会警告,而且这个方法的声明可以不在第一个@interface中去声明。

 
8、堆和栈什么区别?

  答: 管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。

9、数组和链表什么区别?

  答: 数组是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。

       链表恰好相反,链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。 

10、delegate和notification什么区别,什么情况使用?

delegate 一对一

notification 一对多

 delegate的命名要准确,尽量看名字就知道用法。delegate和通知有的用法有些象,但是前者是单对单的,后者是单对多的情况。

注意:在dealloc要把delegate至为nil,还有就是delegate设置属性的时候要用assign,不要用retain。

11

assign: 简单赋值,不更改索引计数
copy: 建立一个索引计数为1的对象,然后释放旧对象
retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1 

 

12.两个controller传值,

一般的传值使用简单的赋值,

你可以在B里面声明一个属性,在A里面创建B的时候,将B的属性赋值即可

若当异步操作(一般耗时的或网络请求用异步)时,可以用一下方法,, 或   block

想到四个途径:
1)使用代理
2)使用通知notification
3)使用NSUserdefault
4)使用全局变量,如在appdelegate里面定义一个变量用于传值

NSNotification

  个人觉得用这个东西在不同的viewcontroller间传东西很方便的

  发消息

  [[NSNotificationCenter defaultCenter] postNotificationName:@"popView"/*消息名字,在添加监听时会用到*/       object:@"ShowHomeLineViewController"/*传的参数,多个参数就可以用数组啦*/];

  收消息

  1、添加监听:

  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(Show:)/*收到消息后的响应函数*/ name:@"popView"/*消息名字,在发消息时  指定的*/ object:nil];

  2、消息处理(实现前面的Show:函数)

  -(void)Show:(NSNotification*)notification

  {

  NSString* str = (NSString*)[notification object];//这里取出刚刚从过来的字符串

  }

  3、不要忘记移除监听

  [[NSNotificationCenter defaultCenter] removeObserver:self name:@"popView" object:nil];

 11、同步请求和异步请求什么区别?

答: 发送同步请求,程序将停止用户交互,直至服务器返回数据完成,才可以进行下一步操作,

      异步请求不会阻塞主线程,而会建立一个新的线程来操作,用户发出异步请求后,依然可以对UI进行操作,程序可以继续运行。

12、iOS中的多线程操作、多线程方式

 iOS 提供了方便的多线程调用机制: NSOperation 和 NSOperationQueue 。它的使用方法也很简单,

一般都是将NSOperation对象加入到NSOperationQueue队列中,加入后队列就开始处理,知道任务操作完成。

13、UIViewController的生命周期

答: 当一个视图控制器被创建,并在屏幕上显示的时候。 代码的执行顺序 
       // 视图显示在屏幕上的顺序

      1、 alloc                     创建对象,分配空间。

    2、init (initWithNibName)     初始化对象,初始化数据。

    3、loadView                    从nib载入视图, 这一步不需要去干涉。除非没有使用xib文件创建视图。

    4、viewDidLoad                 加载完毕,可以进行自定义数据以及动态创建其他控件。

    5、viewWillAppear              视图将出现在屏幕之前,马上这个视图即将显示在屏幕上。

    6、viewDidAppear               视图已在屏幕上渲染完成。

    // 视图将被从屏幕上移除的顺序

    1、viewWillDisappear           视图将被从屏幕上移除之前执行。

    2、viewDidDisappear            视图已经被从屏幕上移除。

    3、dealloc                     视图被销毁,此时需要在init和viewDidLoad中创建的对象进行释放。

    4、viewDidUnload               出现内存警告在内存不足时执行,并对所有非当前显示的controller执行。

在iOS6中,viewDidUnload回调方法被Deprecated掉了。查看苹果的文档,可以看到如下的说明。

 

dealloc方法

viewDidUnload和dealloc方法没有关联,dealloc还是继续做它该做的事情

 

看到以下的代码

- (void)viewDidUnload {

self.detailViewController = nil; 

self.languageNames = nil; 

self.languageCodes = nil;

}

- (void)dealloc {

[detailViewController release];

 [languageNames release]; 

[languageCodes release]; 

[super dealloc];

}

 

如果是先调用viewDidUnload后再调用dealloc, 那么languageNames都已经是nil了,再掉release有什么意义呢?

原因似乎是,对一个viewcontroller来说,它的数据的初始化在init中,而它管理的view采用了lazy load的方式,也就是有需要的时候才会载入,所以跟view相关的数据可以在viewDidLoad(也就是在view被载入的时候)进行初始化。当内存紧张的时候, ios会销毁点一些view,通过调用viewDidUnload (里面一般也只是把跟view相关的数据设为nil), 但这个时候viewcontroller本身还在,所以它的dealloc不会被调用,除非是到了viewcontroller也被销毁的时候

14、iOS数据持久化方式

    答: 四种:属性列表、对象归档、SQLite3和Core Data

15.实例方法跟类方法

16.weak strong retain

17.Object C中创建线程的方法是什么?如果在主线程中执行代码,方法是什么?如果想延时执行代码、方法又是什么?

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

 

18.

       另外:atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。
       加了atomic,setter函数会变成下面这样:
       if (property != newValue) {
       [property release];
       property = [newValue retain];
       }

19. 单件实例是什么

 答:  Foundation 和 Application Kit 框架中的一些类只允许创建单件对象,即这些类在当前进程中的唯一实例。

       举例:NSFileManager 和NSWorkspace 类在使用时都是基于进程进行单件对象的实例化。

       当向这些类请求实例的时候,它们会向您传递单一实例的一个引用,如果该实例还不存在,则首先进行实例的分配 和初始化。

 

27.类别的作用?继承和类别在实现中有何区别? 
 答: category 可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修改。

      并且如果类别和原来类中的方法产生名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。 类别主要有3个作用:

      (1)将类的实现分散到多个不同文件或多个不同框架中。

      (2)创建对私有方法的前向引用。

      (3)向对象添加非正式协议。  

      继承可以增加,修改或者删除方法,并且可以增加属性。

 28.类别和类扩展的区别。 
 答: category和extensions的不同在于 后者可以添加属性。另外后者添加的方法是必须要实现的。 extensions可以认为是一个私有的Category。

 

 29.29.KVO and KVC?

 

20.代理的作用

答: 代理的目的是改变或传递控制链。允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针。可以减少框架复杂度。 另外一点,代理可以理解为java中的回调监听机制的一种类似。

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

 
33.方法和选择器有何不同? 
答: selector是一个方法的名字,method是一个组合体 。
35.ARC自动引用技术
答: 1.ARC是编译特性,不是运行时特性,只是在编译的时候,编译器会自动加上释放代码 
    2.不能调用release、retain、autorelease、retainCount 
    3.dealloc注意 
     1> 不能在dealloc中调用[super dealloc] 
     2> 不能在dealloc中释放资源 
    4.@property 参数说明 
    1> retain 改为 strong 
    2> 基本数据类型(int\float)还是用assign 
    3> copy 还是 copy 
    4> 如果2个对象循环引用,一端用strong,一端用weak 
    5> weak是用在对象上,weak其实作用跟assign相当 
    5.ARC中只允许使用通过@autoreleasepool {}创建自动释放池
34.iOS多线程GCD

35.

进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地

址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一

个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的

地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程

序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进

行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

 

36.

为什么很多内置的类,如TableViewController的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模式时,也要注意这点。

 

 

 

转载于:https://www.cnblogs.com/smallyin00/p/3369465.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值