你的位置:首页 > 操作系统

[操作系统]一些iOS面试长见问题的讨论


---恢复内容开始---

0、为什么使用XIB/StoryBoard创建控件时,对象要用weak来修饰?
IBOutlet的属性一般可以设为weak是因为它已经被view引用了,除非view被释放,否则IBOutlet的属性也不会被释放,另外IBOutlet属性的生命周期和view应该是一致的,所以IBOutlet属性一般设为weak。
1、#import和#include的区别,@class代表什么?
(1)#import指令是Object-C针对#include的改进版本,#import确保引用的文件只会被引用一次,这样你就不会陷入递归包含的问题中。
(2)@class:类的前置声明
2、浅拷贝和深拷贝区别是什么?
浅 拷贝就是成员数据之间的一一赋值:把值一一赋给要拷贝的值。但是可能会有这样的情况:对象还包含资源,这里的资源可以是堆资源,或者一个文件。当值拷贝 的时候,两个对象就有用共同的资源,同时对资源可以访问,这样就会出问题。深拷贝就是用来解决这样的问题的,它把资源也赋值一次,使对象拥有不同的资源, 但资源的内容是一样的。对于堆资源来说,就是在开辟一片堆内存,把原来的内容拷贝。
如果你拷贝的对象中引用了某个外部的内容(比如分配在堆上的数据),那么在拷贝这个对象的时候,让新旧两个对象指向同一个外部的内容,就是浅拷贝;如果在拷贝这个对象的时候为新对象制作了外部对象的独立拷贝,就是深拷贝 。
引用和指针的语义是相似的,引用是不可改变的指针,指针是可以改变的引用。其实都是实现了引用语义。
深拷贝和浅拷贝的区别是在对象状态中包含其它对象的引用的时候,当拷贝一个对象时,如果需要拷贝这个对象引用的对象,则是深拷贝,否则是浅拷贝。
COW语义是“深拷贝”与“推迟计算”的组合,仍然是深拷贝,而非浅拷贝,因为拷贝之后的两个对象的数据在逻辑上是不相关的,只是内容相同。
3、Objective-C中类别和类扩展的区别?
在iOS中,有一种机制可以使用户在没有远吗的情况下扩展类的功能,但不是通过继承,这就是类别。iOS中没有类似C++中可以定义私有方法和私有变量的关键字,要定义私有方法和私有变量,可以用类扩展来实现。
类别
类别在不需要继承的情况下可以扩展类的功能。但类别不能添加类的属性和私有变量。类别可以用来扩展Cocoa中类的方法,也可以用来扩展用户自己的类中的 方法。当我们查看系统头文件的时候能发现类似@interface NSMutableArray (NSExtendedMutableArray)的类定义,其实这就是类别的定义形式。
类别的定义和类的定义有相似之处,都是用关键字@interface和类名来定义,不同之处在于类别的定义是在类名之后不是类所继承的父类,而是用括号括 起来的类别名。@end之前的方法定义和类中方法的定义是一样的。不过,在类别中,不能定义属性。类别中的方法与原类中的方法的使用是完全一致的,没有任 何差别。所有NSString的子类也都能使用类这两个类别中的方法。
在使用类别的时候,类别中的方法命名特别重要。
如果类别中的方法名与原类中的方法名重名了,在苹果开发者文档中的描述是,当方法重名的时候,在运行的时候不知道会调用哪个方法。实际上,这个应该是有规 则可循的。我建了一个工程,给NSString增加了一个类别,里面重写了length和substringFromIndex方法。length方法是 NSString的方法,substringFromIndex是NSString的一个类别里的方法。当我调用者两个方法时,发现调用length的时 候返回的是系统的那个调用,而不是我自己实现。而当调用substringFromIndex时,调用的则是我实现的方法。于是我推断当系统类中的方法名 与自己定义的类别里的方法重名时,会调用系统的方法名,而当自定义类别中的方法名与系统类别中的方法重名时,会使用自定义类别中的方法的实现。为了验证这 一推断,我又继续增加了NSArray的类别来进行测试,测试结果正如我推断的一样。即使是这样,我们也不能确定这个结论就是正确的,还有待进一步的验 证。
4、Objective-C堆和栈的区别?
堆和栈的区别:
  一、堆栈空间分配区别:
  1、栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈;
  2、堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。
  二、堆栈缓存方式区别:
  1、栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放;
  2、堆是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。
  三、堆栈数据结构区别:
  堆(数据结构):堆可以被看成是一棵树,如:堆排序;
  栈(数据结构):一种先进后出的数据结构。
