标题
1、简述OC中内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?readwrite,readonly,assign,retain,copy,nonatomic 、atomic、strong、weak属性的作用?
答:引入计数的增加和减少应该相等,当引用计数降为0的时候,不应该再使用这块内存。 凡是使用了alloc、retain、或者copy、new、mutableCopy让内存的引用计数增加了,就需要使用release或者autorelease让内存的引入计数减少。在一段代码中,增加和减少的次数要相等。
OC的内存管理分为垃圾回收和引用计数, 垃圾回收用于MAC, 引用计数用于IOS
如果拥有一个对象的所有权,那么需要在该对象不再被使用的时候,释放其所有权,如果一个对象不归我们拥有,就不要对其做释放所有权的操作。
与retain配对使用的方法是release,alloc配对使用的方法是dealloc;
因为retain是获得所有权,release则是释放所有权;
alloc开辟空间,dealloc是用来销毁空间。
readwrite 告诉编译器,同时声明setter和getter方法,即不但可读而且可写。
readonly 只声明getter方法,即只读。
assign 不会使引用计数加1,setter、getter的内部实现是直接赋值。
retain setter、getter方法的内部会做内存优化。(先release,后retain)
@property(nonatomic, retain)NSString *name;
- (void)setName:(NSString *)name {
if (_name != name) {
[_name release];
_name = [name retain];
}
}
- (NSString *)name {
return [[_name retain] autorelease];
}
copy copy和retain十分类似,内部会做相同的内存优化。
nonatomic 非原子性访问,多线程并发会提高性能。
atomic 原子性访问,setter、getter方法在多线程访问下是绝对安全的(加锁解锁操作),但性能没有nonatomic高。
strong 打开ARC时候才会使用,相当于retain
weak 打开ARC时才会使用,相当于assign,可以把相应的指针变量置为nil(弱引用)
自动释放池:三种创建释放池的地方:1.UI时间 2.NSTIME CALL 3. Protocol Call
2、变量的@protected ,@private,@public,@package,声明各有什么含义?
答:OC对存取权限的设定,也是变量的作用域。
@protected 受保护的,该类和所有的子类的方法内可以访问这样的变量,这是默认的。
@private 私有的,该类中得方法可以访问这样的方法,子类不可以。
@public 除了自己和子类的方法中,也可以被其他类或者其他模块中的方法所访问,开放性最大。
@package 本包内可以使用,跨包不可以。
3、线程是什么?进程是什么?二者有什么区别和联系?
答:线程,有时候称为轻量级进程,是被系统独立调度和CPU的基本运行单位;进程是操作系统中可以并行工作的基本单位。一个应用程序里至少有一个进程,一个进程里至少要有一个线程。
4、谈谈你对多线程开发的理解,iOS中有几种实现多线程的方法?
答:在一个进程中有多个线程,每个线程有自己单独的任务。
多线程的有点是效率快,缺点不安全,耗费资源。
三种:
1、使用@synchronized(self)
2、使用GCD。
3、使用NSOperationQueue
5、线程同步和异步的区别?IOS中如何实现多线程的同步?
同步:在当前线程中执行
异步:在另一条线程中执行
串行和并行
串行:让任务一个接着一个地执行,一个任务结束后再去执行下一个任务
并行:可以让多个任务并发执行, 并发执行就是同时去执行 并发功能只有在异步
怎么实现线程同步,利用线程锁:NSLock *mLock//互斥 NSConditionLock //条件 NSRecursiveLock//循环锁
答: 一个进程启动多个不相干线程,他们相互关系为异步。而同步的话指的是多线程同时操作一个数据,这个时候需要对数据添加保护,这个保护就是线程的同步。
使用GCD中得串行队列来解释多线程的同步,也就是队列中的任务为串行,他们各自对相邻的任务有依赖性,如果任务1还不完成,任务2就不会开始。
6、假设有一个字符串aabcad,请写一段程序,去掉字符串中不相邻的重复字符串,即上述字符串处理之后的输出结果为:aabcd
NSMutableString *string = [NSMutableString stringWithFormat:@"aaabababb"];
NSMutableArray *array = [NSMutableArray array];
for (int i = 0; i < string.length; i++) {
//[array addObject:[string characterAtIndex:i]];
[array addObject:[NSString stringWithFormat:@"%c", [string characterAtIndex:i]]];
}
NSLog(@"%@", array);
NSMutableArray *number = [NSMutableArray array];
for (int i = 0; i < array.count; i++) {
for (int j = i + 1; j < array.count - 1; j++) {
if ([array[i] isEqualToString:array[i + 1]] && (([array[i] isEqualToString:array[j]] && ![array[j] isEqualToString:array[j - 1]]) && ([array[i] isEqualToString:array[j]] && ![array[j] isEqualToString:array[j + 1]]))) {
//[array removeObjectAtIndex:j];
NSLog(@"----%d", j);
}
if (![array[i] isEqualToString:array[i + 1]] &&(([array[i] isEqualToString:array[j]] && [array[j] isEqualToString:array[j - 1]] )|| ([array[j] isEqualToString:array[i]] && [array[j] isEqualToString:array[j + 1]]))) {
//[array removeObjectAtIndex:i];
NSLog(@"%d", i);
}
}
}
NSLog(@"%@", array);
PS:解决最后一位无法判断的情况,多加一个判断,直接判断数组最后一位是否满足条件,是则移除.
7、获取一台设备唯一标识的方法有哪些?
答:1.UDID (Unique Device Identifier)
2.UUID (Universally Unique Identifier iOS 5 后来被 Apple 禁止掉)
3.MAC ADDRESS (iOS 6后来被 Apple 禁止掉)
4.OPEN UDID (模仿UDID40位的字符串)
5.广告标识符(ASIdentifierManager的advertisingIdentifier属性作为替代)
6.Vindor标示符(IDFV - identifierForVendor)
7.推送token + bundle_id
8、iOS类是否可以多继承?如果没有,那可以用其他方法实现吗?简述实现过程。
答:不可以多继承.不可以,Objective-c只支持单继承,如果要实现多继承,可以通过类别和协议的方式来实现,cocoa中所有的类都是NSObject的子类,多继承在这里是用protocol 委托代理来实现的.
9、堆和栈的区别?
答:堆需要用户手动进行释放内存,而栈是在程序运行结束之后自动释放内存;
对于栈来讲,是由编译器自动管理,无需我们手动控制;对于堆来说,释放工作由程序员控制,容易产生memory leak;
1、栈区(stack)— 程序运行时由编译器自动分配,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。程序结束时由编译器自动释放。(分配效率最高, 进栈出栈)
2、堆区(heap) — 在内存开辟另一块存储区域。一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。用malloc, calloc, realloc等分配内存的函数分配得到的就是在堆上(会产生内存碎片)
3、全局区(静态区)(static)—编译器编译时即分配内存。全局变量和静态变量的存储是放在一块的。对于C语言初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。而C++则没有这个区别 - 程序结束后由系统释放
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码.
参考网址:http://blog.csdn.net/wealoong/article/details/8686353
10、iOS本地数据存储都有哪种方式?
1.NSKeyedArchiver:采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法。前一个方法告诉系统怎么对对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码。例如对Possession对象归档保存。
2.NSUserDefaults:用来保存应用程序设置和属性、用户保存的数据。用户再次打开程序或开机后这些数据仍然存在。NSUserDefaults可以存储的数据类型包括:NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary。如果要存储其他类型,则需要转换为前面的类型,才能用NSUserDefaults存储。
3. Write写入方式:永久保存在磁盘中。
4. SQLite:采用SQLite数据库来存储数据。SQLite作为一中小型数据库,应用ios中,跟前三种保存方式相比,相对比较复杂一些。
5. coredata CoreData数据持久化是对SQLite的一个升级,它是ios集成的,在说Core Data之前,我们先说说在CoreData中使用的几个类。
参考文档:http://www.apkbus.com/android-830-1.html
11、iOS动态类型和动态绑定
iOS的动态性来自三个方面:动态类型、动态绑定、动态载入、SEL类型
1、动态类型<弱类型>(id):在代码的运行阶段判断代码的类型,使用id类型可以让应用在“运行时”使用任何类型来替换。动态类型让程序更加灵活,但是会使数据的统一性降低和代码的可读性。我们常用静态类型<强类型>(如NSString),使用静态类型编译器可以完全分析你的代码,这让代码的性能和可预知性更高。2、动态绑定:让代码在运行时判断需要调用什么方法,而不是在编译时。 动态类型和动态绑定使得选择哪个接收者已经调用什么方法都放到运行时去完成。
3、动态载入:应用程序可以根据需要加载可执行代码以及资源,而不是在启动时就加载所有资源。
4、SEL类型 iOS在编译的时候会根据方法的名字(包括参数序列),生成一个用来区分这个方法的唯一的ID,这个ID是SEL类型的,SEL的本质就是类方法的编号[函数地址]。(类似C语言里面的函数指针,但是OC的类不能直接使用函数指针,这样只能做一个@selector语法来取。注意:@selector是查找当前类(含子类)的方法。)
参考文档:http://blog.csdn.net/tskyfree/article/details/7984887
12、深拷贝和浅拷贝的理解
深拷贝和浅拷贝的定义可以简单理解成:如果一个类拥有资源(堆,或者是其它系统资源),当这个类的对象发生复制过程的时候,这个过程就可以叫做深拷贝,反之对象存在资源但复制过程并未复制资源的情况视为浅拷贝。
浅拷贝资源后在释放资源的时候会产生资源归属不清的情况导致程序运行出错,这点尤其需要注意!
浅层复制:只复制指向对象的指针,而不复制引用对象本身。
深层复制:复制引用对象本身。
意思就是说我有个A对象,复制一份后得到A_copy对象后,对于浅复制来说,A和A_copy指向的是同一个内存资源,复制的只不过是是一个指针,对象本身资源
还是只有一份,那如果我们对A_copy执行了修改操作,那么发现A引用的对象同样被修改,这其实违背了我们复制拷贝的一个思想。深复制就好理解了,内存中存在了
两份独立对象本身。
用网上一哥们通俗的话将就是:
浅复制好比你和你的影子,你完蛋,你的影子也完蛋
深复制好比你和你的克隆人,你完蛋,你的克隆人还活着。
参考文档:http://blog.sina.com.cn/s/blog_7b9d64af01019k6n.html
13、怎样实现一个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;
}
14、什么是安全释放?
把对象指针置为nil,再对其释放
15、什么是RunLoop?
一个RunLoop就是一个事件处理的循环,用来不停的调度工作以及处理输入时间。使用runloop的目的是让你的线程在有工作的时候忙于工作,而没工作的时候处于休眠状态。runloop的设计是为了减少cpu无谓的空转。
使用runloop情况:1.子线程里使用nstimer 2.在子线程里做一些循环的任务 ,下载图片, 下载视频3.创建接口
16、什么是序列化和反序列化, 可以用来做什么? 如何在OC中实现复杂对象的存储?
序列化是将对象状态转换为可保持或传输的格式的过程,在序列化过程中,对象的公共字段和私有字段以及类的名称(包括包含该类的程序集)都被转换为字节流,然后写入数据流。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。
要实现对象的序列化,首先要保证该对象可以序列化。而且,序列化只是将对象的属性进行有效的保存,对于对象的一些方法则无法实现序列化的。实现一个类可序列化的最简便的方法就是增加Serializable属性标记类。注意序列化的类必须为Public,否则不能够被序列化。
参考文献:http://blog.csdn.net/tt7380/article/details/7018804
复杂对象的存储方式:利用归档,遵守NSCoding协议,来实现复杂对象的存储, 实现该协议后就可以对其进行打包或者解包,然后转换成NSData.
17、写一个标准宏MIN, 这个宏输入两个参数并返回较小的一个
写宏的时候应该注意函数宏后面的参数要都用括号单独括起来, 函数名大写
#define MinValue(A, B) ({_typeof_(A) _a = (A); _typeof_(B)_b = (B); _a < _b ? _a : _b;})
18、iphone os有没有垃圾回收机制?简单阐述一下OC内存管理?
没有垃圾回收机制
19、简述应用程序按Home键进入后台时的生命周期,以及从后台回到前台时的生命周期?
Noruning 未运行,程序没启动, 或者应用正在运行但是途中被系统停止
Inactive 未激活,当前应用正在前台运行,但是并不接收事件(当前或许正在执行其它代码)。一般每当应用要从一个状态切换到另一个不同的状态时,中途过渡会短暂停留在此状态。唯一在此状态停留时间比较长的情况是:当用户锁屏时,或者系统提示用户去响应某些(诸如电话来电、有未读短信等)事件的时候。
Active 激活, 当前应用正在前台运行,并且接收事件。这是应用正在前台运行时所处的正常状态。
Backgound 后台 应用处在后台,并且还在执行代码。大多数将 要进入Suspended状态的应用,会先短暂进入此状态。然而,对于请求需要额外的执行时间的应用,会在此状态保持更长一段时间。另外,如果一个应用要求启动时直接进入后台运行,这样的应用会直接从Notrunning状态进入Background状态,中途不会经过Inactive状态。比如没有界面的应用。注此处并不特指没有界面的应用,其实也可以是有界面的应用,只是如果要直接进入background状态的话,该应用界面不会被显示。
Suspended 应用处在后台,并且已停止执行代码。系统自动的将应用移入此状态,且在此举之前不会对应用做任何通知。当处在此状态时,应用依然驻留内存但不执行任何程序代码。当系统发生低内存告警时,系统将会将处 于Suspended状态的应用清除出内存以为正在前台运行的应用提供足够的内存。
//告诉代理进程启动但还没进入状态保存
- (BOOL)application:(UIApplication*)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
// 告诉代理启动基本完成程序准备开始运行
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
// 当应用程序将要入非活动状态执行,在此期间,应用程序不接收消息或事件,比如来电话了
-(void)applicationWillResignActive:(UIApplication *)application
// 当应用程序入活动状态执行,这个刚好跟上面那个方法相反
-(void)applicationDidBecomeActive:(UIApplication *)application
// 当程序被推送到后台的时候调用。所以要设置后台继续运行,则在这个函数里面设置即可
-(void)applicationDidEnterBackground:(UIApplication *)application
//当程序从后台将要重新回到前台时候调用,这个刚好跟上面的那个方法相反。
- (void)applicationWillEnterForeground:(UIApplication*)application
//当程序将要退出是被调用,通常是用来保存数据和一些退出前的清理工作。这个需要要设置UIApplicationExitsOnSuspend的键值。
-(void)applicationWillTerminate:(UIApplication *)application
//当程序载入后执行
-(void)applicationDidFinishLaunching:(UIApplication*)application
20、ViewController 的 alloc,loadView, viewDidLoad,viewWillAppear,viewDidUnload,dealloc、init分别是在什么时候调用的?在自定义ViewController的时候这几个函数里面应该做什么工作?
alloc进行申请内存的操作
init是初始化的调用,做初始化操作
dealloc销毁的视图的时候调用,进行销毁视图的操作
loadView 视图加载时调用(执行self.view的getter方法)
ViewDidLoad 视图已经加载的时候调用
ViewWillAppear视图将要出现的时候调用
ViewDidAppear视图已经出现
ViewDidUnload视图开始加载,但是没有加载成功(self.view=nil, 6.0之后被干掉了,替换成didReceiveMemoryWarning)
ViewDidLoad视图已经加载的时候调用(网络数据之类的,刷新表之类)(添加通知)
21、描述应用程序的启动顺序
1、 应用程序入口main函数创建UIApplication实例和UIApplication代理实例
2、UIApplication代理实例中重启启动方法,设置RootViewController
2、在RootViewController中添加控件,实现对应的程序界面
22、为什么很多内置类 如 UITableViewController的delegate属性都是assign 而不是retain 请举例说明
答案:防止循环引用
所有的引用计数系统,都存在循环引用的问题。例如下面的引用关系:对象a创建并引用了对象b,对象b创建并引用了对象c,对象c创建并引用了对象b.这时候b和c的引用计数分别是2和1。当a不再使用b,调用release释放对b的所有权,因为c还引用了b,所以b的引用计数为1,b不会被释放。b不释放,c的引用计数就是1,c也不会被释放。从此,b和c永远留在内存中。
这种情况,必须打断循环引用,通过其他规则来维护引用关系。比如,我们常见的delegate往往是assign方式的属性而不是retain方式的属性,赋值不会增加引用计数,就是为了防止delegation两端产生不必要的循环引用。如果一个UITableViewController对象a通过retain获取了UITableView对象b的所有权,这个UITableView对象b的delegate又是a,如果这个delegate是retain方式的,那基本上就没有机会释放这两个对象了。
23、UITableView必须要实现的方法
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
24、写一个便利构造器
+(id)modelWithDictionary(NSDictionary*)dict{
return [[[self class] alloc]initWithDictionary:dict];
}
25、UIImage初始化一张图片有几张方法?简述各自的优缺点
当图片比较大时使用initWithContentsOfFile
当图片比较小时使用[UIImage imageWith];
imageNamed:系统会先检查系统缓存中是否有该名字的Image,如果有的话,则直接返回,如果没有,则先加载图像到缓存,然后再返回。
initWithContentsOfFile:系统不会检查系统缓存,而直接从文件系统中加载并返回。
imageWithCGImage:scale:orientation 当scale=1的时候图像为原始大小,orientation制定绘制图像的方向
//
一、imageNamed——方法介绍imageNamed:是UIImage的一个类方法,它做的事情比我们看到的要稍微多一些。它的加载流程如下:1、系统回去检查系统缓存中是否存在该名字的图像,如果存在则直接返回。2、如果系统缓存中不存在该名字的图像,则会先加载到缓存中,在返回该对象。从蓝鸥的角度出发,观察上面的操作我们发现系统会缓存我们使用imageNamed:方法加载的图像时候,系统会自动帮我们缓存。这种机制适合于那种频繁用到界面贴图累的加载,但如果我们需要短时间内频繁的加载一些一次性的图像的话,最好不要使用这种方法。 。
二、imageWithContentsOfFile:和initWithContentsOfFile:方法——介绍这两个方法跟前一个方法一样都是完成从文件加载图像的功能。但是不会经过系统缓存,直接从文件系统中加载并返回。顺便提一下,当收到内存警告的时候,系统可能会将UIImage内部的存储图像的内存释放,下一次需要绘制的时候会重新去加载
三、imageWithCGImage:scale:orientation:方法——介绍该方面使用一个CGImageRef创建UIImage,在创建时还可以指定方法倍数以及旋转方向。当scale设置为1的时候,新创建的图像将和原图像尺寸一摸一样,而orientaion则可以指定新的图像的绘制方向。
26、回答person的retainCount值,并解释为什么
Person * per = [[Person alloc] init];
self.person = per;
如果person的属性是assign的话 引用计数为1;
如果person的属性是retain得话,引用计数为2;
27、这段代码有什么问题,如何修改
@implementation Person
- (void)setAge:(int)newAge {
self.age = newAge;
}
self.age点语法调用setter方法,会进入死循环.把self.age修改成_age;
28、这段代码有什么问题?
for (int i = 0; i < someLargeNumber; i++) {
NSString *string = @"Abc";
string = [string lowercaseString];
string = [string stringByAppendingString:@"xyz"];
NSLog(@"%@", string);
}
如果循环次数过大,会导致内存不够用产生闪退,加一个自动释放池
29、截取字符串”20 | http://www.baidu.com”中,”|”字符前面和后面的数据,分别输出它们。
NSMutableString *mutableString = [NSMutableString stringWithFormat:@“20|http://www.baidu.com"];
删除”|”;
[mutableString deleteCharactersInRange:[mutableString rangeOfString:@"|"]];
NSLog(@"%@", mutableString);
用”|”分割 然后放到数组中那个
NSMutableString *str = [NSMutableString stringWithFormat:@"20|http://www.baidu.com"];
NSArray *array = [str componentsSeparatedByString:@"|"];
// [mutableString deleteCharactersInRange:NSMakeRange(2, 1)];
30、 用obj-c写一个冒泡排序
int array[] = {3, 2, 6, 9, 8, 5, 7, 1, 4};
int count = array.count;
int flag = 1;
for (int i = 0; i < count - 1 && 1 == flag; ) {
flag = 0;
for (int j = 0; j < count - i - 1; j++) {
if (array[j] > array[j + 1]) {
int k = array[j];
array[j] = array[j + 1];
array[j + 1] = k;
flag = 1;
}
}
}
31、简述你对UIView、UIWindow和CALayer的理解
UIView对象定义了一个屏幕上的一个矩形区域,同时处理该区域的绘制和触屏事件。
可以在这个区域内绘制图形和文字,还可以接收用户的操作。一个UIView的实例可以包含和管理若干个子UIView。
UIWindow对象是所有UIView的根,管理和协调的应用程序的显示
UIWindow类是UIView的子类,可以看作是特殊的UIView。一般应用程序只有一个UIWindow对象,即使有多个UIWindow对象,也只有一个UIWindow可以接受到用户的触屏事件。
CALayer是用来绘制内容的,对内容进行动画处理依赖与UIView来进行显示,不能处理用户事件。
32、写一个完整的代理,包括声明,实现
#import <UIKit/UIKit.h>
@class ReadSelectViewController;
@protocol pushSelectDetail <NSObject>
- (void)pushSelectDetailController:(id)controller;
@end
@interface ReadSelectViewController : UITableViewController
@property (nonatomic, retain) NSString *webview;
@property (nonatomic, assign) id<pushSelectDetail> delegate;
@end
if (self.delegate && [self.delegate respondsToSelector:@selector(pushSelectDetailController:)]) {
[self.delegate pushSelectDetailController:text];
}
- (void)pushSelectDetailController:(id)controller{
[self.navigationController pushViewController:controller animated:YES];
}
33、分析json、xml的区别?json、xml解析方式的底层是如何处理的?
(1).可读性方面。
JSON和XML的数据可读性基本相同,JSON和XML的可读性可谓不相上下,一边是建议的语法,一边是规范的标签形式,XML可读性较好些。
(2).可扩展性方面。
XML天生有很好的扩展性,JSON当然也有,没有什么是XML能扩展,JSON不能的。
(3).编码难度方面。
XML有丰富的编码工具,比如Dom4j、JDom等,JSON也有json.org提供的工具,但是JSON的编码明显比XML容易许多,即使不借助工具也能写出JSON的代码,可是要写好XML就不太容易了。
(4).解码难度方面。
XML的解析得考虑子节点父节点,让人头昏眼花,而JSON的解析难度几乎为0。这一点XML输的真是没话说。
(5).流行度方面。
XML已经被业界广泛的使用,而JSON才刚刚开始,但是在Ajax这个特定的领域,未来的发展一定是XML让位于JSON。到时Ajax应该变成Ajaj(Asynchronous Javascript and JSON)了。
(6).解析手段方面。
JSON和XML同样拥有丰富的解析手段。
(7).数据体积方面。
JSON相对于XML来讲,数据的体积小,传递的速度更快些。
(8).数据交互方面。
JSON与JavaScript的交互更加方便,更容易解析处理,更好的数据交互。
(9).数据描述方面。
JSON对数据的描述性比XML较差。
(10).传输速度方面。
JSON的速度要远远快于XML。
json中以key/value形式保存,大多数是字典数组模式
xml中则是<>
参考文档:http://www.cnblogs.com/SanMaoSpace/p/3139186.html
34、ViewController 的 didReceiveMemoryWarning 是在什么时候被调用的?默认的操作是什么?
didReceiveMemoryWarning出现内存警告时调用该方法。在该方法里释放暂时没有使用的可重用的对象
if([self isViewLoaded] == YES && self.View.window == nil){
self.View == nil;
}
35、面向对象的三大特征,并作简单的介绍
封装:是把客观事物封装成抽象的类,隐含内部实现 提供接口
多态:是不同的对象以自己的方式响应相同的消息的能力就是多态
继承:是使用现有类的所有功能 无需编码原先类的情况下进行扩展
36、重写一个NSStrng类型的retain方式声明name属性的setter和getter方法
- (void)setName:(NSString *)name{
if(_name != name){
[_name release];
[_name retain];
_name = name;
}
}
- (NSString *)name{
return [[_name retain]autorelease];
}
37、简述NotificationCenter、KVC、KVO、Delegate?并说明它们之间的区别?
NotificationCenter消息中心: 消息的发送者告知接受者事件已经发生或者将要发送, 接受者并不能反过来营销那个发送者的行为. 通常发送者和接受者的关系是间接的多对多的关系,类似于广播的形式,也可以一对多..
KVC: 键值编码, 可以直接通过字符串的名字(key)来间接访问属性的机制, 而不是通过getter和setter方法访问.
KVO:是一个对象能够观察另外一个对象的属性的值, 并且发现值的变化, 更适合任何类型的对象侦听另外一个任意对象的变化, 这是一个对象和另外一个对象保持同步的一种方法, 即两一个对象发生改变时, 观察者立马做出反应. 它只能用来对属性做出反应, 而不会用来对方法或则动作做出反应,
缺点:观察的属性使用string来定义, 因此在编译器不会检查并出现警告.
Delegate: 代理 类A调用类B, 当类B想回调A的方法的时候, 要用到delegate. 多用于发送者希望接受到接受者的某个功能反馈值.
代理的目的是改变或传递控制链。允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针。可以减少框架复杂度。
另外一点,代理可以理解为java中的回调监听机制的一种类似.
参考文档:http://283962999.blog.51cto.com/6514739/1266791
参考文档:http://blog.sina.com.cn/s/blog_bf9843bf0101j5px.html
38、What is lazy loading?
懒加载, 只在用到的时候才去初始化. 避免内存过多, 一个异步加载, 避免线程阻塞.
39、什么是Protocol?什么是代理?写一个委托的interface?委托的property声明用什么属性?为什么?
详见32题和37题 assign 防止循环引用
40、分别描述类别(categories)和延展(extensions)是什么?以及两者的区别?继承和类别在实现中有何区别?为什么Category只能为对象添加方法,却不能添加成员变量
Extension的主要作用是管理类的”私有方法”.
面向对象编程也叫面向接口编程.
延展的作用就是定义自己的私有方法。
形式和类目相同,不用新创建文件,只是把类目的interface地方的文件放在了你需要扩展的类的.m文件里边。
Extension的功能是帮我们去管理这些内部使用的方法(“私有方法”).
Category也叫分类或类⺫;主要作⽤用是为现有的类添加方法。通过Category添加的⽅法会成为原类的一部分。从⽽而达到扩展一个类的功能。
category可以为当前类生成私有方法,子类不能直接调用;
但是通过继承,子类可以调用父类所有的属性和方法;对已有类进行拓展.
类目为什么不能添加实例变量:因为类的方法中使用的都是静态变量,不能使用实例变量
41、Objective‐C中,所有实例变量默认都是私有的,所有实例方法默认都是公有的
objective-c – 类里面的方法只有两种, 静态方法和实例方法. @private来修饰私有变量OC中所有的实例变量默认都是私有的,所有的实例方法默认都是公有的。
42、#import、#include和@class有什么区别#include c语言中引入一个头文件,但是可能出现交叉编译#import在OC中引入自己创建的头文件#import””或者系统框架#import<>。#import不会出现交叉编译@class对一个类进行声明,告诉编译器有这个类,但是类的定义什么的都不知道
43、谈谈你对MVC的理解?为什么要用MVC?在Cocoa中MVC是怎么实现的?你还熟悉其他的OC设计模式或别的设计模式吗?MVC是Model-VIew-Controller,就是模型-视图-控制器, MVC把软件系统分为三个部分:Model,View,Controller。在cocoa中,你的程序中的每一个object(对象)都将明显地仅属于这三部分中的一个,而完全不属于另外两个。MVC可以帮助确保帮助实现程序最大程度的可重用性。各MVC元素彼此独立运作,通过分开这些元素,可以构建可维护,可独立更新的程序组建。
单例模式,delegate设计模式,target-action设计模式
44、如监测系统键盘的弹出[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( ) name:UIKeyboardWillShowNotification object:nil];
45、举出5个以上你所熟悉的ios sdk库有哪些和第三方库有哪些?
Foundation,CoreFraphics,UIKit,MapKit,CoreLocation,CFNetWork,MessageUI,ImageIO,CoreData,AFNetWorking,MKNetWorkKit,ASIHttpRequest,FMDB,ZXing,ZBar,SDWebImage
46、如果将产品进行多语言发布?
实现多语言化
Step 1:为应用添加多语言版本
Step 2:编程中的变化
Step 3:获取Localizable.strings
Step 4:编辑Localizable.strings
参考文档:http://blog.csdn.net/songrotek/article/details/8766641
47、如何将敏感字变成**
NSMutableArray *array = [[NSMutableArray alloc] init];//本地敏感词汇
NSString *a = @"敏感字";
NSString *b = @"我";
[array addObject:a];
[array addObject:b];
//下面是方法
//创建一个需要判断的字符串
NSMutableString *s = [[NSMutableString alloc] initWithString:@"我是敏感字"];
for (int i = 0 ; i < array.count; i++) {
NSString *minganzi = array[i];
NSMutableString *replaceString = [[NSMutableString alloc] init];
for (int j = 0; j < s.length - a.length + 1; j++) {
NSRange range;
range.length = minganzi.length;//得到敏感字长度
range.location = j;//得到起始下标
if ([[s substringWithRange:range] isEqualToString:minganzi]) {
for (int k = 0; k < range.length; k++) {
[replaceString appendString:@"*"];
}
//根据range 来替换敏感字
[s replaceCharactersInRange:range withString:replaceString];
}
}
}
NSLog(@"%@", s);
}
48、objc中的减号与加号代表什么?
减号代表静态方法, 加号代表静态方法, 也叫类方法
49、单例的目的是什么, 并写出一个
单例模式确保一个类只有一个实例,比较节省内存,自行提供这个实例并向整个系统提供这个实例.
+ (instantClass *)sharedClient {
static instantClass *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedClient = [[instantClass alloc] init];
});
return _sharedClient;
}
50、说说响应链
用户点击屏幕后产生的一个触摸事件,经过一些列的传递过程后,会找到最合适的视图控件来处理这个事件
找到最合适的视图控件后,就会调用控件的touches方法来作具体的事件处理
如果view的控制器存在,就传递给控制器;如果控制器不存在,则将其传递给它的父视图
在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给window对象进行处理
如果window对象也不处理,则其将事件或消息传递给UIApplication对象
如果UIApplication也不能处理该事件或消息,则将其丢弃
参考文档:http://www.cnblogs.com/wendingding/p/3795171.html
51、 请写出代码,用blocks来取代上例中的protocol,并比较两种方法的优势。实际应用部分?请写出代码,用blocks取代协议或回调方法
解决循环引用方案, 将self进行弱引用,出了这个方法,自动释放; 在MRC下, 用__block , 在ARC下, 用__weak
委托和Block是iOS上实现回调的两种机制。
BLock基本可以代替委托的功能,而且实现起来比较简洁,比较推荐能用Block的地方不要用委托
TimerControl.h文件
// 委托的协议定义
@protocol UpdateAlertDelegate
-(void)UpdateAlter:(NSString *)title;
@end
@interface TimerControl :NSObject
// 委托变量定义
@property (nonatomic,weak)id<UpdateAlertDelegate>delegate
// block
typedef void (^UpdateAlterBlock)(NSString * title);
@property (nonatomic,copy)UpdateAlertBlock updateAlertBlock;
-(void)startTheTimer;
@end
TimerControl.m文件
-(void)timerProc{
[self.delegate updateAlert:@“this is title”]; // 委托更新UI
// block代替委托
if(self.updateAlertBlock){
self.updateAlertBlock(@“this is title”);
}
}
再来看看视图类,实现Block即可
-(void)viewDidLoad
{
[super viewDidLoad];
TimerControl *timer = [[TimerControl alloc] init];
timer.delegate = self; // 设置委托代理
// 实现block
timer.updateAlertBlock = ^(NSString *title){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:@“时间到” delegate:nil otherButtonTitles:@“确定”,nil];
alert.alertViewStyle = UIAlertViewStyleDefault;
[alter show];
};
[timer startTheTimer]; // 启动定时器
}
// 被委托对象,实现协议声明的方法 由委托对象调用
-(void)updateAlert:(NSString *title){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:”时间到” delegate:nil otherButtonTitles:@“确认”,nil];
alert.alertViewStyle = UIAlertViewStyleDefault;
[alert show];
}
参考文档:http://blog.csdn.net/a_ss_a/article/details/38477411
52、你做iphone开发时候,有哪些传值方式,view和view之间是如何传值的?
通知中心NSNotificationCenter 轻量级本地数据存储NSUserDefaults 属性传值 代理传值 单例传值 extern传值 Block传值
在同一个试图控制器里,设置一个全局变量就行
不在一个试图控制器里,可以使用代理 也可以使用属性
53、给定的一个字符串,判断字符串中是否还有png,有就删除它?
NSMutableString *string = [NSMutableString stringWithFormat:@"%@", @"dasdasjdlpngnkpng"];
NSRange range = [string rangeOfString:@"png"];
NSLog(@"%@", NSStringFromRange(range));
while (range.length == 3) {
[string deleteCharactersInRange:range];
range = [string rangeOfString:@"png"];
NSLog(@"%@", NSStringFromRange(range));
}
NSLog(@"%@", string);
54、对于语句NSString* testObject = [[NSData alloc] init];testObject 在编译时和运行时分别是什么类型的对象
编译的时候是NSString, 运行的时候是NSData
首先,声明 NSString *testObject 是告诉编译器,testObject是一个指向某个Objective-C对象的指针。因为不管指向的是什么类型的对象,一个指针所占的内存空间都是固定的,所以这里声明成任何类型的对象,最终生成的可执行代码都是没有区别的。这里限定了NSString只不过是告诉编译器,请把testObject当做一个NSString来检查,如果后面调用了非NSString的方法,会产生警告。
接着,你创建了一个NSData对象,然后把这个对象所在的内存地址保存在testObject里。那么运行时,testObject指向的内存空间就是一个NSData对象。你可以把testObject当做一个NSData对象来用。
55、OC中是所有对象间的交互是如何实现的?
通过消息发送机制实现交互, 一个扮演数据发送者, 一个座位数据接受者;在对象间交互中每个对象承担的角色不同,但总的来说无非就是“数据发送者”或“数据接收者”两种角色。我们可以通过objective-c中给我们提供的手段来实现两者间的通讯。如:
1.”通知中心“ NSNotificationCenter
2.还有就是通过”代理协议“的方式实现。
这两种方式都能最大限度的减少两交互对象之间的藕合,都是不错的设计。
关于gif的显示问题
鉴于这次做显示gif动画的惨痛教训,写下历程作为前车之鉴
做动画时最主要要考虑三个方面:
1,动画时cpu消耗不能过高
2,动画时内存不能消耗过高
3,在符合前两个条件时动画要和原始图一样流畅。
第一次做gif动画,考虑过少,浪费了很多的时间来做后续的修复。
总体来说,gif的显示动画有以下几种显示方式
1,通过最原始的那种UIImageView加载帧动画的方式,前提是动画帧数不多且不会显示多次,不然会造成内存吃不消。
2,通过第三方XYSpriteView 是一个帧动画精灵类,和上面的方式差不多也是一帧一帧的加载动画,效果比方法1的好
3,通过UIWebView显示动画 但是这种虽然内存消耗不是很大,但是很耗cpu,不知道为什么
4,通过苹果自带的ImageIO类库来实现,网上很多用到这个类库的第三方,可以搜一下
5,通过ImageIO把gif的图片找出来后转为NSData,然后再把NSData重绘变为图
6,通过ImageIO把gif的图片找出来后通过NSTimer加一张释放一张。
我这次用的是 http://code4app.com/ios/GIF-Image-View/4f800a9906f6e70a7c000001
这个第三方的缺点就是里面你的gif动画中不能有透明的,或者半透明的,不然必挂,报错的信息是:
: ImageIO: _CGImagePluginInitGIF malformed GIF file (640 x 1136) - [canvasSize: 727040 fileSize: 807 ratio: 900]
图片在转为data的过程中解析错误
56、目标-动作机制
目标-动作机制, 允许一个空间对象(例如案件或滑动条)向另外一个对象发送一条消息(即动作), 以之作为对某个用户事件 (例如一个点击事件)的响应. 接收到消息的对象则可以进行响应, 并针对业务要求做出处理.
程序需要某些机制来进行时间和指令的翻译. 这个机制就是目标- 动作机制.
57、这段代码有什么问题.?会不会造成内存泄露(多线程)?在内存紧张的设备上做大循环时自动释放池是写在循环内好还是循环外好?为什么?
for(int index = 0; index < largenumber; index ++){
NSString *tempStr = @”tempStr”;
NSLog(tempStr);
NSNumber *tempNumber = [NSNumber numberWithInt:2];
NSLog(tempNumber);
}
占用大量内存,可能造成程序崩溃
在多线程中,此循环一直进行,可能制造出得不到数据的野指针,程序崩溃
自动释放池写在内部好 ,每一次循环结束都会释放内存空间,若写在外面加上内存紧张会造成崩溃
当循环次数过大的时候, 会因为内存没有释放, 导致程序闪退. 在内存紧张的设备上做大循环的时候自动释放次应该写在循环内比较好.修改方案如下;
for(int index = 0; index < 7788787; index ++){
@autoreleasepool {
NSString *tempStr = @"tempStr";
NSLog(@"%@", tempStr);
NSNumber *tempNumber = [NSNumber numberWithInt:2];
NSLog(@"%@", tempNumber);
}
}
58、描述上拉加载、下拉刷新的实现机制
上拉加载, 就是上拉加载的时候, 请求更多不同的数据, 然后显示在UI界面上,和下拉刷新最大的区别就是, 下拉刷新是请求当前最新的数据, 然后刷新UI界面显示的数据.
下拉刷新的原理 : 当scrollView向下发生偏移,发起网络请求,请求刷新数据
上拉加载更多:scrollView一开始不存在偏移量,但是会设定contentSize的大小,所以contentSize.height永远会比contentOffSet.y高出一个手机屏幕的高度。当contentOffset.y+手机屏幕高度大于这个滚动视图的contentSize.height时,发起网络请求,请求加载更多数据
59、什么是沙盒(sandbox)?沙盒包含哪些文件,描述每个文件的使用场景。如何获取这些文件的路径?如何获取应用程序包中文件的路径
iOS应用程序只能在为该程序创建的文件系统中读取文件,不可以访问其他地方,这个区域被称为沙盒
沙盒里包含以下内容:
Documents 苹果建议将程序中建立的或在程序中浏览到的文件数据保存在该目录下,iTunes备份和恢复时包括此目录
Library 存储程序的默认设置和其他状态信息 其中Caches存放缓存文件 ,此目录不会在应用退出删除,iTunes不会备份此目录
tmp 提供一个即时创建临时文件的地方,退出应用程序, 就会清空tmp 看
系统提供了方法NSSearchPathForDirectoriesInDomains(NSDocumentDirectory ,NSUserDomainMask,YES);
NSLibraryDirectory
tmpPath = NSTemporaryDirectory();
获取程序包中文件的路径方法:通过NSFileManager中的查找方法
两种方法subPathsOfDirectoryAtPath:文件夹名 error:nil
subpathsAtPath:文件夹名 (后面不带获取失败原因参数)
60、介绍一下XMPP?有什么优缺点吗?
XMPP(可扩展消息处理现场协议)是基于可扩展标记语言XML的协议,它用于即时消息(IM)以及在线现场探测。
优点: 开放
XMPP协议是自由 开放 公开的 并且易于了解。在客户端 服务器 组件 源码库等方面,都已经各自有多种实现
证实可用
第一个Jabber(现在XMPP)技术是Jeremie Miller在1998年开发的,现在已经相当稳定;数以百计的开发者为XMPP技术而努力。今日的互联网上有数以万计的XMPP服务器运作着,并有数以百万计的人们使用XMPP实时传讯软件
可扩展
XML命名空间的威力可使任何人在核心协议的基础上创建定制化的功能;为了维持通透性,常见的扩展由XMPP标准基金会
多样性
用XMPP协议来创造及部署实时应用程序及服务的公司及开源代码计划分布在各种领域;用XMPP技术开发软件,资源及支持的来源是多样
缺点:
数据负载太重
随着通常超过70%的XMPP协议的服务器的数据流量的存在近60%的重复转发。
没有二进制数据
XMPP协议的方式被编码为一个单一的长的XML文件,无法提供修改二进制数据。
61、谈谈对性能优化的看法, 如何做?
1.优化算法
2.内存优化(不要过度得去创建和释放对象,会造成内存碎片)
3.不要滥用一些
4.显卡优化
5.电量的优化
61、应用程序如何省电?
GPS获取到你要的数据后,及时关闭
大数据获得之后做好缓存, 不要过多的请求数据
62、写一个递归方法 :计算N的阶乘,然后将计算结果进行存储. 以便应用退出后瑕疵启动可直接获取该值(NSUserDefault)
63、NSArray 和NSMutableArray的区别,多线程操作哪个更安全?
NSArray更安全, 多线程用NSMutableArray枷锁操作
64、当前有一个数组,里面有若干重复的数据,如何去除重复的数据
转成集合,然后再转换成数组
65、isKindOfClass 判断类的实例
isMemberOfClass 可以判断子类的实例
66、写出下面程序段的输出结果