面试试题
//5 // NSLog(@"1"); // dispatch_sync(dispatch_get_main_queue(), ^{ // NSLog(@"2"); // }); // NSLog(@"3");// 结果是1 //6 // NSMutableArray * arrayy = [[NSMutableArray array]retain]; // NSString * string = [NSString stringWithFormat:@"test"]; // [string retain]; // [arrayy addObject:string]; // NSLog(@"%ld",(unsigned long)[string retainCount]); // [string retain]; // [string release]; // [string release]; // NSLog(@"%ld",(unsigned long)[string retainCount]); // [arrayy removeAllObjects]; // NSLog(@"%ld",(unsigned long)[string retainCount]); //结果是3.2.1 //8 // NSMutableArray * array2 = [array copy]; // [array2 addObject:@"abc"]; // NSLog(@"%@",array2);// 结果是nil //Son * son = [[Son alloc]init];// 结果是:Son,Son //4 //NSLog(@"%@",array);//nil
如何创建一个线程,要求可以一直工作,不会执行一次就结束。
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(threadFunc) object:nil]; [thread start]; } static bool over = NO; - (void)threadFunc { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; while (YES) { @synchronized(name){ name = @"Frank"; [NSThread sleepForTimeInterval:2]; if ([NSThread isMultiThreaded]) { NSLog(@"%@ isMultiThreaded",name); } if (over) { break; } } } [pool release]; }
16.结束一个线程:
a)break; b)[thread cancel]
17字符串地址
NSString *s = @"123";//0x100004248 NSString *s1 = @"123";//0x100004248 NSString * s2 = [NSString stringWithFormat:@"123"];//0x33323135 NSString *s3 = [[NSString alloc]initWithFormat:@"123"];//0x33323135 NSLog(@"s=%p--s1=%p--s2=%p---s3=%p",s,s1,s2,s3);
1.刷新UI为什么在主线程中执行
1、在子线程中是不能进行UI 更新的,而可以更新的结果只是一个幻像:因为子线程代码执行完毕了,又自动进入到了主线程,执行了子线程中的UI更新的函数栈,这中间的时间非常的短,就让大家误以为分线程可以更新UI。如果子线程一直在运行,则子线程中的UI更新的函数栈 主线程无法获知,即无法更新
2、只有极少数的UI能,因为开辟线程时会获取当前环境,如点击某个按钮,这个按钮响应的方法是开辟一个子线程,在子线程中对该按钮进行UI 更新是能及时的,如换标题,换背景图,但这没有任何意义
2.UIView 与UILayer 的关系
它真正的绘图部分,是由一个CALayer类来管理。UIView本身更像是一个CALayer的管理器,访问它的跟绘图和跟坐标有关的属性,例如frame,bounds等,实际上内部都是在访问它所包含的CALayer的相关属性。
3.autorelease 在什么时候释放
4、autorelease何时释放?
对于autorelease pool本身,会在如下两个条件发生时候被释放(详细信息请参见第5条)
1)、手动释放Autorelease pool
2)、Runloop结束后自动释放
对于autorelease pool内部的对象在引用计数的retain == 0的时候释放。release和autorelease pool 的 drain都会触发retain--事件。 |
5、autorelease释放的具体原理是什么?
要搞懂具体原理,则要先要搞清楚autorelease何时会创建。
我们的程序在main()调用的时候会自动调用一个autorelease,然后在每一个Runloop, 系统会隐式创建一个Autorelease pool,这样所有的release pool会构成一个象CallStack一样的一个栈式结构,在每一个Runloop结束时,当前栈顶的 Autorelease pool(main()里的autorelease)会被销毁,这样这个pool里的每个Object会被release。
可以把autorelease pool理解成一个类似父类与子类的关系,main()创建了父类,每个Runloop自动生成的或者开发者自定义的autorelease pool都会成为该父类的子类。当父类被释放的时候,没有被释放的子类也会被释放,这样所有子类中的对象也会收到release消息。
那什么是一个Runloop呢? 一个UI事件,Timer call, delegate call, 一个鼠标事件,键盘按下(MAC OSX),或者iphone上的触摸事件,异步http连接下后当接收完数据时,都会是一个新的Runloop。
一般来说,消息循环运行一次是毫秒级甚至微秒级的,因此autorelease的效率仍然是非常高的,确实是一个巧妙的设计。 |
4.使用蓝牙传送大批量数据
5.三个类别定义相同的方法,在调用的时候会是什么情况。
6.performSelector 在主线程中调用还是在子线程中调用,为什么
1、performSelector是运行时系统负责去找方法的,在编译时候不做任何校验;如果直接调用编译是会自动校验。如果imageDownloader:didFinishWithImage:image:不存在,那么直接调用 在编译时候就能够发现(借助Xcode可以写完就发现),但是使用performSelector的话一定是在运行时候才能发现(此时程序崩溃);Cocoa支持在运行时向某个类添加方法,即方法编译时不存在,但是运行时候存在,这时候必然需要使用performSelector去调用。所以有时候如果使用了performSelector,为了程序的健壮性,会使用检查方法
- (BOOL)respondsToSelector:(SEL)aSelector;