5、内存管理的几个原则是什么?
IOS的对象都继承于NSObject,   该对象有一个方法:retainCount ,内存引用计数。 引用计数在很多技术都用到: window下的COM组件,多线程的信号量,读写锁,思想都一样。
   (一般情况下: 后面会讨论例外情况)
    alloc      对象分配后引用计数为1
    retain    对象的引用计数+1
    copy      copy 一个对象变成新的对象(新内存地址) 引用计数为1 原来对象计数不变
    release            对象引用计数-1 如果为0释放内存
    autorelease      对象引用计数-1 如果为0不马上释放,结束最近一个pool时释放
6、NSMuatableArray *array = [NSMuatableArray array] 需要释放么?
不需要
7、@property本质是什么
@property (nonatomic, retain) NSString *name;
@synthesize name;
这种方式的本质是:
-(NSString *) name{
       return name;
}
 
-(void) setName:(NSStrng *) newName{
       if(name!=newName){
              [name release];
              name=[newName retain];
       }
}
对setName方法的解释:
(1)为何要加name!=newName的判断
          如果要是不加,传过来的参数如果是相同的,则newName会一直retain
(2)为何[name release]
          如果不release,直接name=[newName retain],则name原先所指向的内存则会泄露,因为没有释放
8、delegate用什么属性修饰,ARC下与MRC下有何不同,为什么?
1、delegate 之所以用weak来修饰,是防止循环引用,weak属性的变量是不为其所属 对象持有的,并且在该变量被销毁之后,此weak变量的值会自动被赋值为nil。而assign属性一般是对C基本数据类型成员变量的声明,当然也可以用 在对象类型成员变量上,只是其代表的意义只是单纯地拷贝所赋值变量的值。即如果对某assign成员变量B赋值某对象A的指针,则此B只是简单地保存此指 针的值,且并不持有对象A,也就意味着如果A被销毁,则B就指向了一个已经被销毁的对象,如果再对其发送消息会引发崩溃。
2、那关于delegate 既然用weak这么好用,用assign会出现野指针,为什么还会用呢?weak和strong属性是ARC才引入的,而在MRC情况下,只能使用 assign修饰了。weak之所以强大的地方,是当引用的对象被销毁时,它的值也会变为nil,所以推荐使用ARC。
9、NSString,NSArray,NSMutableArray分别用什么属性修饰,原因是什么?
@property(nonatomic,copy)NSString *string;
@property(nonatomic,copy)NSArray *array;
@property(nonatomic,strong)NSMutableArray *array;
10、block用什么属性修饰,为什么?
用copy修饰,保证线程安全,以及block的声明。
11、__block与__weak的区别是什么?
1.__block对象在block中是可以被修改、重新赋值的。
2.__block对象在block中不会被block强引用一次,从而不会出现循环引用问题。
使用了__weak修饰符的对象,作用等同于定义为weak的property。自然不会导致循环引用问题,因为当原对象没有任何强引用的时候,弱引用指针也会被设置为nil。
因此,__block和__weak修饰符的区别其实是挺明显的: 
1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。 
2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。 
3.__block对象可以在block中被重新赋值,__weak不可以。
12、assign与weak的区别是什么?
1.weak:(1).在ARC中,在有可能出现循环引用的时候,往往要通过让其中一端使用weak来解决,比如:delegate代理属性。 (2).如果自身已经对它进行一次强引用,没有必要再强引用一次时也会使用weak。比如:自定义IBOutlet控件属性一般也使用weak,当然也可 以使用strong。2.assign:用于基础数据类型(例如NSInteger等)和C数据类型(int, float, double, char)等,另外还有id类型。
不同点:(1).weak,表明该属性定义了一种“非拥有关系” (nonowning relationship)。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。(2).assign也可以修饰对象,但是用assign修饰 的对象在释放后,指针的地址还是存在的,也就是说指针并没有被置为nil,会造成众所周知的野指针异常。然而,assign修饰的基础数据类型(例如 NSInteger等)和C数据类型(int, float, double, char)等一般分配在栈空间上,栈空间的内存会由系统自动处理,当分配的栈空间的内存没有被指针指向时就会被销毁,所以不会造成野指针异常。 (3).weak比 assign多了一个功能就是当属性所指向的对象消失的时候(也就是内存引用计数为0)会自动赋值为 nil,这样再向 weak修饰的属性发送消息就不会导致野指针操作crash。
13、分别写一个setter方法和getter方法完成@property(nonatomic,retain)NSString *name和@property(nonatomic,copy)NSString *name和@property(nonatomic,assign)NSString *name;
(1)@property(nonatomic,assign)NSString *name
- (void)setName:(NSString *)name
{
    _name = name;
}
- (NSString *)name
{
    return _name;
}
(2)@property(nonatomic,retain)NSString *name
- (void)setName:(NSString *)name
{
    if(_name != name){
    [_name release];
    _name = [name retain];
    }
}
- (NSString *)name
{
    return [[_name retain] autorelease];
}
(3)@property(nonatomic,copy)NSString *name
- (void) setName:(NSString)name
{
    if(_name != name)
    {
        [_name release];
        _name = [name copy];
    }
}
- (NSString *)name
{
    return [[_name retain] autorelease];
}
14、@autoreleasepool {for (long i = 0; i < largeNumber; i++) {Person *per = [[Person alloc] init];[per autorelease];}}有什么内存问题,如何改正?
使用autorelease会将对方存放到最近的释放池中,不会使引用计数立即减一,当释放池销毁时才会被release,所以在这里直接用autorelease是错误的。
改正如下:
@autoreleasepool{
    for(long i = 0 ; i < largeNumber ; i++){
    //在自动释放池中在创建一个自动释放池,每次循环就会立即释放对象
    @autoreleasepool{
    Person *per = [[Person alloc] init];
    [per autorelease];
    }
    }
}
15、如何写一个单例?
+(SingLeton *)ShareIntance;
 static Singleton * intance = nil;
