资源预览内容
第1页 / 共28页
第2页 / 共28页
第3页 / 共28页
第4页 / 共28页
第5页 / 共28页
第6页 / 共28页
第7页 / 共28页
第8页 / 共28页
第9页 / 共28页
第10页 / 共28页
亲,该文档总共28页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
2015年11月9 日 星期一1面试题1、以下代码有什么问题吗?如果没有问题的话,obj 、obj2 的引用计数分别是多少?如果有问题的话存在什么问题?Class *obj = Class allocinit;Class *obj2 = obj;obj hello;obj release; obj2 hello; obj2 release;答:上面的代码是存在问题的。当执行完第一行代码时,因为执行了alloc,obj的引用计数为1。第二行代码执行完之后,obj2只是和obj指向了同一块内存。第三行代码是执行了hello方法。第四行代码执行release消息之后,obj的引用计数减一,这时retainCount变为0.系统自动调用dealloc方法,对象被销毁。第五行代码执行时,obj2执行的内存已经被系统回收了,但还是调用了hello方法,出现了问题(野指针)。第六行执行时,obj2所指向的内存已经不存在,再次调用release消息,出现过度释放的问题,而且obj2 已经变成野指针了。Class *obj = Class allocinit;/obj引用计数加1Class *obj2 = obj;/obj,obj2指向同一块内存(对象)obj hello;obj release;/obj指向的内存(对象)被销毁obj2 hello;/错误,obj2指向的内存(对象)已经被销毁了obj2 release;/obj release之后,obj2是个野指针, 不应该再去调用方法.2015年11月9 日 星期一22、在实际开发的过程中,什么情况下需要创建自动释放池?下面代码中有没有什么问题?Person *p1=Person allocinit;autoreleasepool p1 autorelease;autoreleasepool p1 autorelease; 答:其实自动释放池存在的意义是为了延迟释放一些对象,延迟向对象发送release消息。在实际的开发中呢,有两种情况是需要手动创建自动释放池的。第一个就是在多线程中,因为子线程中可能会使用便利构造器等方法来创建对象,那么这些对象的释放只能放在自动释放池中,主线程其实已经添加过自动释放池,在main函数里面。第二个就是如果一段代码里面(比如for循环)大量使用便利构造器创建对象,也需要手动添加自动释放池。上述代码其实是存在问题的。当执行完第一行代码时,p1的引用计数是1.第二行是创建了一个autoreleasepool。第三行代码向p1 发送了autorelease消息,延迟release,即在出池的时候,把p1释放掉。第四行代码又创建了一个 autoreleasepool。第五行代码再次向p1发送了autorelease消息。当代码执行到第六行的“”时,第二个自动释放池结束,这时p1引用技术减1 ,p1所指向的内存(对象)的retainCount由1 变为0,内存被系统回收。代码执行到第七行时,最外层的自动释放池结束,再次向p1发送release消息,出现过度释放。autoreleasepool p1 autorelease;/此时p1被加入自动释放池1autoreleasepool p1 autorelease;/此时p1被加入自动释放池2/此处,自动释放池2结束, p1引用计数-1/此处,自动释放池1结束,但是向已经被释放的对象p1发送了消息3、ARC 下dealloc 方法存在的意义在于什么地方?举例说明一下具体的使用场景。答:其实在MRC中dealloc 方法存在的主要意义是为了释放自身的实例变量,移除观察者,停止timer,移除通知,代理置空等。ARC 下,系统会帮助我们释放该对象所包含的实例变量,但是有些对象还是需要们自己去释放的(比如Core Foundation框架下的一些对象),另外通知中观察者的移除,代理置空,停止timer等示例如下所示:2015年11月9 日 星期一3- (void)deallocNSNotificationCenter defaultCenter removeObserver:self;/移除通知观察者XMPPManager sharedManager removeFromDelegateQueue:self;/移除委托引用MyClass shareInstance doSomething /其他操作scrollView.delegate = nil;timer invalidate; 4、分别写出MRC中在assign、retain 、copy下属性name对应的setter方法的内部实现。答:assign下- (void) setName:(NSString*)name_name = name;retain下- (void) setName:(NSString*)nameif(_name != name)_name release;_name = name retain;copy下- (void) setName:(NSString*)nameif(_name != name)_name release;_name = name copy;5、在Category中本身不允许为已有的类添加新的属性或者成员变量,你有没有其他的方法可以在category中添加属性或者是成员变量?答:一种方法就是使用runtime.h中的objc_getAssociatedObject 和objc_setAssociatedObject来访问和生成关联对象。例如为NSObject 添加一个类目,分类中添加一个属性。代码如下所示:NSObject+Test.h文件#import interface NSObject (Test)property (nonatomic, strong) NSString *test;end2015年11月9 日 星期一4NSObject+Test.m文件#import “NSObject+Test.h#import static const void *instanceNameKey = &instanceNameKey;implementation NSObject (Test)dynamic test;- (NSString *)testreturn objc_getAssociatedObject(self, instanceNameKey);- (void)setTest:(NSString *)testobjc_setAssociatedObject(self, instanceNameKey, test, OBJC_ASSOCIATION_RETAIN_NONATOMIC);end6、synthesize 和dynamic有什么区别?(1)property有两个对应的词,一个是 synthesize,一个是dynamic 。如果synthesize 和dynamic都没写,那么默认的就是syntheszie var = _var;(2)synthesize的语义是如果你没有手动实现setter方法和 getter方法,那么编译器会自动为你加上这两个方法。(3)dynamic告诉编译器:属性的setter 与getter方法由用户自己实现,不自动生成。(当然对于 readonly的属性只需提供getter即可)。假如一个属性被声明为dynamic var,然后你没有提供setter方法和getter 方法,编译的时候没问题,但是当程序运行到instance.var = someVar,由于缺setter方法会导致程序崩溃;或者当运行到 someVar = instance.var时,由于缺getter方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。dynamic可用于在分类中添加属性(需要用到objc_getAssociatedObject和objc_setAssociatedObject函数)。7、你如何看待 iOS中的拷贝?答:在我看来,日常生活中,当我们用到”拷贝”这个词语的时候,不管怎样都会产生两份。一份是原来的,一份是新拷贝出来的。但是到目前为止,在iOS中我看到了三种拷贝方式:(1)伪拷贝:伪拷贝,顾名思义,就是假拷贝,没有拷贝出新的对象。这一点对于 NSString这种类簇来说比较常见,NSString本身是不可变字符串,内容不可能被修改,因此我们也2015年11月9 日 星期一5没有拷贝的必要,因为拷贝的目的是防止原件被修改,所以才拷贝出来一份,伪拷贝实际上是对象引用计数加了1 (相当于 retain或者strong的功效)。(2)浅拷贝:浅拷贝就是确实拷贝出来一份和原来内容一样的新对象。但是对于对象自带的属性是伪拷贝,两个对象的属性指向同一个内存。(3)深拷贝:深拷贝就是不仅仅拷贝出一份新对象,而且对象的属性也拷贝了一份。总的来说,如果在开发的过程中需要实现拷贝,那么需要接受NSCopying协议。实现copyWithZone:方法。浅拷贝、深拷贝的区别在于copyWithZone:方法的实现不同。8、父类实现深拷贝时,子类如何实现深拷贝 ?父类没有实现深拷贝时,子类如何实现深度拷贝?答:父类实现深拷贝之后,子类在重写的copyWithZone方法,先调用父类的copyWithZone方法,之后实现自己属性的拷贝。如果父类没有实现深拷贝,子类除了需要对自己的属性进行拷贝,还要对父类的属性进行拷贝。9、系统中有哪些单例类?在真实的开发中,单例的应用场景在于什么地方?答:系统为我们提供了很多单例类。例如:UIScreen、UIDevice、NSFileManager、NSNotificationCenter,NSUserDefaults,UIApplication 等等。而且在实际的开发中除了使用系统给我们提供的单例类之外,还会根据需求自己创建单例类。例如:1.数据库处理。对于数据的增删改查,可能在很多界面都会用到,那这个时候,可以定义一个针对数据处理的单例类。2.音乐播放。在做音乐播放类项目时,一般会在多个页面都可以播放音乐,这时也可以讲播放器定义为单例类,在多个界面使用。3.下载管理,当下载音乐或者视频时,应该定义一个单例类管理下载任务。4.登录类程序里面,还可以定义单例类保存用户资料,状态等。10、写出在多线程情况下的一个单例。2015年11月9 日 星期一6答:一般情况下,在开发中我们所写的单例都是伪单例。即只是保证了在调用某一方法时,所产生的对象只有一个,但是没有考虑其他的影响其引用计数的方法。例如retain、copy等。为了保证线程安全,单例的写法如下所示:方法一:static AccountManager *sharedAccountManagerInstance = nil; + (AccountManager *)sharedManager synchronized (self)if (sharedAccountManagerInstance = nil) sharedAccountManagerInstance = AccountManager alloc init;return sharedAccountManagerInstance; 方法二:static AccountManager *sharedAccountManagerInstance = nil; + (AccountManager *)sharedManager static dispatch_once_t onceToke
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号