IOS面试(基础问题)
1、简述OC中内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?readwrite,readonly,assign,retain,copy,nonatomic 、atomic、strong、weak属性的作用?
OC使用了一种叫做引用计数的机制来管理对象,如果对一个对象使用了alloc、[Mutable]copy,retain,那么你必须使用相应的realease或者autorelease。也可以理解为自己生成的对象,自己持有。非自己生成的对象,自己也能持有。不在需要自己持有的对象时释放。非自己持有的对象无法释放。生成并持有对象,持有对象,释放对象,废弃对象。readwrite(默认):可读可写,表示既有getter方法,也有setter方法。readonly:表示只有getter方法,没有setter方法。nonatomic:不考虑线程安全。atomic(默认):线程操作安全。strong(默认):ARC下和MRC下retain一样,weak(ARC下):和(MRC下)assign类似,区别是当weak指向的内存释放掉后自动置为nil,防止野指针。unsafe_unretained声明一个若引用,但不会自动置为nil,可能会出现野指针。线程安全下的setter和getter方法:-(NSString *)value{@synchronized(self){return [[_value retain] autorelease];}}-(void)setValue:(NSString *)aValue{@synchronized(self){[aValue retain];[_value release];_value = aValue;}}
2、类变量的@protected ,@private,@public,@package,声明各有什么含义?上面的几个声明表明的时类成员的作用域,
@private作用范围只能在自身类(外界既不可访问,又不能继承);@protected作用范围在自身类和子类,如果什么都不加修饰,默认是@protected(外界不可访问,但是可以继承);@public作用范围最大,可以在任何地方被访问(外界即可访问,又可以继承);@package作用范围在某个框架内
3、线程是什么?进程是什么?二者有什么区别和联系?线程是CPU独立运行和独立调度的基本单位(可以理解为一个进程中执行的代码片段),进程是资源分配的基本单位(进程是一块包含了某些资源的内存区域)。进程是线程的容器,真正完成代码执行的是线程,而进程则作为线程的执行环境。一个程序至少包含一个进程,一个进程至少包含一个线程,一个进程中的多个线程共享当前进程所拥有的资源。
4、谈谈你对多线程开发的理解?ios中有几种实现多线程的方法?
好处:1、使用线程可以把程序中占据时间长的任务放到后台去处理,如图片、视频的下载2、发挥多核处理器的优势,并发执行让系统运行的更快、更流畅,用户体验更好缺点:1、大量的线程降低代码的可读性,2、更多的线程需要更多的内存空间3、当多个线程对同一个资源出现争夺的时候要注意线程安全的问题。
iOS有三种多线程编程的技术:1、NSThread(两种创建方式)[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];NSThread *myThread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething:) object:nil];[myThread start];2、NSOperationQueueNSOperationQueue *oprationQueue = [[NSOperationQueue alloc] init];oprationQueue addOperationWithBlock:^{//这个block语句块在子线程中执行}http://alloc.sinaapp.com/wp/?p=2373、Grand Central Dispatch (GCD)dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 耗时的操作 dispatch_async(dispatch_get_main_queue(), ^{ // 更新界面 });});PS:不显示的创建线程的方法:用NSObject的类方法 performSelectorInBackground:withObject: 创建一个线程:[Obj performSelectorInBackground:@selector(doSomething)
5、线程同步和异步的区别?IOS中如何实现多线程的同步?
同步:一个线程要等待上一个线程执行完之后才能执行当前的线程,生活中的例子(上厕所)。异步:同时去做两件或者多件事。比如边听歌边看报。原子操作(atomic)、加锁(NSLock、NSRecursive、NSConditionLock)、@synchronized GCD串行队列,GCD当中的屏障,NSOperationQueue设置最大并发数为1
6、假设有一个字符串aabcad,请写一段程序,去掉字符串中不相邻的重复字符串,即上述字符串处理之后的输出结果为:aabcd.
本题的题意是以第一个出现的字母作为参照,只要之后出现相同的字母并且和第一个字母不相邻,那么就删除。为防止删除某些字符之后,把之前不相邻的重复字符串转化为相邻字符串,所以可以先用空格替换掉需要删除的字符,最后对数组里面的空格进行处理。
-(void)removeRepeat:(NSString *)aNum{
NSMutableArray *mArr = [[NSMutableArray alloc]initWithCapacity:10];
for (int i = 0;i < aNum.length;i++) { [mArr addObject:[aNum substringWithRange:NSMakeRange(i,1)]]; } NSLog(@"- %@", mArr); [self compareNum:mArr]; NSLog(@"%@",mArr);}//比较是否相等-(NSMutableArray *)compareNum:(NSMutableArray *)mArr{ int count = mArr.count;//重新定义了,count不会减一 for (int j = 0; j < count - 1; j++) { for (int i = j; i < count - 1-1-1; i++) { NSLog(@" %@ %@",[mArr objectAtIndex:j],[mArr objectAtIndex:i + 2]); NSString *a = [mArr objectAtIndex:j]; NSString *b = [mArr objectAtIndex:i+2]; if ([a isEqualToString:b]) { [mArr replaceObjectAtIndex:i + 2 withObject:@" "]; } } } return mArr;}
7、获取一台设备唯一标识的方法有哪些?MAC地址,udid,keychain,open udid,广告标识IDFA-identifierForIdentifier
8、iOS类是否可以多继承?如果没有,那可以用其他方法实现吗?简述实现过程。不可以,可以通过消息转发、delegate和protocol和类别来实现类似多继承。
9、堆和栈的区别?栈区(stack)--由编译器自动分配释放,存放函数的参数值、局部变量的值。堆区(heap)--一般由程序员分配释放。全局区(静态区)(static)--全局变量和静态变量。程序结束后由系统释放。 文字常量区--常量字符串存放在这里。程序结束后由系统释放。 程序代码区—存放函数体的二进制文件。栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢 出。堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。
10、iOS本地数据存储都有哪几种方式?iOS如何实现复杂对象的存储?
1、NSKeyedArchiver(归档)采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法。
2、NSUserDefaults:用来保存应用程序设置和属性、用户保存的数据。用户再次打开程序或开机后这些数据仍然存在。NSUserDefaults可以存储的数据类型包括:NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary。
3、Write写入方式:永久保存在磁盘中。
4、SQLite(FMDB、CoreData)
11、深拷贝和浅拷贝的理解?深拷贝拷贝的是内容,浅拷贝拷贝的是指针。深拷贝和浅拷贝最大的区别就是子类对象的地址是否改变,如果子类对象的地址改变那么就是深拷贝。
12、怎样实现一个singleton的类。static LOSingleton * shareInstance;+( LOSingleton *)sharedInstance{ @synchronized(self){//这个东西其实就是 一个加锁。如果self 其他线程访问,则会阻塞。这样做一般是用来对单例 进行一个死锁的保护
if (shareInstance == nil) {
shareInstance = [[super allocWithZone:NULL] init];
}
}return shareInstance;
}
//第二种方式
+ (LOSingleton *) sharedInstance{
static LOSingleton *sharedInstance = nil ;
static dispatch_once_t onceToken; // 锁
dispatch_once (& onceToken, ^ { // 最多调用一次
sharedInstance = [[self alloc] init];
});
return sharedInstance;}写一个标准宏MIN,这个宏输入两个参数并返回较小的一个?#define kMIN(X,Y) ((X) > (Y)) ? (Y) :(X)iphone os有没有垃圾回收机制?简单阐述一下OC内存管理。iphone os没有垃圾回收机制。垃圾回收机制用于在空闲时间以不定时的方式动态的回收无任何引用的对象占据的内存空间。简述应用程序按Home键进入后台时的生命周期,以及从后台回到前台时的生命周期?应用程序的状态:Not running 未运行,程序没启动Inactive 未激活,程序在前台运行,不过没接受到事件,没有事件处理的状态下通常处于这个状态。Active 激活 程序在前台并且接收到了事件Backgound 后台 程序在后台而且能执行代码,大多数程序进入这个状态后会在在这个状态上停留一会。Suspended 挂起 程序在后台不能执行代码。ViewController 的 alloc,loadView, viewDidLoad,viewWillAppear,viewDidUnload,dealloc、init分别是在什么时候调用的?在自定义ViewController的时候这几个函数里面应该做什么工作? alloc初始化当前的ViewControllerloadView:没有正在使用nib视图页面,子类将会创建自己的自定义视图层viewDidLoad:试图被加载后调用viewWillAppear:试图即将出现的时候调用viewDidUnload:当系统内存吃紧的时候会调用该方法,释放掉当前未在window中显示的试图和对应的控制器使用UITableView时候必须要实现的几种方法?2个。-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section; 这个方法返回每个分区的行数-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath)indexPath;这个方法返回我们调用的每一个单元格UIImage初始化一张图片有几种方法?简述各自的优缺点。1、从资源读取UIImage *image = [UIImage imageNamed:@”1.png”];2、从网络读取NSURL*url=[NSURL URLWithString:@"http://www.sinaimg.cn/qc/photo_auto/chezhan/2012/50/00/15/80046_950.jpg"];3.从手机本地读取//读取本地图片非resourceNSString *aPath3=[NSString stringWithFormat:@"%@/Documents/%@.jpg",NSHomeDirectory(),@"test"];UIImage *imgFromUrl3=[[UIImage alloc]initWithContentsOfFile:aPath3]; 4.从现有的context中获得图像//add ImageIO.framework and #importCGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
CGImageRef img= CGImageSourceCreateImageAtIndex(source,0,NULL);
CGContextRef ctx=UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
//transformCTM的2种方式
//CGContextConcatCTM(ctx, CGAffineTransformMakeScale(.2, -0.2));
//CGContextScaleCTM(ctx,1,-1);
//注意坐标要反下,用ctx来作为图片源
CGImageRef capture=CGBitmapContextCreateImage(ctx);
CGContextDrawImage(ctx, CGRectMake(160, 0, 160, 230), [image CGImage]);
CGContextDrawImage(ctx, CGRectMake(160, 230, 160, 230), img);
CGImageRef capture2=CGBitmapContextCreateImage(ctx);
5、用Quartz的CGImageSourceRef来读取图片
CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
CGImageRef img= CGImageSourceCreateImageAtIndex(source,0,NULL);
截取字符串”20 | http://www.baidu.com”中,”|”字符前面和后面的数据,分别输出它们。
NSString *string = @” 20 | http://www.baidu.com”;
[string componentsSeparatedByString:@”|”];
用obj-c写一个冒泡排序
NSMutableArray *array = [NSMutableArray arrayWithArray:@[@"3",@"1",@"10",@"5",@"2",@"7",@"12",@"4",@"8"]];
NSString *tmp;
for (int i = 0; i < array.count; i ++) {
for (int j = 0; j < array.count - 1 - i; j++) {
if ([[array objectAtIndex:j] integerValue] > [[array objectAtIndex:j + 1] integerValue]) {
tmp = [array objectAtIndex:j];
[array replaceObjectAtIndex:j withObject:[array objectAtIndex:j + 1]];
[array replaceObjectAtIndex:j + 1 withObject:tmp];
}
}
}
分析json、xml的区别?json、xml解析方式的底层是如何处理的?
json底层原理遍历字符串中的字符,最终根据各市规定的特助字符,比如{},[],:号等进行区分,{}是字典,[]表示的时数组,:号是字典的键和值的分水岭,最总是将json数据转化为字典。Xml两种解析方式,DOM和SAX,DOM需要读入整个XML文档(文档驱动),SAX是事件驱动的,并不需要读入整个文档,文档的读入过程也就是SAX的解析过程。
面向对象的三大特征,并作简单的介绍
封装、继承、多态。封装:是把客观事物封装成抽象的类,隐藏内部的实现,对外部提供接口。继承:可以使用现有类的所有功能,并且在无需重新编写原来的类的情况下对这些功能进行扩展。多态:不同的对象以自己的方式响应相同的的消息的能力叫做多态,或者说父类指针指向子类对象<如UITableView的,cellForRow方法,返回值类型是UITbaleViewCell,但是你返回的cell可以是你自定义的cell,在比如多个类里面都有同一个方法>
简述NotificationCenter、KVC、KVO、Delegate?并说明它们之间的区别?
Notification:观察者模式,controller向defaultNotificationCenter添加自己的 notification,其他类注册这个notification就可以收到通知,这些类可以在收到通知时做自己的操作(多观察者默认随机顺序发通知给 观察者们,而且每个观察者都要等当前的某个观察者的操作做完才能轮到他来操作,可以用NotificationQueue的方式安排观察者的反应顺序,也 可以在添加观察者中设定反映时间,取消观察需要在viewDidUnload 跟dealloc中都要注销)。
KVC键值编码,可以直接通过字符串的名字(key)来间接访问属性的机制,而不是通过调用getter和setter方法访问。
KVO:观测指定对象的属性,当指定对象的属性更改之后会通知相应的观察者。
delegate:一对一,delegate遵循某个协议并实现协议声明的方法。
属性的声明使用assign,防止出现循环引用的问题。
Objective-C有私有方法么?私有变量呢?如多没有的话,有没有什么代替的方法?
objective-c – 类里面的方法只有两种, 静态方法和实例方法.
@private来修饰私有变量
OC中所有的实例变量默认都是私有的,所有的实例方法默认都是公有的。
#import、#include和@class有什么区别
#include c语言中引入一个头文件,但是可能出现交叉编译
#import在OC中引入自己创建的头文件#import””或者系统框架#import<>。#import不会出现交叉编译
@class对一个类进行声明,告诉编译器有这个类,但是类的定义什么的都不知道
谈谈你对MVC的理解?为什么要用MVC?在Cocoa中MVC是怎么实现的?你还熟悉其他的OC设计模式或别的设计模式吗?
MVC是Model-VIew-Controller,就是模型-视图-控制器, MVC把软件系统分为三个部分:Model,View,Controller。在cocoa中,你的程序中的每一个object(对象)都将明显地仅属于这三部分中的一个,而完全不属于另外两个。MVC可以帮助确保帮助实现程序最大程度的可重用性。各MVC元素彼此独立运作,通过分开这些元素,可以构建可维护,可独立更新的程序组建。
单例模式,delegate设计模式,target-action设计模式
举出5个以上你所熟悉的ios sdk库有哪些和第三方库有哪些?
UIKit,MapKit,CoreLocation,CFNetWork,MessageUI,ImageIO,CoreData,
AFNetWorking,MKNetWorkKit,ASIHttpRequest,FMDB,ZXing,ZBar,SDWebImage
你做iphone开发时候,有哪些传值方式,view和view之间是如何传值的?
属性、delegate、KVO、blocks
描述上拉加载、下拉刷新的实现机制?
根据下拉或者上拉的距离来判断是否进行网络请求
什么是沙盒(sandbox)?沙盒包含哪些文件,描述每个文件的使用场景。如何获取这些文件的路径?如何获取应用程序包中文件的路径?
iOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都要保存在此,例如图像,图标,声音,映像,属性列表,文本文件等。
默认情况下,每个沙盒含有3个文件夹:Documents, Library 和 tmp。
Documents:苹果建议将程序中建立的或在程序中浏览到的文件数据保存在该目录下,iTunes备份和恢复的时候会包括此目录Library:存储程序的默认设置或其它状态信息;
Library/Caches:存放缓存文件,iTunes不会备份此目录,此目录下文件不会在应用退出删除
tmp:提供一个即时创建临时文件的地方。
iTunes在与iPhone同步时,备份所有的Documents和Library文件。iPhone在重启时,会丢弃所有的tmp文件。
介绍一下XMPP?有什么优缺点吗?
XMPP:基于XML的点对点的即时通讯协议。
XMPP 协议是公开的,XMPP 协议具有良好的扩展性,安全性
缺点是只能传输文本
谈谈对性能优化的看法,如何做?
从用户体验出发:1、程序logging不要太长、2、相同数据不做重复获取、3、昂贵资源要重用(cell、sqlite、date),4、良好的编程习惯和程序设计:选择正确的集合对象和算法来进行编程、选择适合的数据存储格式(plist、SQLite)、优化SQLite查询语句5、数据资源方面的优化(缓存和异步加载)
解决方案:
• 能够发现问题
• 利用log或工具分析问题原因
• 假设问题原因
改进代码和设计
以.mm为拓展名的文件里,可以包含的代码有哪些?c和obj-c如何混用
obj-c的编译器处理后缀为m的文件时,可以识别obj-c和c的代码, 处理mm文件可以识别obj-c,c,c++代码,但cpp文件必须只能用c/c++代码,而且cpp文件include的头文件中,也不能出现obj- c的代码,因为cpp只是cpp
2) 在mm文件中混用cpp直接使用即可,所以obj-c混cpp不是问题
3)在cpp中混用obj- c其实就是使用obj-c编写的模块是我们想要的。
如果模块以类实现,那么要按照cpp class的标准写类的定义,头文件中不能出现obj-c的东西,包括#import cocoa的。实现文件中,即类的实现代码中可以使用obj-c的东西,可以import,只是后缀是mm。
如果模块以函数实现,那么头文件要按 c的格式声明函数,实现文件中,c++函数内部可以用obj-c,但后缀还是mm或m