+(SingLeton *)ShareIntance{
    if(intance == nil){
    intance = [[Singleton alloc] init];
    }
    return instance;
}
16、post与get的区别?
GET请求的数据会附注在URL之后,POST是把请求的数据放在HTTP包的包体中。
GET提交的数据最多是1024字节,POST没有限制。
get请求数据外部可以看见请求内容,post外部无法看见,get只能传送数据,post可以传送数据也可以发送文件;

17、Http与tcp,udp的区别?
IP:网络层协议
TCP/UDP:传输层协议
TCP/UDP是HTTP传输层协议。
HTTP是利用TCP在两台电脑之间实现信息传输的协议
18、http都设置哪些header?
HTTP协议采用了Message-header/Message-body模型
http header 消息通常被分为4个部分:general  header(通用头), request header(请求头), response header(响应头), entity header(实体头)
19、http与https的区别?
HTTPS需要得到CA申请证书,一般免费证书很少,需要交费;
HTTP是超文本传输协议,信息是明文传送;
HTTPS是HTTP的安全传输通道,使用SSl加密传输协议;
HTTP的端口是80,HTTPS的端口是443;
HTTP连接很简是无状态的,HTTPS是由SSL+HTTP构成的,可以进行加密传输、身份认证的网络协议,要比HTTP安全。
20、网络七层协议(http,tcp/ip处于哪一层)?
7.应用层:拥有与其他客户端具有通信功能的程序,它是对应应用程序的通信服务的;HTTP位于该层。
6.表示层:定义数据格式以及加密;
5.会话层:定义了如何开始、控制、结束一个会话;
4.传输层:TCP位于该层。
3.网络层:IP位于该层。
2.数据链路层
1.物理层
其中高层7、6、5、4层定义了应用程序的功能,下面的3、2、1层主要是通过面向网络的端到端的数据流
21、常用多线程方式有哪些?
NSThread、NSOperation、GCD、PThread
22、NSOperation比GCD有哪些优点,如何处理线程依赖
NSOperation:
优点:不需要线程管理,数据同步的事情,可以把精力放在自己需要操作的事情上。
缺点:NSOperation是面向对象的。
GCD
优点:是苹果公司开发的一个多核开发编程解决方案,是替代NSThread、NSOperation的高效和强大的技术。
缺点:GCD是基于C语言的。
23、runloop与线程的关系
线程和runloop是一一对应的,线程刚创建的时候是没有runloop的,只有在获取的时候创建runloop,在线程结束的时候runloop就会被销毁。只能在线程内部获取runloop(主线程除外)。
24、runtime的理解
runtime简称运行时,就是系统在运行的时候的一些机制,其中最重要的是消息机制。OC函数调用成为消息发送,属于动态调用过程,在编译的时候不能决定真正调用哪个函数,只有在程序真正运行的时候才根据函数名找到对应的函数调用。
25、在实际项目中遇到过死锁么?如何处理死锁问题
死锁产生的原因:
1.互斥条件:一个资源每次只能被一个进程使用;
2.请求与保护条件:一个进程在因请求资源而阻塞的时候,对对已获得的资源保持不放。
3.不剥夺条件:进程已获得的资源,在没有使用完之前,不能强行剥夺。
4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
死锁的定义:在一组进程中,每个进程都占有不会释放的资源,但因相互申请被其他进程所占用不会释放资源,而处于一种永久等待的状态。
避免死锁:
1.按同一顺序访问对象(避免出现循环)。
2.避免事物中的产品交互(减少资源的持有时间,避免出现锁竞争)。
3.保持事物简短并处于一个批处理中(减少资源的持有时间)。
4.使用较低的隔离级别(使用较低的隔离级别(例如:已提交读)比使用较高的隔离级别(例如:可序列化)持有共享锁的时间更短,减少锁竞争)。
5.使用基于行版本的隔离级别。
6.使用绑定连接。
死锁的解决方案:
1.根据2中提供的sql,查看那个spid处于wait状态,然后用kill spid来干掉(即破坏死锁的第四个必要条件:循环等待);当然这只是一种临时解决方案,我们总不能在遇到死锁就在用户的生产环境上排查死锁、Kill sp,我们应该考虑如何去避免死锁。
2.使用SET LOCK_TIMEOUT timeout_period(单位为毫秒)来设定锁请求超时。默认情况下,数据库没有超时期限(timeout_period值为-1,可以用SELECT @@LOCK_TIMEOUT来查看该值,即无限期等待)。当请求锁超过timeout_period时,将返回错误。timeout_period值为0时表示根本不等待,一遇到锁就返回消息。设置锁请求超时,破环了死锁的第二个必要条件(请求与保持条件)。
3.SQL Server内部有一个锁监视器线程执行死锁检查,锁监视器对特定线程启动死锁搜索时,会标识线程正在等待 的资源;然后查找特定资源的所有者,并递归地继续执行对那些线程的死锁搜索,直到找到一个构成死锁条件的循环。检测到死锁后,数据库引擎 选择运行回滚,开 销最小的事务的会话作为死锁牺牲品,返回1205 错误,回滚死锁牺牲品的事务并释放该事务持有的所有锁,使其他线程的事务可以请求资源并继续运行。
26、runloop有几种模式,runloop接收几种输入源
runloop处理的事件的来源:输入源、定时源。
输入源:
1.基于端口的源;
2.自定义输入源;
3.Cocoa Perform Selector Sources;
模式:
1.Default:默认模式是用于大多数操作的一个默认模式。大多数时候,你应该使用这个模式来启动你的运行循环,并配置你的输入源。
2.Connection:
3.Modal:使用这种模式来识别用于模态面板的事件。
4.Event tracking:使用这种模式来限制鼠标拖动循环和其他类型的用户界面跟踪环路中的传入事件。
5.Common modes
27、如何处理滑动UI过程中,广告轮播图停止轮询问题,使用runloop的哪种模式
解决方法,一种方法是在另外的线程中处理定时器事件,可把Timer加入到NSOperation中在另一个线程中调度;还有一种方法时修改Timer运行的run loop模式,将其加入到UITrackingRunLoopMode模式或NSRunLoopCommonModes模式中。
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
28、有一个需求,需要将N个请求全部完成之后执行某个操作,该如何处理?
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
    
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_async(group, queue, ^{
        
        for (NSInteger i = 0; i < 10000; i++) {
            
            NSLog(@"%lu",i);
        }
        
    });
    
    dispatch_group_notify(group, queue, ^{
        
        NSLog(@"finished");
        
    });
