objective-c笔试题

来源:互联网 发布:淘宝起名靠谱吗 编辑:程序博客网 时间:2024/05/22 15:44

原文链接:http://www.cocoachina.com/bbs/simple/?t37328.html

1.ObjC中,与alloc语义相反的方法是dealloc还是release?与retain语义相反的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?答:alloc与dealloc语意相反,alloc是创建变量,dealloc是释放变量。 retain 对应release,retain 保留一个对象。调用之后,变量的计数加1。或许不是很明显,在这有例为证:                   
- (void) setName : (NSString*) name {
     [name retain];
     [myname release];
     myname = name;

}
我们来解释一下:设想,用户在调用这个函数的时候,他注意了内存的管理,所以他小心的写了如下代码:
NSString * newname = [[NSString alloc] initWithString: @"John"];
[aClass setName: newname];
[newname release];
我们来看一看newname的计数是怎么变化的。首先,它被alloc,count = 1; 然后,在setName中,它被retain, count = 2; 最后,用户自己释放newname,count = 1,myname指向了newname。这也解释了为什么需要调用[myname release]。我们需要在给myname赋新值的时候,释放掉以前老的变量。retain 之后直接dealloc对象计数器没有释放。alloc 需要与release配对使用,因为alloc 这个函数调用之后,变量的计数加1。所以在调用alloc 之后,一定要调用对应的release。另外,在release一个变量之后,他的值仍然有效,所以最好是后面紧接着再var = nil。

2.在一个对象的方法里面:
self.name = “object”;

name =”object”
有什么不同吗? 
答:self.name = "object"会调用对象的setName()方法,name = "object"会直接把object赋值给当前对象的name 属性。

3.这段代码有什么问题吗:
@implementation Person
- (void)setAge:(int)newAge {
self.age = newAge;
}
@end
答:会进入死循环。


4.什么是retain count?
答:引用计数(ref count或者retain count)。对象的内部保存一个数字,表示被引用的次数。例如,某个对象被两个指针所指向(引用)那么它的retain count2。需要销毁对 象的时候,不直接调用dealloc,而是调用releaserelease会 让retain count1,只有retain count等于0,系统才会调用dealloc真正销毁这个对象。

5.以下每行代码执行后,person对象的retain count分别是多少
Person *person = [[Person alloc] init]; count 1
[person retain]; count 2
[person release];count 1
[person release];count = 1;

6.为什么很多内置类如UITableViewController的delegate属性都是assign而不是retain的?
答:会引起循环引用。

7.定义属性时,什么情况使用copy,assign,和retain 。
答:assign用于简单数据类型,如NSInteger,double,bool,retain 和copy用户对象,copy用于当 a指向一个对象,b也想指向同样的对象的时候,如果用assign,a如果释放,再调用b会crash,如果用copy 的方式,a和b各自有自己的内存,就可以解决这个问题。retain 会使计数器加一,也可以解决assign的问题。另外:atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。加了atomic,setter函数会变成下面这样:
    if (property != newValue) {
       
        [property release];
       
        property = [newValue retain];
      
    }  
8.的对象是在什么时候被release的?

答:autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当前的Autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用Release。对于每一个Runloop, 系统会隐式创建一个Autorelease pool,这样所有的release pool会构成一个象CallStack一样的一个栈式结构,在每一个Runloop结束时,当前栈顶的Autorelease pool会被销毁,这样这个pool里的每个Object(就是autorelease的对象)会被release。那什么是一个Runloop呢? 一个UI事件,Timer call, delegate call, 都会是一个新的Runloop。那什么是一个Runloop呢? 一个UI事件,Timer call, delegate call, 都会是一个新的Runloop。


9.这段代码有什么问题,如何修改
for (int i = 0; i < someLargeNumber; i++)
{
NSString *string = @”Abc”;
string = [string lowercaseString];
string = [string stringByAppendingString:@"xyz"];
NSLog(@“%@”, string);
}

答:会内存泄露,
for(int i = 0; i<1000;i++){
NSAutoreleasePool * pool1 = [[NSAutoreleasePool alloc] init];
NSString *string = @"Abc";
string = [string lowercaseString];
string = [string stringByAppendingString:@"xyz"];
NSLog(@"%@",string);
[pool1 drain];
}

10.autorelease和垃圾回收机制(gc)有什么关系?

第一个是内存不够后自动释放,也就是杀后台程序;gc是杀那些优先级很低的程序,包括已经关掉有残留的。

11.IPhone OS有没有垃圾回收(gc)?

没有

12.什么是Notification?

答:观察者模式,controller向defaultNotificationCenter添加自己的notification,其他类注册这个notification就可以收到通知,这些类可以在收到通知时做自己的操作(多观察者默认随机顺序发通知给观察者们,而且每个观察者都要等当前的某个观察者的操作做完才能轮到他来操作,可以用NotificationQueue的方式安排观察者的反应顺序,也可以在添加观察者中设定反映时间,取消观察需要在viewDidUnload 跟dealloc中都要注销)。参考链接:http://useyourloaf.com/blog/2010/6/6/delegation-or-notification.html