29、weak会有性能开销么?使用什么代替?
有,strong
30、autorelease pool的原理是什么?
延迟调用release,系统只是把Object放入最近的autoreleasepool中,当autoreleasepool被释放,autorelease中的object都会被release。对于每个runloop系统都会隐式创建一个autoreleasepool,这样就构成了CallStack一样的栈式结构,当runloop结束时,当前栈顶的autoreleasepool就会被释放,autoreleasepool里面的object就会被release。
31、runloop的原理
1.(要让马儿跑)通过do_while死循环让程序持续运行,接收用户输入、调度处理事件时间。
2.(要让马儿少吃草)mach_msg(),让runloop在没事儿的时候进入trpy状态,节省CPU资源。
32、runloop与autoreleasepool的关系
每个runloop系统都会隐式创建一个autoreleasepool,在runloop结束时,autoreleasepool就会被释放。


---恢复内容结束---

0、为什么使用XIB/StoryBoard创建控件时,对象要用weak来修饰?
IBOutlet的属性一般可以设为weak是因为它已经被view引用了,除非view被释放,否则IBOutlet的属性也不会被释放,另外IBOutlet属性的生命周期和view应该是一致的,所以IBOutlet属性一般设为weak。
1、#import和#include的区别,@class代表什么?
(1)#import指令是Object-C针对#include的改进版本,#import确保引用的文件只会被引用一次,这样你就不会陷入递归包含的问题中。
(2)@class:类的前置声明
2、浅拷贝和深拷贝区别是什么?
浅 拷贝就是成员数据之间的一一赋值:把值一一赋给要拷贝的值。但是可能会有这样的情况:对象还包含资源,这里的资源可以是堆资源,或者一个文件。当值拷贝 的时候,两个对象就有用共同的资源,同时对资源可以访问,这样就会出问题。深拷贝就是用来解决这样的问题的,它把资源也赋值一次,使对象拥有不同的资源, 但资源的内容是一样的。对于堆资源来说,就是在开辟一片堆内存,把原来的内容拷贝。
如果你拷贝的对象中引用了某个外部的内容(比如分配在堆上的数据),那么在拷贝这个对象的时候,让新旧两个对象指向同一个外部的内容,就是浅拷贝;如果在拷贝这个对象的时候为新对象制作了外部对象的独立拷贝,就是深拷贝 。
引用和指针的语义是相似的,引用是不可改变的指针,指针是可以改变的引用。其实都是实现了引用语义。
深拷贝和浅拷贝的区别是在对象状态中包含其它对象的引用的时候,当拷贝一个对象时,如果需要拷贝这个对象引用的对象,则是深拷贝,否则是浅拷贝。
COW语义是“深拷贝”与“推迟计算”的组合,仍然是深拷贝,而非浅拷贝,因为拷贝之后的两个对象的数据在逻辑上是不相关的,只是内容相同。
3、Objective-C中类别和类扩展的区别?
在iOS中,有一种机制可以使用户在没有远吗的情况下扩展类的功能,但不是通过继承,这就是类别。iOS中没有类似C++中可以定义私有方法和私有变量的关键字,要定义私有方法和私有变量,可以用类扩展来实现。
类别
类别在不需要继承的情况下可以扩展类的功能。但类别不能添加类的属性和私有变量。类别可以用来扩展Cocoa中类的方法,也可以用来扩展用户自己的类中的 方法。当我们查看系统头文件的时候能发现类似@interface NSMutableArray (NSExtendedMutableArray)的类定义,其实这就是类别的定义形式。
类别的定义和类的定义有相似之处,都是用关键字@interface和类名来定义,不同之处在于类别的定义是在类名之后不是类所继承的父类,而是用括号括 起来的类别名。@end之前的方法定义和类中方法的定义是一样的。不过,在类别中,不能定义属性。类别中的方法与原类中的方法的使用是完全一致的,没有任 何差别。所有NSString的子类也都能使用类这两个类别中的方法。
在使用类别的时候,类别中的方法命名特别重要。
如果类别中的方法名与原类中的方法名重名了,在苹果开发者文档中的描述是,当方法重名的时候,在运行的时候不知道会调用哪个方法。实际上,这个应该是有规 则可循的。我建了一个工程,给NSString增加了一个类别,里面重写了length和substringFromIndex方法。length方法是 NSString的方法,substringFromIndex是NSString的一个类别里的方法。当我调用者两个方法时,发现调用length的时 候返回的是系统的那个调用,而不是我自己实现。而当调用substringFromIndex时,调用的则是我实现的方法。于是我推断当系统类中的方法名 与自己定义的类别里的方法重名时,会调用系统的方法名,而当自定义类别中的方法名与系统类别中的方法重名时,会使用自定义类别中的方法的实现。为了验证这 一推断,我又继续增加了NSArray的类别来进行测试,测试结果正如我推断的一样。即使是这样,我们也不能确定这个结论就是正确的,还有待进一步的验 证。
4、Objective-C堆和栈的区别?
堆和栈的区别:
  一、堆栈空间分配区别:
  1、栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈;
  2、堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。
  二、堆栈缓存方式区别:
  1、栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放;
  2、堆是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。
  三、堆栈数据结构区别:
  堆(数据结构):堆可以被看成是一棵树,如:堆排序;
  栈(数据结构):一种先进后出的数据结构。
5、内存管理的几个原则是什么?
IOS的对象都继承于NSObject,   该对象有一个方法:retainCount ,内存引用计数。 引用计数在很多技术都用到: window下的COM组件,多线程的信号量,读写锁,思想都一样。
   (一般情况下: 后面会讨论例外情况)
    alloc      对象分配后引用计数为1
    retain    对象的引用计数+1
    copy      copy 一个对象变成新的对象(新内存地址) 引用计数为1 原来对象计数不变
    release            对象引用计数-1 如果为0释放内存
    autorelease      对象引用计数-1 如果为0不马上释放,结束最近一个pool时释放
6、NSMuatableArray *array = [NSMuatableArray array] 需要释放么?
不需要
7、@property本质是什么
@property (nonatomic, retain) NSString *name;
@synthesize name;
这种方式的本质是:
-(NSString *) name{
       return name;
}
 
-(void) setName:(NSStrng *) newName{
       if(name!=newName){
              [name release];
              name=[newName retain];
       }
}
对setName方法的解释:
(1)为何要加name!=newName的判断
          如果要是不加,传过来的参数如果是相同的,则newName会一直retain
(2)为何[name release]
          如果不release,直接name=[newName retain],则name原先所指向的内存则会泄露,因为没有释放
8、delegate用什么属性修饰,ARC下与MRC下有何不同,为什么?
1、delegate 之所以用weak来修饰,是防止循环引用,weak属性的变量是不为其所属 对象持有的,并且在该变量被销毁之后,此weak变量的值会自动被赋值为nil。而assign属性一般是对C基本数据类型成员变量的声明,当然也可以用 在对象类型成员变量上,只是其代表的意义只是单纯地拷贝所赋值变量的值。即如果对某assign成员变量B赋值某对象A的指针,则此B只是简单地保存此指 针的值,且并不持有对象A,也就意味着如果A被销毁,则B就指向了一个已经被销毁的对象,如果再对其发送消息会引发崩溃。
2、那关于delegate 既然用weak这么好用,用assign会出现野指针,为什么还会用呢?weak和strong属性是ARC才引入的,而在MRC情况下,只能使用 assign修饰了。weak之所以强大的地方,是当引用的对象被销毁时,它的值也会变为nil,所以推荐使用ARC。
9、NSString,NSArray,NSMutableArray分别用什么属性修饰,原因是什么?
@property(nonatomic,copy)NSString *string;
@property(nonatomic,copy)NSArray *array;
@property(nonatomic,strong)NSMutableArray *array;
10、block用什么属性修饰,为什么?
用copy修饰,保证线程安全,以及block的声明。
11、__block与__weak的区别是什么?
1.__block对象在block中是可以被修改、重新赋值的。
2.__block对象在block中不会被block强引用一次,从而不会出现循环引用问题。
使用了__weak修饰符的对象,作用等同于定义为weak的property。自然不会导致循环引用问题,因为当原对象没有任何强引用的时候,弱引用指针也会被设置为nil。
因此,__block和__weak修饰符的区别其实是挺明显的: 
1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。 
2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。 
3.__block对象可以在block中被重新赋值,__weak不可以。
12、assign与weak的区别是什么?
1.weak:(1).在ARC中,在有可能出现循环引用的时候,往往要通过让其中一端使用weak来解决,比如:delegate代理属性。 (2).如果自身已经对它进行一次强引用,没有必要再强引用一次时也会使用weak。比如:自定义IBOutlet控件属性一般也使用weak,当然也可 以使用strong。2.assign:用于基础数据类型(例如NSInteger等)和C数据类型(int, float, double, char)等,另外还有id类型。
不同点:(1).weak,表明该属性定义了一种“非拥有关系” (nonowning relationship)。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。(2).assign也可以修饰对象,但是用assign修饰 的对象在释放后,指针的地址还是存在的,也就是说指针并没有被置为nil,会造成众所周知的野指针异常。然而,assign修饰的基础数据类型(例如 NSInteger等)和C数据类型(int, float, double, char)等一般分配在栈空间上,栈空间的内存会由系统自动处理,当分配的栈空间的内存没有被指针指向时就会被销毁,所以不会造成野指针异常。 (3).weak比 assign多了一个功能就是当属性所指向的对象消失的时候(也就是内存引用计数为0)会自动赋值为 nil,这样再向 weak修饰的属性发送消息就不会导致野指针操作crash。
13、分别写一个setter方法和getter方法完成@property(nonatomic,retain)NSString *name和@property(nonatomic,copy)NSString *name和@property(nonatomic,assign)NSString *name;
(1)@property(nonatomic,assign)NSString *name
- (void)setName:(NSString *)name
{
    _name = name;
}
- (NSString *)name
{
    return _name;
}
(2)@property(nonatomic,retain)NSString *name
- (void)setName:(NSString *)name
{
    if(_name != name){
    [_name release];
    _name = [name retain];
    }
}
- (NSString *)name
{
    return [[_name retain] autorelease];
}
(3)@property(nonatomic,copy)NSString *name
- (void) setName:(NSString)name
{
    if(_name != name)
    {
        [_name release];
        _name = [name copy];
    }
}
- (NSString *)name
{
    return [[_name retain] autorelease];
}
14、@autoreleasepool {for (long i = 0; i < largeNumber; i++) {Person *per = [[Person alloc] init];[per autorelease];}}有什么内存问题,如何改正?
使用autorelease会将对方存放到最近的释放池中,不会使引用计数立即减一,当释放池销毁时才会被release,所以在这里直接用autorelease是错误的。
改正如下:
@autoreleasepool{
    for(long i = 0 ; i < largeNumber ; i++){
    //在自动释放池中在创建一个自动释放池,每次循环就会立即释放对象
    @autoreleasepool{
    Person *per = [[Person alloc] init];
    [per autorelease];
    }
    }
}
15、如何写一个单例?
+(SingLeton *)ShareIntance;
 static Singleton * intance = nil;