13.什么时候用delegate,什么时候用Notification?

答:delegate针对one-to-one关系,并且reciever可以返回值给sender,notification 可以针对one-to-one/many/none,reciever无法返回值给sender.所以,delegate用于sender希望接受到reciever的某个功能反馈值,notification用于通知多个object某个事件。

14.什么是KVC和KVO?

答:KVC(Key-Value-Coding)内部的实现:一个对象在调用setValue的时候,(1)首先根据方法名找到运行方法的时候所需要的环境参数。(2)他会从自己isa指针结合环境参数,找到具体的方法实现的接口。(3)再直接查找得来的具体的方法实现。KVO(Key-Value-Observing):当观察者为一个对象的属性进行了注册,被观察对象的isa指针被修改的时候,isa指针就会指向一个中间类,而不是真实的类。所以isa指针其实不需要指向实例对象真实的类。所以我们的程序最好不要依赖于isa指针。在调用类的方法的时候,最好要明确对象实例的类名。

15.Notification和KVO有什么不同?

答:Delegate是一种回掉函数,更多的用在一对一的场合,可参考 iphone:delegate机制 ;Notification 用得较少,使用Notification Center,类似广播方式,所以更适合一对多的通信;KVO,key-Value-Observing,观察者模式,适用于侦听另一对象的属性的变化。

16.KVO在ObjC中是怎么实现的?

答:

1.核心内容

(1)注册监听

【被监听对象 addObserver:监听者 forKeyPath:被监听对象的属性 options:监视内容(新值或旧值)context:额外信息】;

(2)监听者实现的方法

-(void)observerValueForKeyPath:(NSString*)keyPath

                                                   ofObject:(id)object (被监听对象) 

                                                     change:(NSdictionary*)change

                                                     context:(void*)context

{

        NSLog(@“keyPath:%@ object:%@change:%@ context:%@”,keyPath,object,    change,context);

}

(3)监听触发条件

//被监听对象 key = newValue;

//自动调用监听方法


2.举例


-(void)observerValueForKeyPath:(NSString*)keyPath 

                                                  ofObject:(id)object 

                                                    change:(NSDictionary*)change

                                                    context:(void*)context

{

       NSLog:(@"keyPath:%@ object:%@ change:%@context:%@ ",keyPath,object,change,context);

}


Student *stu = 【【Student alloc】init】;

stu.name = @"张三";

【stu addObserver:self 

              forKeyPath :@"name"

                      options:NSKeyValueObservingOptionNew 

                     context:nil】;

stu.name = @"李四";

stu.name = @"王五";

【stu release】;



17.ViewController 的 loadView, viewDidLoad, viewDidUnload 分别是在什么时候调用的?在自定义ViewController的时候这几个函数里面应该做什么工作?三个方法的关系?

答:(1)loadView:每次访问UIViewController的view(比如controller.view、self.view)而且view为nil,loadView方法就会被调用

viewDidLoad:不管你是通过xib文件还是重写loadView创建UIViewController的view,在view创建完毕后,即view 从nib文件初始化时,会调用viewDidLoad方法。

viewDidUnload:iOS设备的内存是极其有限的,如果应用程序占用的内存过多的话,系统就会对应用程序发出内存警告。UIViewController就会收到didReceiveMemoryWarning消息。didReceiveMemoryWarning方法的默认实现是:如果当前UIViewController的view不在应用程序的视图层次结构(View Hierarchy)中,即view的superview为nil的时候,就会将view释放,并且调用viewDidUnload方法。

(2)loadViewloadView方法是用来负责创建UIViewController的view。

viewDidLoad:一般我们会在这里做界面上的初始化操作,比如往view中添加一些子视图、从数据库或者网络加载模型数据装配到子视图中。

viewDidUnload上面说到,发出内存警告且view被释放的时候就会调用viewDidUnload方法,所以一般在释放资源,主要是释放界面元素相关的资源,将相关的实例都赋值为nil。

(3)A.第一次访问UIViewController的view时,view为nil,然后就会调用loadView方法创建view。

B.view创建完毕后会调用viewDidLoad方法进行界面元素的初始化。

C.当内存警告时,系统可能会释放UIViewController的view,将view赋值为nil,并且调用viewDidUnload方法。

D.当再次访问UIViewController的view时,view已经在3中被赋值为nil,所以又会调用loadView方法重新创建view。

E.view被重新创建完毕后,还是会调用viewDidLoad方法进行界面元素的初始化。

18.ViewController 的 didReceiveMemoryWarning 是在什么时候被调用的?默认的操作是什么?

答:应用程序占用的内存过多的话,系统就会对应用程序发出内存警告。

19.dealloc也是用来释放资源的,那跟viewDidUnload有什么关系?

当发出内存警告调用viewDidUnload方法时,只是释放了view,并没有释放UIViewController,所以并不会调用dealloc方法。即viewDidUnload和dealloc方法并没有任何关系,dealloc方法只会在UIViewController被释放的时候调用。


原创粉丝点击