+(SingLeton *)ShareIntance{
    if(intance == nil){
    intance = [[Singleton alloc] init];
    }
    return instance;
}
16、post与get的区别?
GET请求的数据会附注在URL之后,POST是把请求的数据放在HTTP包的包体中。
GET提交的数据最多是1024字节,POST没有限制。
get请求数据外部可以看见请求内容,post外部无法看见,get只能传送数据,post可以传送数据也可以发送文件;

17、Http与tcp,udp的区别?
IP:网络层协议
TCP/UDP:传输层协议
TCP/UDP是HTTP传输层协议。
HTTP是利用TCP在两台电脑之间实现信息传输的协议
18、http都设置哪些header?
HTTP协议采用了Message-header/Message-body模型
http header 消息通常被分为4个部分:general  header(通用头), request header(请求头), response header(响应头), entity header(实体头)
19、http与https的区别?
HTTPS需要得到CA申请证书,一般免费证书很少,需要交费;
HTTP是超文本传输协议,信息是明文传送;
HTTPS是HTTP的安全传输通道,使用SSl加密传输协议;
HTTP的端口是80,HTTPS的端口是443;
HTTP连接很简是无状态的,HTTPS是由SSL+HTTP构成的,可以进行加密传输、身份认证的网络协议,要比HTTP安全。
20、网络七层协议(http,tcp/ip处于哪一层)?
7.应用层:拥有与其他客户端具有通信功能的程序,它是对应应用程序的通信服务的;HTTP位于该层。
6.表示层:定义数据格式以及加密;
5.会话层:定义了如何开始、控制、结束一个会话;
4.传输层:TCP位于该层。
3.网络层:IP位于该层。
2.数据链路层
1.物理层
其中高层7、6、5、4层定义了应用程序的功能,下面的3、2、1层主要是通过面向网络的端到端的数据流
21、常用多线程方式有哪些?
NSThread、NSOperation、GCD、PThread
22、NSOperation比GCD有哪些优点,如何处理线程依赖
NSOperation:
优点:不需要线程管理,数据同步的事情,可以把精力放在自己需要操作的事情上。
缺点:NSOperation是面向对象的。
GCD
优点:是苹果公司开发的一个多核开发编程解决方案,是替代NSThread、NSOperation的高效和强大的技术。
缺点:GCD是基于C语言的。
23、runloop与线程的关系
线程和runloop是一一对应的,线程刚创建的时候是没有runloop的,只有在获取的时候创建runloop,在线程结束的时候runloop就会被销毁。只能在线程内部获取runloop(主线程除外)。
24、runtime的理解
runtime简称运行时,就是系统在运行的时候的一些机制,其中最重要的是消息机制。OC函数调用成为消息发送,属于动态调用过程,在编译的时候不能决定真正调用哪个函数,只有在程序真正运行的时候才根据函数名找到对应的函数调用。
25、在实际项目中遇到过死锁么?如何处理死锁问题
死锁产生的原因:
1.互斥条件:一个资源每次只能被一个进程使用;
2.请求与保护条件:一个进程在因请求资源而阻塞的时候,对对已获得的资源保持不放。
3.不剥夺条件:进程已获得的资源,在没有使用完之前,不能强行剥夺。
4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
死锁的定义:在一组进程中,每个进程都占有不会释放的资源,但因相互申请被其他进程所占用不会释放资源,而处于一种永久等待的状态。
避免死锁:
1.按同一顺序访问对象(避免出现循环)。
2.避免事物中的产品交互(减少资源的持有时间,避免出现锁竞争)。
3.保持事物简短并处于一个批处理中(减少资源的持有时间)。
4.使用较低的隔离级别(使用较低的隔离级别(例如:已提交读)比使用较高的隔离级别(例如:可序列化)持有共享锁的时间更短,减少锁竞争)。
5.使用基于行版本的隔离级别。
6.使用绑定连接。
死锁的解决方案:
1.根据2中提供的sql,查看那个spid处于wait状态,然后用kill spid来干掉(即破坏死锁的第四个必要条件:循环等待);当然这只是一种临时解决方案,我们总不能在遇到死锁就在用户的生产环境上排查死锁、Kill sp,我们应该考虑如何去避免死锁。
2.使用SET LOCK_TIMEOUT timeout_period(单位为毫秒)来设定锁请求超时。默认情况下,数据库没有超时期限(timeout_period值为-1,可以用SELECT @@LOCK_TIMEOUT来查看该值,即无限期等待)。当请求锁超过timeout_period时,将返回错误。timeout_period值为0时表示根本不等待,一遇到锁就返回消息。设置锁请求超时,破环了死锁的第二个必要条件(请求与保持条件)。
3.SQL Server内部有一个锁监视器线程执行死锁检查,锁监视器对特定线程启动死锁搜索时,会标识线程正在等待 的资源;然后查找特定资源的所有者,并递归地继续执行对那些线程的死锁搜索,直到找到一个构成死锁条件的循环。检测到死锁后,数据库引擎 选择运行回滚,开 销最小的事务的会话作为死锁牺牲品,返回1205 错误,回滚死锁牺牲品的事务并释放该事务持有的所有锁,使其他线程的事务可以请求资源并继续运行。
26、runloop有几种模式,runloop接收几种输入源
runloop处理的事件的来源:输入源、定时源。
输入源:
1.基于端口的源;
2.自定义输入源;
3.Cocoa Perform Selector Sources;
模式:
1.Default:默认模式是用于大多数操作的一个默认模式。大多数时候,你应该使用这个模式来启动你的运行循环,并配置你的输入源。
2.Connection:
3.Modal:使用这种模式来识别用于模态面板的事件。
4.Event tracking:使用这种模式来限制鼠标拖动循环和其他类型的用户界面跟踪环路中的传入事件。
5.Common modes
27、如何处理滑动UI过程中,广告轮播图停止轮询问题,使用runloop的哪种模式
解决方法,一种方法是在另外的线程中处理定时器事件,可把Timer加入到NSOperation中在另一个线程中调度;还有一种方法时修改Timer运行的run loop模式,将其加入到UITrackingRunLoopMode模式或NSRunLoopCommonModes模式中。
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
28、有一个需求,需要将N个请求全部完成之后执行某个操作,该如何处理?
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
    
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_async(group, queue, ^{
        
        for (NSInteger i = 0; i < 10000; i++) {
            
            NSLog(@"%lu",i);
        }
        
    });
    
    dispatch_group_notify(group, queue, ^{
        
        NSLog(@"finished");
        
    });
29、weak会有性能开销么?使用什么代替?
有,strong
30、autorelease pool的原理是什么?
延迟调用release,系统只是把Object放入最近的autoreleasepool中,当autoreleasepool被释放,autorelease中的object都会被release。对于每个runloop系统都会隐式创建一个autoreleasepool,这样就构成了CallStack一样的栈式结构,当runloop结束时,当前栈顶的autoreleasepool就会被释放,autoreleasepool里面的object就会被release。
31、runloop的原理
1.(要让马儿跑)通过do_while死循环让程序持续运行,接收用户输入、调度处理事件时间。
2.(要让马儿少吃草)mach_msg(),让runloop在没事儿的时候进入trpy状态,节省CPU资源。
32、runloop与autoreleasepool的关系
每个runloop系统都会隐式创建一个autoreleasepool,在runloop结束时,autoreleasepool就会被释放。