2015年11月25日 星期三
14:13
1.你实现过一个框架或者库以供别人使用么?如果有,请谈一谈构建框架或者库时候的经验;如果没有,请设想和设计框架的public的API,并指出大概需要如何做、需要注意一些什么方面,来使别人容易地使用你的框架。
抽象和封装,方便使用。首先是对问题有充分的了解,比如构建一个文件解压压缩框架,从使用者的角度出发,只需关注发送给框架一个解压请求,框架完成复杂文件的解压操作,并且在适当的时候通知给是哦难过者,如解压完成、解压出错等。在框架内部去构建对象的关系,通过抽象让其更为健壮、便于更改。其次是API的说明文档.
1.提供给外界的接口功能是否实用、够用
2.别人使用我的框架时,能不能根据类名、方法名就猜出接口的具体作用
3.别人调用接口时,提供的参数是否够用、调用起来是否简单
4.别人使用我的框架时,要不要再导入依赖其他的框架
2.你在实际开发中,有哪些手机架构与性能调试经验
1>刚接手公司的旧项目时,模块特别多,而且几乎所有的代码都写在控制器里面,比如UI控件代码、网络请求代码、数据存储代码
2>接下来采取MVC模式进行封装、重构
自定义UI控件封装内部的业务逻辑
封装网络请求工具类
封装数据存储工具类
使用NSOperation发送异步网络请求,使用NSOperationQueue管理线程数目及优先级,底层是用NSURLConnetion,详细可见开源框架LWConnetion。
KVO Delegation NSNotification
通知
通知比较灵活,不需要编写多少代码,实现比较简单;
对于一个发出的通知,多个对象能够做出反应,即1对多的方式
代理
代理的语法比较严格,如果delegate中的一个方法没有实现那么就会出现编译警告
需要定义很多代码
KVO
KVO性能不好(底层会动态产生新的类),只能监听某个对象属性的改变
2. KVO内部实现原理
KVO是基于runtime机制实现的
当某个类的对象第一次被观察时, 系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter方法。
派生类在被重写的setter方法实现真正的通知机制(Person NSKVONotifying_Person)
多图片下载
Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么?
答:Object-c的类不可以多重继承;可以实现多个接口,通过实现多个接口可以完成C++的多重继承;
Category是类别,一般情况用分类好,用Category去重写类的方法,仅对本Category有效,不会影响到其他类与原有类的关
#import跟#include又什么区别,@class呢, #import<>跟#import”又什么区别?
答:#import是Objective-C导入头文件的关键字,#include是C/C++导入头文件的关键字,使用#import头文件会自动只导入一次,不会重复导入,相当于#include和#pragma once;@class告诉编译器某个类的声明,当执行时,才去查看类的实现文件,可以解决头文件的相互包含;#import<>用来包含系统的头文件,#import””用来包含用户头文件。
属性readwrite,readonly,assign,retain,copy,nonatomic各是什么作用,在那种情况下用?
readwrite是可读可写特性;需要生成getter方法和setter方法时
readonly是只读特性 只会生成getter方法 不会生成setter方法;不希望属性在类外改变
assign是赋值特性,setter方法将传入参数赋值给实例变量;仅设置变量时;
retain表示持有特性,setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1;
copy表示赋值特性,setter方法将传入对象复制一份;需要完全一份新的变量时。
nonatomic非原子操作,决定编译器生成的setter getter是否是原子操作,atomic表示多线程安全,一般使用nonatomic
写一个setter方法用于完成@property(nonatomic,retain)NSString *name,写一个setter方法用于完成@property(nonatomic,copy)NSString *name
-
(void) setName:(NSString*) str
{
[str retain];
[name release];
name = str;
} -
(void)setName:(NSString *)str
{
id t = [str copy];
[name release];
name = t;
}
对于语句NSString*obj = [[NSData alloc] init]; obj在编译时和运行时分别时什么类型的对象?
编译时是NSString的类型;运行时是NSData类型的对象
常见的object-c的数据类型有那些, 和C的基本数据类型有什么区别?如:NSInteger和int
答:object-c的数据类型有NSString,NSNumber,NSArray,NSMutableArray,NSData等等,这些都是class,创建后便是对象,而C语言的基本数据类型int,只是一定字节的内存空间,用于存放数值;NSInteger是基本数据类型,并不是NSNumber的子类,当然也不是NSObject的子类。NSInteger是基本数据类型Int或者Long的别名(NSInteger的定义typedef longNSInteger),它的区别在于,NSInteger会根据系统是32位还是64位来决定是本身是int还是Long。
id声明的对象有什么特性?
答:Id声明的对象具有运行时的特性,即可以指向任意类型的objcetive-c的对象;
Objective-C如何对内存管理的?
答:Objective-C的内存管理主要有三种方式ARC(自动引用计数)、MRC(手动内存计数)、autorelease(自动释放池)。
原子(atomic)跟非原子(non-atomic)属性有什么区别?
atomic提供多线程安全。是防止在写未完成的时候被另外一个线程读取,造成数据错误
non-atomic:在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果指定了nonatomic,那么访问器只是简单地返回这个值。
内存管理的几条原则时什么?按照默认法则.那些关键字生成的对象需要手动释放?在和property结合的时候怎样有效的避免内存泄露?
谁申请,谁释放
遵循Cocoa Touch的使用原则;
内存管理主要要避免“过早释放”和“内存泄漏”,对于“过早释放”需要注意@property设置特性时,一定要用对特性关键字,对于“内存泄漏”,一定要申请了要负责释放,要细心。
关键字alloc或new生成的对象需要手动释放;
设置正确的property属性,对于retain需要在合适的地方释放,
如何对iOS设备进行性能测试?
Profile-> Instruments ->Time Profiler
Object C中创建线程的方法是什么?如果在主线程中执行代码,方法是什么?如果想延时执行代码、方法又是什么?
答:线程创建有三种方法:使用NSThread创建、使用GCD的dispatch、使用子类化的NSOperation,然后将其加入NSOperationQueue;在主线程执行代码,方法是performSelectorOnMainThread,如果想延时执行代码可以用performSelector:onThread:withObject:waitUntilDone:
MVC设计模式是什么? 你还熟悉什么设计模式?
设计模式:并不是一种新技术,而是一种编码经验,使用比如java中的接口,iphone中的协议,继承关系等基本手段,用比较成熟的逻辑去处理某一种类型的事情,总结为所谓设计模式。面向对象编程中,java已经归纳了23种设计模式。
mvc设计模式 :模型,视图,控制器,可以将整个应用程序在思想上分成三大块,对应是的数据的存储或处理,前台的显示,业务逻辑的控制。Iphone本身的设计思想就是遵循mvc设计模式。其不属于23种设计模式范畴。
代理模式:代理模式给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用.比如一个工厂生产了产品,并不想直接卖给用户,而是搞了很多代理商,用户可以直接找代理商买东西,代理商从工厂进货.常见的如QQ的自动回复就属于代理拦截,代理模式在iphone中得到广泛应用.
单例模式:说白了就是一个类不通过alloc方式创建对象,而是用一个静态方法返回这个类的对象。系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为,比如想获得[UIApplication sharedApplication];任何地方调用都可以得到UIApplication的对象,这个对象是全局唯一的。
观察者模式: 当一个物体发生变化时,会通知所有观察这个物体的观察者让其做出反应。实现起来无非就是把所有观察者的对象给这个物体,当这个物体的发生改变,就会调用遍历所有观察者的对象调用观察者的方法从而达到通知观察者的目的。
工厂模式:
public class Factory {
public static Sample creator(int which ){
if (which==1)
return new SampleA();
else if (which==2)
return new SampleB();
}
}
类别的作用?继承和类别在实现中有何区别?
答:category可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修改,并且如果类别和原来类中的方法产生名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。
类别主要有3个作用:
1).将类的实现分散到多个不同文件或多个不同框架中。
2).创建对私有方法的前向引用。
3).向对象添加非正式协议。
继承可以增加,修改或者删除方法,并且可以增加属性。
类别和类扩展的区别。
答:category和extensions的不同在于 后者可以添加属性。另外后者添加的方法是必须要实现的。
extensions可以认为是一个私有的Category。
oc中的协议和java中的接口概念有何不同?
答:OC中的代理有2层含义,官方定义为formal和informal protocol。前者和Java接口一样。
informal protocol中的方法属于设计模式考虑范畴,不是必须实现的,但是如果有实现,就会改变类的属性。
其实关于正式协议,类别和非正式协议我很早前学习的时候大致看过,也写在了学习教程里
“非正式协议概念其实就是类别的另一种表达方式“这里有一些你可能希望实现的方法,你可以使用他们更好的完成工作”。
现在来看,其实protocal已经开始对两者都统一和规范起来操作,因为资料中说“非正式协议使用interface修饰“,
现在我们看到协议中两个修饰词:“必须实现(@requied)”和“可选实现(@optional)”。
什么是KVO和KVC?
答:KVC:键–值编码是一种间接访问对象的属性使用字符串来标识属性,而不是通过调用存取方法,直接或通过实例变量访问的机制。
很多情况下可以简化程序代码。apple文档其实给了一个很好的例子。
KVO:键值观察机制,他提供了观察某一属性变化的方法,极大的简化了代码。
具体用看到嗯哼用到过的一个地方是对于按钮点击变化状态的的监控。
比如我自定义的一个button
[self addObserver:self forKeyPath:@"highlighted" options:0 context:nil];
#pragma mark KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"highlighted"] ) {
[ self setNeedsDisplay];
}
}
对于系统是根据keypath去取的到相应的值发生改变,理论上来说是和kvc机制的道理是一样的。
对于kvc机制如何通过key寻找到value:
“当通过KVC调用对象时,比如:[selfvalueForKey:@”someKey”]时,程序会自动试图通过几种不同的方式解析这个调用。首先查找对象是否带有someKey这个方法,如果没找到,会继续查找对象是否带有someKey这个实例变量(iVar),如果还没有找到,程序会继续试图调用-(id) valueForUndefinedKey:这个方法。如果这个方法还是没有被实现的话,程序会抛出一个NSUndefinedKeyException异常错误。
(cocoachina.com注:Key-Value Coding查找方法的时候,不仅仅会查找someKey这个方法,还会查找getsomeKey这个方法,前面加一个get,或者someKey以及getsomeKey这几种形式。同时,查找实例变量的时候也会不仅仅查找someKey这个变量,也会查找_someKey这个变量是否存在。) -设计valueForUndefinedKey:方法的主要目的是当你使用-(id)valueForKey方法从对象中请求值时,对象能够在错误发生前,有最后的机会响应这个请求。这样做有很多好处,下面的两个例子说明了这样做的好处。“
来至cocoa,这个说法应该挺有道理。
因为我们知道button却是存在一个highlighted实例变量.因此为何上面我们只是add一个相关的keypath就行了,
可以按照kvc查找的逻辑理解,就说的过去了。
代理的作用?
答:代理的目的是改变或传递控制链。允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针。可以减少框架复杂度。
另外一点,代理可以理解为java中的回调监听机制的一种类似。
oc中可修改和不可以修改类型。
答:可修改不可修改的集合类。这个我个人简单理解就是可动态添加修改和不可动态添加修改一样。
比如NSArray和NSMutableArray。前者在初始化后的内存控件就是固定不可变的,后者可以添加等,可以动态申请新的内存空间。
我们说的oc是动态运行时语言是什么意思?
答:多态。 主要是将数据类型的确定由编译时,推迟到了运行时。
这个问题其实浅涉及到两个概念,运行时和多态。
简单来说,运行时机制使我们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法。
多态:不同对象以自己的方式响应相同的消息的能力叫做多态。意思就是假设生物类(life)都用有一个相同的方法-eat;
那人类属于生物,猪也属于生物,都继承了life后,实现各自的eat,但是调用是我们只需调用各自的eat方法。
也就是不同的对象以自己的方式响应了相同的消息(响应了eat这个选择器)。
因此也可以说,运行时机制是多态的基础?~~~
通知和协议的不同之处?
答:协议有控制链(has-a)的关系,通知没有。
首先我一开始也不太明白,什么叫控制链(专业术语了~)。但是简单分析下通知和代理的行为模式,我们大致可以有自己的理解
简单来说,通知的话,它可以一对多,一条消息可以发送给多个消息接受者。
代理按我们的理解,到不是直接说不能一对多,比如我们知道的明星经济代理人,很多时候一个经济人负责好几个明星的事务。
只是对于不同明星间,代理的事物对象都是不一样的,一一对应,不可能说明天要处理A明星要一个发布会,代理人发出处理发布会的消息后,别称B的
发布会了。但是通知就不一样,他只关心发出通知,而不关心多少接收到感兴趣要处理。
因此控制链(has-a从英语单词大致可以看出,单一拥有和可控制的对应关系。
什么是推送消息?
答:推送通知更是一种技术。
简单点就是客户端获取资源的一种手段。
普通情况下,都是客户端主动的pull。
推送则是服务器端主动push。 测试push的实现可以查看该博文。
关于多态性
答:多态,子类指针可以赋值给父类。
这个题目其实可以出到一切面向对象语言中,
因此关于多态,继承和封装基本最好都有个自我意识的理解,也并非一定要把书上资料上写的能背出来
对于单例的理解
答:在objective-c中要实现一个单例类,至少需要做以下四个步骤:
1). 为单例对象实现一个静态实例,并初始化,然后设置成nil,
2).实现一个实例构造方法检查上面声明的静态实例是否为nil,如果是则新建并返回一个本类的实例,
3).重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实力的时候不产生一个新实例,
4).适当实现allocWitheZone,copyWithZone,release和autorelease。
说说响应链
答: 事件响应链。包括点击事件,画面刷新事件等。在视图栈内从上至下,或者从下之上传播。可以说点事件的分发,传递以及处理。具体可以去看下touch事件这块。因为问的太抽象化了严重怀疑题目出到越后面就越笼统。可以从责任链模式,来讲通过事件响应链处理,其拥有的扩展性
frame和bounds有什么不同?
答:frame指的是:该view在父view坐标系统中的位置和大小。(参照点是父亲的坐标系统)
bounds指的是:该view在本身坐标系统中 的位置和大小。(参照点是本身坐标系统)
方法和选择器有何不同?
答:selector是一个方法的名字,method是一个组合体,包含了名字和实现.
详情可以看apple文档。
- OC的垃圾回收机制?
答:OC2.0有Garbage collection,但是iOS平台不提供。一般我们了解的objective-c对于内存管理都是手动操作的,但是也有自动释放池。但是差了大部分资料,貌似不要和arc机制搞混就好了。
NSOperation queue?
答:存放NSOperation的集合类。
操作和操作队列,基本可以看成java中的线程和线程池的概念。用于处理ios多线程开发的问题。
网上部分资料提到一点是,虽然是queue,但是却并不是带有队列的概念,放入的操作并非是按照严格的先进现出。
这边又有个疑点是,对于队列来说,先进先出的概念是Afunc添加进队列,Bfunc紧跟着也进入队列,Afunc先执行这个是必然的,但是Bfunc是等Afunc完全操作完以后,B才开始启动并且执行,因此队列的概念离乱上有点违背了多线程处理这个概念。但是转念一想其实可以参考银行的取票和叫号系统。因此对于A比B先排队取票但是B率先执行完操作,我们亦然可以感性认为这还是一个队列。但是后来看到一票关于这操作队列话题的文章,其中有一句提到
“因为两个操作提交的时间间隔很近,线程池中的线程,谁先启动是不定的。”
瞬间觉得这个queue名字有点忽悠人了,还不如pool~
综合一点,我们知道他可以比较大的用处在于可以帮组多线程编程就好了。
什么是延迟加载?
答:懒汉模式,只在用到的时候才去初始化。
也可以理解成延时加载。
我觉得最好也最简单的一个列子就是tableView中图片的加载显示了。
一个延时载,避免内存过高,一个异步加载,避免线程堵塞。
是否在一个视图控制器中嵌入两个tableview控制器?
答:一个视图控制只提供了一个View视图,理论上一个tableViewController也不能放吧,只能说可以嵌入一个tableview视图。当然,题目本身也有歧义,如果不是我们定性思维认为的UIViewController,而是宏观的表示视图控制者,那我们倒是可以把其看成一个视图控制者,它可以控制多个视图控制器,比如TabbarController那样的感觉。
一个tableView是否可以关联两个不同的数据源?你会怎么处理?
答:首先我们从代码来看,数据源如何关联上的,其实是在数据源关联的代理方法里实现的。
因此我们并不关心如何去关联他,他怎么关联上,方法只是让我返回根据自己的需要去设置如相关的数据源。
因此,我觉得可以设置多个数据源啊,但是有个问题是,你这是想干嘛呢?想让列表如何显示,不同的数据源分区块显示?
什么时候使用NSMutableArray,什么时候使用NSArray?
答:当数组在程序运行时,需要不断变化的,使用NSMutableArray,当数组在初始化后,便不再改变的,使用NSArray。需要指出的是,使用NSArray只表明的是该数组在运行时不发生改变,即不能往NSAarry的数组里新增和删除元素,但不表明其数组內的元素的内容不能发生改变。NSArray是线程安全的,NSMutableArray不是线程安全的,多线程使用到NSMutableArray需要注意。
给出委托方法的实例,并且说出UITableVIew的Data Source方法
答:CocoaTouch框架中用到了大量委托,其中UITableViewDelegate就是委托机制的典型应用,是一个典型的使用委托来实现适配器模式,其中UITableViewDelegate协议是目标,tableview是适配器,实现UITableViewDelegate协议,并将自身设置为talbeview的delegate的对象,是被适配器,一般情况下该对象是UITableViewController。
UITableVIew的Data Source方法有- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
(UITableViewCell )tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
在应用中可以创建多少autorelease对象,是否有限制?
答案:无
如果我们不创建内存池,是否有内存池提供给我们?
答:界面线程维护着自己的内存池,用户自己创建的数据线程,则需要创建该线程的内存池
什么时候需要在程序中创建内存池?
答:用户自己创建的数据线程,则需要创建该线程的内存池
类NSObject的那些方法经常被使用?
答:NSObject是Objetive-C的基类,其由NSObject类及一系列协议构成。
其中类方法alloc、class、description对象方法init、dealloc、– performSelector:withObject:afterDelay:等经常被使用
什么是简便构造方法?
答:简便构造方法一般由CocoaTouch框架提供,如NSNumber的+ numberWithBool: + numberWithChar: + numberWithDouble: + numberWithFloat: + numberWithInt:
Foundation下大部分类均有简便构造方法,我们可以通过简便构造方法,获得系统给我们创建好的对象,并且不需要手动释放。
如何使用Xcode设计通用应用?
答:使用MVC模式设计应用,其中Model层完成脱离界面,即在Model层,其是可运行在任何设备上,在controller层,根据iPhone与iPad(独有UISplitViewController)的不同特点选择不同的viewController对象。在View层,可根据现实要求,来设计,其中以xib文件设计时,其设置其为universal。
UIView的动画效果有那些?
答:有很多,如UIViewAnimationOptionCurveEaseInOut UIViewAnimationOptionCurveEaseIn UIViewAnimationOptionCurveEaseOut UIViewAnimationOptionTransitionFlipFromLeft UIViewAnimationOptionTransitionFlipFromRight UIViewAnimationOptionTransitionCurlUpUIViewAnimationOptionTransitionCurlDown
在iPhone应用中如何保存数据?
答:有以下几种保存机制:
1).通过web服务,保存在服务器上
2).通过NSCoder固化机制,将对象保存在文件中
3).通过SQlite或CoreData保存在文件数据库中
什么是coredata?
答:coredata是苹果提供一套数据保存框架,其基于SQlite
什么是NSManagedObject模型?
答:NSManagedObject是NSObject的子类 ,也是coredata的重要组成部分,它是一个通用的类,实现了core data模型层所需的基本功能,用户可通过子类化NSManagedObject,建立自己的数据模型。
什么是NSManagedobjectContext?
答:NSManagedobjectContext对象负责应用和数据库之间的交互。
什么是谓词?
答:谓词是通过NSPredicate,是通过给定的逻辑条件作为约束条件,完成对数据的筛选。
predicate = [NSPredicate predicateWithFormat:@"customerID == %d",n];
a = [customers filteredArrayUsingPredicate:predicate];
和coredata一起有哪几种持久化存储机制?
答:存入到文件、 存入到NSUserDefaults(系统plist文件中)、存入到Sqlite文件数据库
谈谈对Block的理解?并写出一个使用Block执行UIVew动画?
答:Block是可以获取其他函数局部变量的匿名函数,其不但方便开发,并且可以大幅提高应用的执行效率(多核心CPU可直接处理Block指令)
[UIView transitionWithView:self.view
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{ [[blueViewController view] removeFromSuperview]; [[ self view] insertSubview:yellowViewController.view atIndex:0]; }
completion: NULL];
写出上面代码的Block的定义。
答:
typedef void(^animations) (void);
typedef void(^completion) (BOOL finished);
试着使用+ beginAnimations:context:以及上述Block的定义,写出一个可以完成
(void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void(^)(void))animations completion:(void(^)(BOOLfinished))completion NS_AVAILABLE_IOS(4_0);操作的函数执行部分
答案:无
做过的项目是否涉及网络访问功能,使用什么对象完成网络功能?
答:ASIHTTPRequest与NSURLConnection
简单介绍下NSURLConnection类及+ sendSynchronousRequest:returningResponse:error:与– initWithRequest:delegate:两个方法的区别?
答: NSURLConnection主要用于网络访问,其中+ sendSynchronousRequest:returningResponse:error:是同步访问数据,即当前线程会阻塞,并等待request的返回的response,而– initWithRequest:delegate:使用的是异步加载,当其完成网络访问后,会通过delegate回到主线程,并其委托的对象。
多线程是什么
答:多线程是个复杂的概念,按字面意思是同步完成多项任务,提高了资源的使用效率,从硬件、操作系统、应用软件不同的角度去看,多线程被赋予不同的内涵,对于硬件,现在市面上多数的CPU都是多核的,多核的CPU运算多线程更为出色;从操作系统角度,是多任务,现在用的主流操作系统都是多任务的,可以一边听歌、一边写博客;对于应用来说,多线程可以让应用有更快的回应,可以在网络下载时,同时响应用户的触摸操作。在iOS应用中,对多线程最初的理解,就是并发,它的含义是原来先做烧水,再摘菜,再炒菜的工作,会变成烧水的同时去摘菜,最后去炒菜。
iOS中的多线程
答: iOS中的多线程,是Cocoa框架下的多线程,通过Cocoa的封装,可以让我们更为方便的使用线程,做过C++的同学可能会对线程有更多的理解,比如线程的创立,信号量、共享变量有认识,Cocoa框架下会方便很多,它对线程做了封装,有些封装,可以让我们创建的对象,本身便拥有线程,也就是线程的对象化抽象,从而减少我们的工程,提供程序的健壮性。
GCD是(Grand Central Dispatch)的缩写 ,从系统级别提供的一个易用地多线程类库,具有运行时的特点,能充分利用多核心硬件。GCD的API接口为C语言的函数,函数参数中多数有Block,关于Block的使用参看这里,为我们提供强大的“接口”,对于GCD的使用参见本文
NSOperation与Queue
NSOperation是一个抽象类,它封装了线程的细节实现,我们可以通过子类化该对象,加上NSQueue来同面向对象的思维,管理多线程程序。具体可参看这里:一个基于NSOperation的多线程网络访问的项目。
NSThread
NSThread是一个控制线程执行的对象,它不如NSOperation抽象,通过它我们可以方便的得到一个线程,并控制它。但NSThread的线程之间的并发控制,是需要我们自己来控制的,可以通过NSCondition实现。
参看iOS多线程编程之NSThread的使用
其他多线程
在Cocoa的框架下,通知、Timer和异步函数等都有使用多线程,(待补充).
在项目什么时候选择使用GCD,什么时候选择NSOperation?
答:项目中使用NSOperation的优点是NSOperation是对线程的高度抽象,在项目中使用它,会使项目的程序结构更好,子类化NSOperation的设计思路,是具有面向对象的优点(复用、封装),使得实现是多线程支持,而接口简单,建议在复杂项目中使用。
项目中使用GCD的优点是GCD本身非常简单、易用,对于不复杂的多线程操作,会节省代码量,而Block参数的使用,会是代码更为易读,建议在简单项目中使用。
什么是block
答:对于闭包(block),有很多定义,其中闭包就是能够读取其它函数内部变量的函数,这个定义即接近本质又较好理解。对于刚接触Block的同学,会觉得有些绕,因为我们习惯写这样的程序main(){ funA();} funA(){funB();} funB(){…..};就是函数main调用函数A,函数A调用函数B…函数们依次顺序执行,但现实中不全是这样的,例如项目经理M,手下有3个程序员A、B、C,当他给程序员A安排实现功能F1时,他并不等着A完成之后,再去安排B去实现F2,而是安排给A功能F1,B功能F2,C功能F3,然后可能去写技术文档,而当A遇到问题时,他会来找项目经理M,当B做完时,会通知M,这就是一个异步执行的例子。在这种情形下,Block便可大显身手,因为在项目经理M,给A安排工作时,同时会告诉A若果遇到困难,如何能找到他报告问题(例如打他手机号),这就是项目经理M给A的一个回调接口,要回掉的操作,比如接到电话,百度查询后,返回网页内容给A,这就是一个Block,在M交待工作时,已经定义好,并且取得了F1的任务号(局部变量),却是在当A遇到问题时,才调用执行,跨函数在项目经理M查询百度,获得结果后回调该block。
block实现原理
答: Objective-C是对C语言的扩展,block的实现是基于指针和函数指针。
从计算语言的发展,最早的goto,高级语言的指针,到面向对象语言的block,从机器的思维,一步步接近人的思维,以方便开发人员更为高效、直接的描述出现实的逻辑(需求)。
使用实例
cocoaTouch框架下动画效果的Block的调用
使用typed声明block
typedef void(^didFinishBlock) (NSObject *ob);
这就声明了一个didFinishBlock类型的block,
然后便可用
@property (nonatomic,copy) didFinishBlock finishBlock;
声明一个blokc对象,注意对象属性设置为copy,接到block参数时,便会自动复制一份。
__block是一种特殊类型,
使用该关键字声明的局部变量,可以被block所改变,并且其在原函数中的值会被改变。
关于block
答:面试时,面试官会先问一些,是否了解block,是否使用过block,这些问题相当于开场白,往往是下面一系列问题的开始,所以一定要如实根据自己的情况回答。
1).使用block和使用delegate完成委托模式有什么优点?
首先要了解什么是委托模式,委托模式在iOS中大量应用,其在设计模式中是适配器模式中的对象适配器,Objective-C中使用id类型指向一切对象,使委托模式更为简洁。了解委托模式的细节:
iOS设计模式—-委托模式
使用block实现委托模式,其优点是回调的block代码块定义在委托对象函数内部,使代码更为紧凑;
适配对象不再需要实现具体某个protocol,代码更为简洁。
2).多线程与block
GCD与Block
使用dispatch_async系列方法,可以以指定的方式执行block
GCD编程实例
dispatch_async的完整定义
void dispatch_async(
dispatch_queue_t queue,
dispatch_block_t block);
功能:在指定的队列里提交一个异步执行的block,不阻塞当前线程
通过queue来控制block执行的线程。主线程执行前文定义的finishBlock对象
dispatch_async(dispatch_get_main_queue(),^(void){finishBlock();});
62.谈谈Object-C的内存管理方式及过程?
答: 1).当你使用new,alloc和copy方法创建一个对象时,该对象的保留计数器值为1.当你不再使用该对象时,你要负责向该对象发送一条release或autorelease消息.这样,该对象将在使用寿命结束时被销毁.
2).当你通过任何其他方法获得一个对象时,则假设该对象的保留计数器值为1,而且已经被设置为自动释放,你不需要执行任何操作来确保该对象被清理.如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它.
3).如果你保留了某个对象,你需要(最终)释放或自动释放该对象.必须保持retain方法和release方法的使用次数相等.
63.Object-C有私有方法吗?私有变量呢?
答: objective-c –类里面的方法只有两种,静态方法和实例方法.这似乎就不是完整的面向对象了,按照OO的原则就是一个对象只暴露有用的东西.如果没有了私有方法的话,对于一些小范围的代码重用就不那么顺手了.在类里面声名一个私有方法
@interface Controller : NSObject { NSString *something; }
(void)thisIsAStaticMethod;
– (void)thisIsAnInstanceMethod;
@end
@interface Controller (private) -
(void)thisIsAPrivateMethod;
@end
@private可以用来修饰私有变量
在Objective‐C中,所有实例变量默认都是私有的,所有实例方法默认都是公有的
64.Object-C有多继承吗?没有的话用什么代替?cocoa中所有的类都是NSObject的子类
答:多继承在这里是用protocol委托代理 来实现的
你不用去考虑繁琐的多继承,虚基类的概念.
ood的多态特性 在obj-c中通过委托来实现.
65.内存管理Autorelease、retain、copy、assign的set方法和含义?
答: 1).你初始化(alloc/init)的对象,你需要释放(release)它。例如:
NSMutableArray aArray = [[NSArray alloc] init];后,需要[aArray release];
2).你retain或copy的,你需要释放它。例如:
[aArray retain]后,需要[aArray release];
3).被传递(assign)的对象,你需要斟酌的retain和release。例如:
obj2 = [[obj1 someMethod] autorelease];
对象2接收对象1的一个自动释放的值,或传递一个基本数据类型(NSInteger,NSString)时:你或希望将对象2进行retain,以防止它在被使用之前就被自动释放掉。但是在retain后,一定要在适当的时候进行释放。
关于索引计数(Reference Counting)的问题
retain值=索引计数(Reference Counting)
NSArray对象会retain(retain值加一)任何数组中的对象。当NSArray被卸载(dealloc)的时候,所有数组中的对象会 被 执行一次释放(retain值减一)。不仅仅是NSArray,任何收集类(Collection Classes)都执行类似操作。例如NSDictionary,甚至UINavigationController。
Alloc/init建立的对象,索引计数为1。无需将其再次retain。
[NSArray array]和[NSDate date]等“方法”建立一个索引计数为1的对象,但是也是一个自动释放对象。所以是本地临时对象,那么无所谓了。如果是打算在全Class中使用的变量(iVar),则必须retain它。
缺省的类方法返回值都被执行了“自动释放”方法。(*如上中的NSArray)
在类中的卸载方法“dealloc”中,release所有未被平衡的NS对象。(*所有未被autorelease,而retain值为1的)
C和obj-c如何混用
答: 1).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。
总结:只要cpp文件和cpp include的文件中不包含obj-c的东西就可以用了,cpp混用obj-c的关键是使用接口,而不能直接使用 实现代 码,实际上cpp混用的是obj-c编译后的o文件,这个东西其实是无差别的,所以可以用。obj-c的编译器支持cpp
Objective-C堆和栈的区别?
答:管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。
申请大小:
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因 此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出
分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。
ViewController的didReceiveMemoryWarning怎么被调用:
答:[supper didReceiveMemoryWarning];
69.什么时候用delegate,什么时候用Notification?
答: delegate针对one-to-one关系,用于sender接受到reciever的某个功能反馈值。
notification针对one-to-one/many/none,reciver,用于通知多个object某个事件。
70.用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
答:
define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
我在这想看到几件事情:
define语法的基本知识(例如:不能以分号结束,括号的使用,等等)
懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。
71.写一个”标准"宏MIN,这个宏输入两个参数并返回较小的一个。
答:
define MIN(A,B)((A)<= (B) ? (A) : (B))
这个测试是为下面的目的而设的:
标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方
法,
对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。
三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。
懂得在宏中小心地把参数用括号括起来
我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?
least = MIN(*p++, b);
结果是:
((p++) <= (b) ? (p++) : (*p++))
这个表达式会产生副作用,指针p会作三次++自增操作。
72.关键字const有什么含意?修饰类呢?static的作用,用于类呢?还有externc的作用
答:
const意味着"只读",下面的声明都是什么意思?
const inta;
int consta;
const int*a;
int*consta;
int const* aconst;
前两个的作用是一样,a是一个常整型数。
第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。
第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。
最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。
结论:
关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。
如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的) 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。
1).欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初
始化,因为以后就没有机会再去改变它了;
2).对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指
定为const;
3).在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
4).对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;
5).对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。
关键字volatile有什么含意?并给出三个不同的例子。
答:一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
下面是volatile变量的几个例子:
并行设备的硬件寄存器(如:状态寄存器)
一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
多线程应用中被几个任务共享的变量
一个参数既可以是const还可以是volatile吗? 一个指针可以是volatile吗?解释为什么。
答:1).是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
2).是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
75 .static关键字的作用:
答:
1).函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,
因此其值在下次调用时仍维持上次的值;
2).在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
3).在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明
它的模块内;
4).在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
5).在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。
线程与进程的区别和联系?
答:
1).进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性
2).进程和线程的主要差别在于它们是不同的操作系统资源管理方式。
3).进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。
4.)线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉。所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。
5).但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
列举几种进程的同步机制,并比较其优缺点。
答: 原子操作 信号量机制 自旋锁 管程,会合,分布式系统
进程之间通信的途径
答:共享存储系统消息传递系统管道:以文件系统为基础
进程死锁的原因
答:资源竞争及进程推进顺序非法
死锁的4个必要条件
答:互斥、请求保持、不可剥夺、环路
死锁的处理
答:鸵鸟策略、预防策略、避免策略、检测与解除死锁
cocoa touch框架
答:iPhone OS应用程序的基础Cocoa Touch框架重用了许多Mac系统的成熟模式,但是它更多地专注于触摸的接口和优化。
UIKit为您提供了在iPhone OS上实现图形,事件驱动程序的基本工具,其建立在和Mac OS X中一样的Foundation框架上,包括文件处理,网络,字符串操作等。
Cocoa Touch具有和iPhone用户接口一致的特殊设计。有了UIKit,您可以使用iPhone OS上的独特的图形接口控件,按钮,以及全屏视图的功能,您还可以使用加速仪和多点触摸手势来控制您的应用。
各色俱全的框架 除了UIKit外,Cocoa Touch包含了创建世界一流iPhone应用程序需要的所有框架,从三维图形,到专业音效,甚至提供设备访问API以控制摄像头,或通过GPS获知当前位置。
Cocoa Touch既包含只需要几行代码就可以完成全部任务的强大的Objective-C框架,也在需要时提供基础的C语言API来直接访问系统。这些框架包括:
Core Animation:通过Core Animation,您就可以通过一个基于组合独立图层的简单的编程模型来创建丰富的用户体验。
Core Audio:Core Audio是播放,处理和录制音频的专业技术,能够轻松为您的应用程序添加强大的音频功能。
Core Data:提供了一个面向对象的数据管理解决方案,它易于使用和理解,甚至可处理任何应用或大或小的数据模型。
功能列表:框架分类
下面是Cocoa Touch中一小部分可用的框架:
音频和视频:Core Audio,OpenAL,Media Library,AV Foundation
数据管理 :Core Data,SQLite
图形和动画 :Core Animation,OpenGL ES,Quartz 2D
网络:Bonjour,WebKit,BSD Sockets
用户应用:Address Book,Core Location,Map Kit,Store Kit
自动释放池是什么,如何工作
答:当您向一个对象发送一个autorelease消息时,Cocoa就会将该对象的一个引用放入到最新的自动释放.它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。当程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放。
Objective-C的优缺点。
答:objc优点:
1). Cateogies
2). Posing
3).动态识别
4).指标计算
5).弹性讯息传递
6).不是一个过度复杂的C衍生语言
7).Objective-C与C++可混合编程
objc缺点:
1).不支援命名空间
2).不支持运算符重载
3).不支持多重继承
4).使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优化方法都用不到。(如内联函数等),性能低劣。
sprintf,strcpy,memcpy使用上有什么要注意的地方。
答:
1). sprintf是格式化函数。将一段数据通过特定的格式,格式化到一个字符串缓冲区中去。sprintf格式化的函数的长度不可控,有可能格式化后的字符串会超出缓冲区的大小,造成溢出。
2).strcpy是一个字符串拷贝的函数,它的函数原型为strcpy(chardst,const charsrc将src开始的一段字符串拷贝到dst开始的内存中去,结束的标志符号为‘\0',由于拷贝的长度不是由我们自己控制的,所以这个字符串拷贝很容易出错。
3). memcpy是具备字符串拷贝功能的函数,这是一个内存拷贝函数,它的函数原型为memcpy(chardst,const charsrc,unsigned intlen);将长度为len的一段内存,从src拷贝到dst中去,这个函数的长度可控。但是会有内存叠加的问题。
readwrite,readonly,assign,retain,copy,nonatomic属性的作用
答:@property是一个属性访问声明,扩号内支持以下几个属性:
1).getter=getterName,setter=setterName,设置setter与getter的方法名
2).readwrite,readonly,设置可供访问级别
2).assign,setter方法直接赋值,不进行任何retain操作,为了解决原类型与环循引用问题
3).retain,setter方法对参数进行release旧值再retain新值,所有实现都是这个顺序(CC上有相关资料)
4).copy,setter方法进行Copy操作,与retain处理流程一样,先旧值release,再Copy出新的对象,retainCount为1。这是为了减少对上下文的依赖而引入的机制。
5).nonatomic,非原子性访问,不加同步,多线程并发访问会提高性能。注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。锁被加到所属对象实例级。
http和scoket通信的区别。
答:http是客户端用http协议进行请求,发送请求时候需要封装http请求头,并绑定请求的数据,服务器一般有web服务器配合(当然也非绝对)。http请求方式为客户端主动发起请求,服务器才能给响应,一次请求完毕后则断开连接,以节省资源。服务器不能主动给客户端响应(除非采取http长连接 技术)。iphone主要使用类是NSUrlConnection。
scoket是客户端跟服务器直接使用socket“套接字”进行连接,并没有规定连接后断开,所以客户端和服务器可以保持连接通道,双方 都可以主动发送数据。一般在游戏开发或股票开发这种要求即时性很强并且保持发送数据量比较大的场合使用。主要使用类是CFSocketRef。
TCP和UDP的区别
答:TCP全称是Transmission Control Protocol,中文名为传输控制协议,它可以提供可靠的、面向连接的网络数据传递服务。传输控制协议主要包含下列任务和功能:
确保IP数据报的成功传递。
对程序发送的大块数据进行分段和重组。
确保正确排序及按顺序传递分段的数据。
通过计算校验和,进行传输数据的完整性检查。
TCP提供的是面向连接的、可靠的数据流传输,而UDP提供的是非面向连接的、不可靠的数据流传输。
简单的说,TCP注重数据安全,而UDP数据传输快点,但安全性一般
你了解svn,cvs等版本控制工具么?
答: 版本控制svn,cvs是两种版控制的器,需要配套相关的svn,cvs服务器。
scm是xcode里配置版本控制的地方。版本控制的原理就是a和b同时开发一个项目,a写完当天的代码之后把代码提交给服务器,b要做的时候先从服务器得到最新版本,就可以接着做。 如果a和b都要提交给服务器,并且同时修改了同一个方法,就会产生代码冲突,如果a先提交,那么b提交时,服务器可以提示冲突的代码,b可以清晰的看到,并做出相应的修改或融合后再提交到服务器。
什么是push。
答: 客户端程序留下后门端口,客户端总是监听针对这个后门的请求,于是 服务器可以主动像这个端口推送消息。
静态链接库
答:此为.a文件,相当于java里的jar包,把一些类编译到一个包中,在不同的工程中如果导入此文件就可以使用里面的类,具体使用依然是#import “ xx.h”。
fmmpeg框架
答: 音视频编解码框架,内部使用UDP协议针对流媒体开发,内部开辟了六个端口来接受流媒体数据,完成快速接受之目的。
fmdb框架
答:数据库框架,对sqllite的数据操作进行了封装,使用着可把精力都放在sql语句上面。
320框架
答:ui框架,导入320工程作为框架包如同添加一个普通框架一样。cover(open) flower框架(2d仿射技术),内部核心类是CATransform3D.
什么是沙盒模型?哪些操作是属于私有api范畴?
答:某个iphone工程进行文件操作有此工程对应的指定的位置,不能逾越。
iphone沙箱模型的有四个文件夹documents,tmp,app,Library,永久数据存储一般放documents文件夹,得到模拟器的路径的可使用NSHomeDirectory()方法。Nsuserdefaults保存的文件在tmp文件夹里。
在一个对象的方法里面:self.name= “object”;和name =”object”有什么不同吗?
答:self.name =”object”:会调用对象的setName()方法;
name = “object”:会直接把object赋值给当前对象的name属性。
请简要说明viewDidLoad和viewDidUnload何时调用
答:viewDidLoad在view从nib文件初始化时调用,loadView在controller的view为nil时调用。此方法在编程实现view时调用,view控制器默认会注册memory warning notification,当view controller的任何view没有用的时候,viewDidUnload会被调用,在这里实现将retain的view release,如果是retain的IBOutletview属性则不要在这里release,IBOutlet会负责release。
简述内存分区情况
答:
1).代码区:存放函数二进制代码
2).数据区:系统运行时申请内存并初始化,系统退出时由系统释放。存放全局变量、静态变量、常量
3).堆区:通过malloc等函数或new等操作符动态申请得到,需程序员手动申请和释放
4).栈区:函数模块内申请,函数结束时由系统自动释放。存放局部变量、函数参数
队列和栈有什么区别:
答:队列和栈是两种不同的数据容器。从”数据结构”的角度看,它们都是线性结构,即数据元素之间的关系相同。
队列是一种先进先出的数据结构,它在两端进行操作,一端进行入队列操作,一端进行出列队操作。
栈是一种先进后出的数据结构,它只能在栈顶进行操作,入栈和出栈都在栈顶操作。
HTTP协议中,POST和GET的区别是什么?
答:
1).GET方法
GET方法提交数据不安全,数据置于请求行,客户端地址栏可见;
GET方法提交的数据大小有限
GET方法不可以设置书签
2).POST方法
POST方法提交数据安全,数据置于消息主体内,客户端不可见
POST方法提交的数据大小没有限制
POST方法可以设置书签
iOS的系统架构
答:iOS的系统架构分为( 核心操作系统层theCore OS layer)、( 核心服务层theCore Services layer)、( 媒体层theMedia layer)和(Cocoa界面服务层the Cocoa Touch layer)四个层次。
控件主要响应3种事件
答:1).基于触摸的事件; 2).基于值的事件; 3).基于编辑的事件。
xib文件的构成分为哪3个图标?都具有什么功能。
答:File’s Owner是所有nib文件中的每个图标,它表示从磁盘加载nib文件的对象;
First Responder就是用户当前正在与之交互的对象;
View显示用户界面;完成用户交互;是UIView类或其子类。
简述视图控件器的生命周期。
答:loadView尽管不直接调用该方法,如多手动创建自己的视图,那么应该覆盖这个方法并将它们赋值给试图控制器的view属性。
viewDidLoad只有在视图控制器将其视图载入到内存之后才调用该方法,这是执行任何其他初始化操作的入口。
viewDidUnload当试图控制器从内存释放自己的方法的时候调用,用于清楚那些可能已经在试图控制器中创建的对象。
viewVillAppear当试图将要添加到窗口中并且还不可见的时候或者上层视图移出图层后本视图变成顶级视图时调用该方法,用于执行诸如改变视图方向等的操作。实现该方法时确保调用[superviewWillAppear:
viewDidAppear当视图添加到窗口中以后或者上层视图移出图层后本视图变成顶级视图时调用,用于放置那些需要在视图显示后执行的代码。确保调用[superviewDidAppear:]。
动画有基本类型有哪几种;表视图有哪几种基本样式。
答:动画有两种基本类型:隐式动画和显式动画。
实现简单的表格显示需要设置UITableView的什么属性、实现什么协议?
答:实现简单的表格显示需要设置UITableView的dataSource和delegate属性,实现UITableViewDataSource和UITableViewDelegate协议。
Cocoa Touch提供了哪几种Core Animation过渡类型?
答:Cocoa Touch提供了4种Core Animation过渡类型,分别为:交叉淡化、推挤、显示和覆盖。
UIView与CLayer有什么区别?
答:
1).UIView是iOS系统中界面元素的基础,所有的界面元素都是继承自它。它本身完全是由CoreAnimation来实现的。它真正的绘图部分,是由一个CALayer类来管理。UIView本身更像是一个CALayer的管理器,访问它的跟绘图和跟坐标有关的属性。
2).UIView有个重要属性layer,可以返回它的主CALayer实例。
3).UIView的CALayer类似UIView的子View树形结构,也可以向它的layer上添加子layer,来完成某些特殊的表示。即CALayer层是可以嵌套的。
4).UIView的layer树形在系统内部,被维护着三份copy。分别是逻辑树,这里是代码可以操纵的;动画树,是一个中间层,系统就在这一层上更改属性,进行各种渲染操作;显示树,其内容就是当前正被显示在屏幕上得内容。
5).动画的运作:对UIView的subLayer(非主Layer)属性进行更改,系统将自动进行动画生成,动画持续时间的缺省值似乎是0.5秒。
6).坐标系统:CALayer的坐标系统比UIView多了一个anchorPoint属性,使用CGPoint结构表示,值域是0~1,是个比例值。这个点是各种图形变换的坐标原点,同时会更改layer的position的位置,它的缺省值是{0.5,0.5},即在layer的中央。
7).渲染:当更新层,改变不能立即显示在屏幕上。当所有的层都准备好时,可以调用setNeedsDisplay方法来重绘显示。
8).变换:要在一个层中添加一个3D或仿射变换,可以分别设置层的transform或affineTransform属性。
9).变形:Quartz Core的渲染能力,使二维图像可以被自由操纵,就好像是三维的。图像可以在一个三维坐标系中以任意角度被旋转,缩放和倾斜。CATransform3D的一套方法提供了一些魔术般的变换效果。
Quatrz 2D的绘图功能的三个核心概念是什么并简述其作用。
答:上下文:主要用于描述图形写入哪里;
路径:是在图层上绘制的内容;
状态:用于保存配置变换的值、填充和轮廓,alpha值等。
iPhone OS主要提供了几种播放音频的方法?
答:SystemSound Services
AVAudioPlayer类
Audio Queue Services
OpenAL
使用AVAudioPlayer类调用哪个框架、使用步骤?
答:AVFoundation.framework
步骤:配置AVAudioPlayer对象;
实现AVAudioPlayer类的委托方法;
控制AVAudioPlayer类的对象;
监控音量水平;
回放进度和拖拽播放。
有哪几种手势通知方法、写清楚方法名?
答:
-(void)touchesBegan:(NSSet)touchedwithEvent:(UIEvent)event;
-(void)touchesMoved:(NSSet)touched withEvent:(UIEvent)event;
-(void)touchesEnded:(NSSet)touchedwithEvent:(UIEvent)event;
-(void)touchesCanceled:(NSSet)touchedwithEvent:(UIEvent)event;
CFSocket使用有哪几个步骤。
答:创建Socket的上下文;创建Socket;配置要访问的服务器信息;封装服务器信息;连接服务器;
Core Foundation中提供了哪几种操作Socket的方法?
答:CFNetwork、CFSocket和BSD Socket。
解析XML文件有哪几种方式?
答:以DOM方式解析XML文件;以SAX方式解析XML文件;
ios平台怎么做数据的持久化?coredata和sqlite有无必然联系?coredata是一个关系型数据库吗?
答:iOS中可以有四种持久化数据的方式:属性列表(plist)、对象归档、SQLite3和Core Data;core data可以使你以图形界面的方式快速的定义app的数据模型,同时在你的代码中容易获取到它。coredata提供了基础结构去处理常用的功能,例如保存,恢复,撤销和重做,允许你在app中继续创建新的任务。在使用core data的时候,你不用安装额外的数据库系统,因为core data使用内置的sqlite数据库。core data将你app的模型层放入到一组定义在内存中的数据对象。coredata会追踪这些对象的改变,同时可以根据需要做相反的改变,例如用户执行撤销命令。当core data在对你app数据的改变进行保存的时候,core data会把这些数据归档,并永久性保存。mac os x中sqlite库,它是一个轻量级功能强大的关系数据引擎,也很容易嵌入到应用程序。可以在多个平台使用,sqlite是一个轻量级的嵌入式sql数据库编程。与core data框架不同的是,sqlite是使用程序式的,sql的主要的API来直接操作数据表。Core Data不是一个关系型数据库,也不是关系型数据库管理系统(RDBMS)。虽然Core Dta支持SQLite作为一种存储类型,但它不能使用任意的SQLite数据库。Core Data在使用的过程种自己创建这个数据库。Core Data支持对一、对多的关系。
tableView的重用机制?
答:UITableView通过重用单元格来达到节省内存的目的:通过为每个单元格指定一个重用标识符(reuseIdentifier),即指定了单元格的种类,以及当单元格滚出屏幕时,允许恢复单元格以便重用.对于不同种类的单元格使用不同的ID,对于简单的表格,一个标识符就够了.
#父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。
•深拷贝同浅拷贝的区别:浅拷贝是指针拷贝,对一个对象进行浅拷贝,相当于对指向对象的指针进行复制,产生一个新的指向这个对象的指针,那么就是有两 个指针指向同一个对象,这个对象销毁后两个指针都应该置空。深拷贝是对一个对象进行拷贝,相当于对对象进行复制,产生一个新的对象,那么就有两个指针分别 指向两个对象。当一个对象改变或者被销毁后拷贝出来的新的对象不受影响。
•实现深拷贝需要实现NSCoying协议,实现- (id)copyWithZone:(NSZone *)zone方法。当对一个property属性含有copy修饰符的时候,在进行赋值操作的时候实际上就是调用这个方法。
•父类实现深拷贝之后,子类只要重写copyWithZone方法,在方法内部调用父类的copyWithZone方法,之后实现自己的属性的处理
•父类没有实现深拷贝,子类除了需要对自己的属性进行处理,还要对父类的属性进行处理。
#KVO,NSNotification,delegate及block区别
• KVO就是cocoa框架实现的观察者模式,一般同KVC搭配使用,通过KVO可以监测一个值的变化,比如View的高度变化。是一对多的关系,一个值的变化会通知所有的观察者。
• NSNotification是通知,也是一对多的使用场景。在某些情况下,KVO和NSNotification是一样的,都是状态变化之后告知 对方。NSNotification的特点,就是需要被观察者先主动发出通知,然后观察者注册监听后再来进行响应,比KVO多了发送通知的一步,但是其优 点是监听不局限于属性的变化,还可以对多种多样的状态变化进行监听,监听范围广,使用也更灵活。
• delegate是代理,就是我不想做的事情交给别人做。比如狗需要吃饭,就通过delegate通知主人,主人就会给他做饭、盛饭、倒水,这些操作,这些狗都不需要关 心,只需要调用delegate(代理人)就可以了,由其他类完成所需要的操作。所以delegate是一对一关系。
• block是delegate的另一种形式,是函数式编程的一种形式。使用场景跟delegate一样,相比delegate更灵活,而且代理的实现更直观。
• KVO一般的使用场景是数据,需求是数据变化,比如股票价格变化,我们一般使用KVO(观察者模式)。delegate一般的使用场景是行为,需求是需要别人帮我做一件事情,比如买卖股票,我们一般使用delegate。
Notification一般是进行全局通知,比如利好消息一出,通知大家去买入。delegate是强关联,就是委托和代理双方互相知道,你委托别人买股票你就需要知道经纪人, 经纪人也不要知道自己的顾客。Notification是弱关联,利好消息发出,你不需要知道是谁发的也可以做出相应的反应,同理发消息的人也不需要知道 接收的人也可以正常发出消息。
#KVC如果实现,如何进行键值查找。KVO如何实现
请看这两篇博文 KVC KVO
#将一个函数在主线程执行的4种方法
• GCD方法,通过向主线程队列发送一个block块,使block里的方法可以在主线程中执行。
dispatch_async(dispatch_get_main_queue(), ^{
//需要执行的方法
});
• NSOperation方法
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; //主队列
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
//需要执行的方法
}];
[mainQueue addOperation:operation];
• NSThread方法
[self performSelector:@selector(method) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES modes:nil];
[self performSelectorOnMainThread:@selector(method) withObject:nil waitUntilDone:YES];
[[NSThread mainThread] performSelector:@selector(method) withObject:nil];
• RunLoop方法
[[NSRunLoop mainRunLoop] performSelector:@selector(method) withObject:nil];
#如何让计时器调用一个类方法
•计时器只能调用实例方法,但是可以在这个实例方法里面调用静态方法。
•使用计时器需要注意,计时器一定要加入RunLoop中,并且选好model才能运行。scheduledTimerWithTimeInterval方法创建一个计时器并加入到RunLoop中所以可以直接使用。
•如果计时器的repeats选择YES说明这个计时器会重复执行,一定要在合适的时机调用计时器的invalid。不能在dealloc中调用, 因为一旦设置为repeats为yes,计时器会强持有self,导致dealloc永远不会被调用,这个类就永远无法被释放。比如可以在viewDidDisappear中调用,这 样当类需要被回收的时候就可以正常进入dealloc中了。
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
-(void)timerMethod
{
//调用类方法
[[ self class] staticMethod];
}
-(void)invalid
{
[timer invalid];
timer = nil;
}
#如何重写类方法
• 1、在子类中实现一个同基类名字一样的静态方法
• 2、在调用的时候不要使用类名调用,而是使用[self class]的方式调用。原理,用类名调用是早绑定,在编译期绑定,用[self class]是晚绑定,在运行时决定调用哪个方法。
#NSTimer创建后,会在哪个线程运行。
•用scheduledTimerWithTimeInterval创建的,在哪个线程创建就会被加入哪个线程的RunLoop中就运行在哪个线程
•自己创建的Timer,加入到哪个线程的RunLoop中就运行在哪个线程。
#1.8id和NSObject*的区别
•id是一个objc_object结构体指针,定义是
typedef struct objc_object *id
•id可以理解为指向对象的指针。所有oc的对象id都可以指向,编译器不会做类型检查,id调用任何存在的方法都不会在编译阶段报错,当然如果这个id指向的对象没有这个方法,该崩溃还是会崩溃的。
• NSObject *指向的必须是NSObject的子类,调用的也只能是NSObjec里面的方法否则就要做强制类型转换。
•不是所有的OC对象都是NSObject的子类,还有一些继承自NSProxy。NSObject *可指向的类型是id的子集。
以下内容后续补充
#iOS核心框架
• CoreAnimation
• CoreGraphics
• CoreLocation
• AVFoundation
• Foundation
#iOS核心机制
• UITableView重用
• ObjC内存管理;自动释放池,ARC如何实现
• runloop
• runtime
• Block的定义、特性、内存区域、如何实现
• Responder Chain
• NSOperation
#• GCD
#数据结构
• 8大排序算法
•二叉树实现
•二分查找实现
#面向对象编程
•封装、继承、多态
•设计模式6个原则
•设计一个类的功能,如何划分粒度(单一职责)
•接口隔离。
•如果有一个鸟类,有飞的动作,一个鸵鸟继承它是合适的吗(里氏替换)
•类之间的依赖如何依赖偶合度最小(依赖倒转)
高层依赖低层,低层不能依赖高层。依赖接口,不能依赖具体的类。
•如果A要调用C函数,但C是B的成员类,应该如何设计?(迪米特)
•如何设计类,能做到只增加代码,而不修改代码,有哪些经验(开放封闭)
通过设计模式解决。
#计算机技术
•计算机网络:TCP/IP、HTTPCDN、SPDY
•计算机安全:RSA、AES、DES
•操作系统:线程、进程、堆栈、死锁、调度算法
#iOS新特性、新技术
• iOS7 UIDynamic、SpritKit、新布局、扁平化
• iOS8应用程序扩展、HealthKit、SceneKit、CoreLocation、TouchID、PhotoKit
• iOS9
• Apple Watch
#•第三方库:SDWebImage、AFNetwork、JSONKit、wax
• swift
#****************************************************************************
#1.简述OC中内存管理机制.
答:内存管理机制:使用引用计数管理,分为ARC和MRC,MRC需要程序员自己管理内存,ARC则不需要.但是并不是所有对象在ARC环境下均不需要管理内存,子线程和循环引用并不是这样.与retain配对使用的是release,retain代表引用计数+1,release代表引用计数-1,当引用计数减为0时,对象则被系统自动销毁.与alloc配对使用的是dealloc,alloc代表为对象开辟内存空间,dealloc则代表销毁对象的内存空间.
#2.readwrite,readonly,assign,retain,copy,nonatomic,atomic,strong,weak的作用?
答:读写属性:readonly和readwrite; 语义属性:assign/retain/copy; 原子性:nonatomic.
①.readwrite代表可读,可写,即有setter和getter方法,是默认属性.readonly代表只可读,即只有get方法,因为不会生成setter方法,所以它不可以和copy/retain/assign组合使用.
②.weak和assign均是弱引用,assign修饰基本数据类型,weak修饰对象类型.strong和weak用于ARC下(ARC下的代理使用weak,block块使用copy).strong相当于retain.weak相当于assign;assign/retain/copy这些属性用于指定set访问器的语义,也就是说,这些属性决定了以何种方式对数据成员赋值.
assign,直接赋值,引用计数不改变,适用于基本数据类型.
retain,浅拷贝,使用的是原来的内存空间,只能适用于Objective-C对象类型,而不能适用于Core Foundation对象(retain会增加对象的引用计数,而基本数据和Core Foundation对象都没有引用计数).
copy:对象的拷贝,新申请一块内存空间,并把原始内容复制到那片空间.新对象的引用计数为1,此属性只对那些遵循了NSCopy协议的对象类型有效.
③.nonatomic,非原子性访问,不加同步,是异步操作.默认为atomic,原子操作,atomic是Objc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误,而这种机制是消耗系统内存资源的,所以在移动端,都选择nonatomic.
#另:内存分为5个区,分别是栈区,堆区,全局区,文字常量区,程序代码区.
栈区:由编译器自动分配释放,不需要管理内存.
堆区:一般有程序员分配释放.
全局区:存放全局变量和静态变量.
文字常量区:存放常量字符串.
程序代码区:存放二进制代码.
#3.类变量的@protected,@private,@public,@package,声明各有什么含义?
@protected受保护的.本类,子类可见.
@private私有的,类内可用
@public公有的,类内,子类,外部均可用
@package可见度在@protected和@public之间,这个类型最常用于框架类的实例变量.
#4.线程是什么?进程又是什么?区别和联系.
进程:正在运行的程序,负责程序的内存分配.
线程:线程是进程中一个独立执行的控制单元(路径),一个进程至少包含一条线程,即主线程.
创建线程的目的:开辟一条新的执行路径,运行指定的代码,与主线程的代码实现同时执行.
#5.对多线程开发的理解,iOS中有几种实现多线程的方式.
多线程的使用场景:防止卡顿,可以同时完成多个任务,且不影响主线程,把耗时操作放在子线程中执行,但是会消耗内存.
实现多线程的方式:①.NSThread(内存需要自己管理.触发),②.NSOperationQueue(不再关注线程,当前可执行任务个数queue.maxConcurrentOperationCount)③.GCD
#详解三种实现多线程的方式:
GCD:
GCD里面包含了串行队列、并行队列、主队列、全局队列。
Dispatch_queue_t q = dispatch_queue_create(“qqq”,DISPATCH_QUEUE_SERIAL);//创建一个串行队列
Dispatch_sync(q,^{
});//开启同步任务
Dispatch_async(q,^{
});//开启异步任务
并行队列:DISPATCH_QUEUE_CONCURRENT
主队列:dispatch_queue_t q = dispatch_get_main_queue();
全局队列:dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
NSThread
获取当前线程:NSThread * current = [NSThread currentThread];
获取主线程:NSThread * main = [NSThread mainThread];
使用NSThread创建线程的两种方式:
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;
- (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;
暂停当前线程:
[NSThread sleepForTimeInterval:2];
NSOperationQueue
创建一个操作队列:NSOperationQueue * queue = [[NSOperationQueue alloc]init];
添加NSOperation到NSOperationQueue中:[queue addOperation:operation];
添加一组operation:[queue addOperations:operations waitUntilFinished:NO];
添加一个block形式的operation:[queue addOperationWithBlock:^(){
}];
添加NSOperation的依赖对象:[operation2 addDependency:operation1];
设置队列的最大操作数:[queue setMaxConcurrentOperationCount:1];
等待options完成:[operation waitUntilFinished];
暂停、继续queue:[queue setSuspended:YES] [queue setSuspend:NO]
#6.线程同步和异步的区别?ios中如何实现线程的同步?
同步:任务顺序执行,下一个任务依赖于上一任务的完成.
异步:任务执行顺序不定,一起执行.
实现:设置依赖:NSOpreationQueue GCD中的串行队列.
#7.iOS类是否可以多继承,如果没有,怎么实现?
不可以多继承.
可以通过类目,延展,协议实现多继承.
类目:类目也叫分类,英文category,在没有原类.m文件的基础上,给该类添加方法.类目里不能添加实例变量,不能添加和原始类方法名相同的方法,否则会发生覆盖.一个类可以添加多个类目,类目中的方法可以成为原始类的一部分,和原始类方法级别相同,可以被子类继承.
延展:Extension,是一种特殊形式的类目,主要是在一个类的.m里面声明与实现.作用:就是给某类添加私有方法或者私有变量.
虽然延展是给一个类定义私有方法,但是OC没有绝对的私有方法,其实还是可以调用的,延展里面声明的变量只能在该类内部使用,外界访问不了.如果是新建文件建的的某类延展.h文件,则不能添加实例变量,如果括号里没有类目名,则认为延展里面的方法为全都必须实现,如果有,则可选实现.
类目写的方法必须实现,延展写的方法非必须.
#8.栈和堆的区别?
栈:内存系统管理(系统开辟,系统释放),先进后出.
堆:内存自己管理(自己开辟,自己释放).先进先出.
#9.iOS本地数据存储都有几种方式?
①.NSkeyedArchiver:采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法.前一个方法告诉系统怎么对对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码.
②.NSUserDefaults:用来保存应用程序设置和属性,用户保存的数据.用户再次打开程序或者开机后这些数据仍然存在.NSUserDefaults可以存储的数据类型包括:NSData,NSString,NSNumber,NSDate,NSArray.NSDictionary,其他类型的数据需要先行转换.
③.Write写入方式:永久保存在磁盘中.具体:a.获得文件保存的路径.b.生成该路径下的文件,c,往文件中写入数据.d.从文件中读出数据.
④.SQLite:采用SQLite数据库来存储数据,SQLite作为一种轻量级数据库.具体:a.添加SQLite相关的库以及头文件,b.使用数据库存数数据:打开数据库,编写数据库语句,执行,关闭数据库.另:写入数据库,字符串可以采用char方式,而从数据库中取出char类型,当char类型有表示中文字符时,会出现乱码,这是因为数据库默认使用ascII编码方式,所以想要正确从数据库中取出中文,需要使用NSString来接受从数据库取出的字符串.
⑤.CoreData:原理是对SQLite的封装,开发者不需要接触sql语句,就可以对数据库进行操作.
#10.ios动态类型和动态绑定
多态:父类指针指向子类对象.
动态类型:只有在运行期,才能确定其真正类型.
动态加载:根据不同的条件,加载不同的资源.32和64位.
#11.深拷贝和浅拷贝的理解.
深拷贝;拷贝的内容.
浅拷贝:拷贝的指针.
深拷贝如:
NSMutableDictionary * dic = [@{} mutableCopy];
NSMutableArray * ary = [@[] mutableCopy];
#12.怎么实现一个singleton的类.
单例是一种设计模式,对象只有一个.缺点:对象不会被释放,如果创建很多的话会占用很多内存,优点:可以当做工具类使用.
static SortDetailsModelDown * single = nil;
+(SortDetailsModelDown *)shareSortDetailsModelDown{
@synchronized(self){
if (!single) {
single = [[SortDetailsModelDown alloc]init];
}
}
return single;
}
#13.什么是安全释放?
先释放再置空.
#14.RunLoop是什么?
事件循环,是线程里面的一个组件.主线程的RunLoop是自动开启的.分为:计时源(timer source),事件源(输入源):input source.防止CPU中断(保证程序执行的线程不会被系统终止).
Runloop提供了一种异步执行代码的机制,并不能并行执行任务,是事件接收和分发机制的一个实现.每一个线程都有其对应的RunLoop,但是默认非主线程的RunLoop是没有运行的,需要为RunLoop添加至少一个事件源,然后run它.
一般情况下我们是没有必要去启动线程的RunLoop的,除非你在一个单独的线程中需要长时间的检测某个事件.
RunLoop,正如其名所示,是线程进入和被线程用来响应事件以及调用事件处理函数的地方.
input source传递异步事件,通常是来自其他线程和不同程序的消息.
timer source传递同步事件.
当有事件发生时,RunLoop会根据具体的事件类型通知应用程序作出响应.
当没有事件发生时,RunLoop会进入休眠状态,从而到达省电的目的.
当事件再次发生时,RunLoop会被重新唤醒,处理事件.
一般在开发中很少会主动创建RunLoop,而通常会把事件添加到RunLoop中.
#15.什么是序列化和反序列化,可以用来做什么?如何在OC中实现复杂对象的存储.
序列化和反序列化:归档和反归档,进行本地化,进行数据存储.
CoreData:数据托管.有四种存储方式:xml,sqlite,二进制,内存.
遵循NSCoding协议之后,进行归档即可实现复杂对象的存储.
#16.写一个标准宏MIN,这个宏输入两个参数并返回较小的一个.
#define MIN(A,B) (A)>(B)?(B):(A)
#17.iPhone OS有没有垃圾回收机制,简易阐述一下OC内存管理.
木有.引用计数,ARC和MRC,swift(自动引用计数).
#18.简述应用程序按HOME键进入后台时的生命周期,以及从后台进入前台时的生命周期.
前者:- (void)applicationWillResignActive:(UIApplication *)application
- (void)applicationDidEnterBackground:(UIApplication *)application
后者:- (void)applicationWillEnterForeground:(UIApplication *)application
- (void)applicationDidBecomeActive:(UIApplication *)application
另:
各个程序运行状态时代理的回调:
- (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
当程序从后台将要重新回到前台时候调用,这个刚好跟上面的那个方法相反。
- (void)applicationWillTerminate:(UIApplication *)application
当程序将要退出是被调用,通常是用来保存数据和一些退出前的清理工作。这个需要要设置UIApplicationExitsOnSuspend的键值。
- (void)applicationDidFinishLaunching:(UIApplication*)application
当程序载入后执行
在上面8个方法对应的方法中键入NSLog打印。
现在启动程序看看执行的顺序:
启动程序
lifeCycle[40428:11303] willFinishLaunchingWithOptions
lifeCycle[40428:11303] didFinishLaunchingWithOptions
lifeCycle[40428:11303] applicationDidBecomeActive
按下home键
lifeCycle[40428:11303] applicationWillResignActive
lifeCycle[40428:11303] applicationDidEnterBackground
双击home键,再打开程序
lifeCycle[40428:11303] applicationWillEnterForeground
lifeCycle[40428:11303] applicationDidBecomeActive
#19.ViewController的alloc,loadView,viewDidLoad,viewWillAppear,viewDidUnload,dealloc,init分别是在什么时候调用?在自定义ViewController的时候这几个函数里面应该做什么工作?
alloc:申请内存时调用.
loadView:加载视图时调用.
viewDidLoad;视图已经加载后调用.
viewWillAppear:视图将要出现时调用.
viewDidUnload:视图已经加载但是没有加载出来时调用.
dealloc:销毁该视图时调用.
init;初始化该视图时调用.
#20.描述应用程序的启动顺序.
a.程序入口main函数创建UIApplication实例和UIApplication代理实例.
b.在UIApplication代理实例中重写启动方法,设置根ViewController
c.在第一ViewController中添加控件,实现应用程序界面.
#21.为什么很多内置类如UITableViewControl的delegate属性都是assign而不是retain?
防止循环引用.
如:对象A引用了对象B,对象B引用了对象C,对象C引用了对象B,这个时候B的引用计数是2,而C的引用计数是1,当A不再使用B的时候,就释放了B的所有权,这个时候C还引用对象B,所以B不会释放,引用计数为1,因为B也引用着对象C,B不释放,那么C也就不会被释放,所以他们的引用计数都为1,并且永远不会被释放,形成了循环引用.
#22.使用UITableView的时候必须要实现的几种方法?
2个数据源方法.分别是:
-
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
-
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
#23.写一个遍历构造器.
+(id)leftModelWith{
leftModel * model = [ self alloc]init];
return model;
}
#24.UIImage初始化一张图片有几种方法?简述其特点?
3种,
imageNamed:系统会先检查系统缓存中是否有该名字的image,如果有的话,则直接返回,如果没有,则先加载图像到缓存,然后再返回.
initWithContentsOfFile:系统不会检查缓存,而直接从文件系统中记载并返回.
imageWithCGImage:scale:orientation当scale= 1的时候图像为原始大小,orientation指定绘制图像的方向.
#25.person的retainCount值,并解释为什么?
Person * per = [Person alloc]init];
self.person = per;
1或者2.看person是什么类型修饰的.
alloc+1,assign+0,retain+1.
26.下面这段代码有何问题?
@implementationPerson
- (void)setAge:(int)newAge {
self.age = newAge;
}
@end
死循环
#27. 这段代码有什么问题,如何修改
for (int i = 0; i < someLargeNumber; i++) {
NSString *string = @”Abc”;
string = [string lowercaseString];
string = [string stringByAppendingString: @"xyz"];
NSLog(@“%@”, string);
}
加入自动释放池@autoreleasepool{};
for (int i = 0; i < someLargeNumber; i++) {
@antoreleasepool {
NSString *string = @”Abc”;
string = [string lowercaseString];
string = [string stringByAppendingString: @"xyz"];
NSLog(@“%@”, string);
}
}
#28.截取字符串"20 |http://www.baidu.com"中,"|"字符前面和后面的数据,分别输出它们。
["20 |http://www.baidu.com" componentSeparatedByString:@"|"];
#29.用obj-c写一个冒泡排序.
NSMutableArray *ary = [@[@"1", @"2", @"3", @"4", @"6", @"5"] mutableCopy];
for (int i = 0; i < ary.count - 1; i++) {
for (int j = 0; j < ary.count - i - 1; j++) {
if ([ary[j] integerValue] < [ary[j + 1] integerValue]) {
[ary exchangeObjectAtIndex:j withObjectAtIndex:j + 1];
}
}
}
NSLog(@"%@", ary);
#30.简述对UIView.UIWindow和CALayer的理解.
UIWindow是应用的窗口,继承于UIResponder.
UIView继承于UIView,是创建窗口中的一个视图,可以响应交互事件.一个程序只有一个主window,可以有多个window.
CALayer图层,一个view可有多个图层,不可以响应事件.
#31.写一个完整的代理,包括声明,实现.
代理:遵守协议的对象.
@class MyView;
第一步:指定协议:(协议名:类名+Delegate)
@protocol MyViewDelegate
@required
-(void)changeViewBackgroudColor:(MyView *)view;
@optional
-(void)test;
@end
@interface MyView : UIView
第二步:指定代理
@property(nonatomic,assign)id
@end
第三步:代理遵循协议.
第四步:代理实现协议里面的必须实现的方法和其他可选方法.
第五步:委托方通知代理开始执行方法.
#32.分析json.xml的区别,底层如何实现?
Json:键值对.数据小,不复杂.便于解析,有框架支持,适合轻量级传输.作为数据包个数传输的时候效率更高.
xml:标签套内容.xml数据两较大,比较复杂.适合大数据量的传输.xml有丰富的编码工具,比如:Dom4j,JDom.解析方式有两种,一是通过文芳模型解析,另外一种遍历节点.
#33.ViewController的didReceiveMemoryWarning是在什么时候被调用的?
1.当应用程序的内存使用接近系统的最大内存使用时,应用会向系统发送内存警告,这时候系统会调用方法向所有ViewController发送内存警告.
2.打开系统相机.
3.加载高清图片.
默认操作:把里面没有用的对象进行释放.
#34.面向对象的三大特征,简单介绍.
封装:代码模块化,方便以后调用.
继承:子类继承父类的所有方法和属性.
多态:父类指针指向子类对象.
#35.重写一个NSString类型的,retain方式声明name属性的setter和getter方法.
属性的三大特性:语义特性,原子特性,读写特性.
同时重写setter和getter方法,@synchronizedname = _name,关联属性和实例变量.
- (void)setName:(NSString *)name{
if(_name != name){
[_name retain];
[_name release];
_name = name;
}
}
- (NSString *)name{
return [[_name retain]autorelease];
}
#36.简述NotificationCenter.KVC,KVO,Delegate?并说明它们之间的区别?
NotificationCenter:消息中心.消息通知.
KVC:利用键-值间接访问类中的某个属性.
[self setValue:@"123" forKeyPath:@"name"];
NSLog(@"%@",[self valueForKeyPath:@"name"]);
KVO:利用键-路径间接访问类中的某个属性,也就是观察者模式(KVO+通知中心).基于KVC和通知中心,观察的是实例变量.
Delegate:用于多个类之间的传值.
37.What is lazy loading?
懒加载
#38.对MVC的理解,好处?
MVC:是一种架构.model:数据处理,view:视图显示,controller:逻辑控制,负责视图和模型之间的通信.
高类聚,低耦合,提高代码的复用性.
#39.监测键盘的弹出.
通知.
[[NSNotificationCenter defaultCenter]addObserver:self selector: @selector() name:UIKeyboardWillShowNotification object:nil];
#40. 5个ios,sdk库和第三方库.
系统库:UIKit框架:负责应用程序的图形及事件驱动的关键基础,如:用户界面管理,图形和窗口支持.
Mapkit框架:地图.
Message UI框架:电子邮件
AV Foundation框架:可用于音频播放.
OpenAL框架:用于播放,可播放高质,高性能的网络音频
Core Data框架:将数据存储在SQLite数据库.
Core Media框架:播放视频.
第三方:SDWebImage :简化图片处理
ShareSDK 分享
SVProgressHUD 轻量级菊花
AFNetworkin 方便网络开发
FreeStreamer 播放音频
#41.介绍响应者链.
当用户点击屏幕,能够产生响应的对象组成的链.
继承自NSResponder,响应者链能够中断.
#42.传值方式:
通知,单例,代理,属性,block.
#43.NSString * test = [[NSData alloc] init],test在编译时和运行时分别是什么类型的对象?
编译时是NSString,运行时是NSData.NSData
#44.OC中对象的交互是如何实现的?
消息机制.
#45.给定一个字符串,判断字符串中是否还有png,有就删除.
stringContains
使用@""直接替换实现删除
#46.目标-动作机制.
Target - action
#47.什么是沙盒?沙盒里包含哪些文件,如何获取文件路径.
沙盒:程序可操作的磁盘空间,系统为之开辟.
包含了3个文件夹.
1.Documents:存放一些比较重要的文件,但是放入Documents中的文件不能过大.
2.Library :是一个资源库,存储一些不太重要的数据.里面包含了两个子文件夹,Caches文件夹,用于缓存,
Preferences文件夹,系统偏好设置,用户对应用程序的设置,如密码.perferences路径无法找到,只能通过NSUserDefaults.
如:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES) firstObject];
#48.介绍一下XMPP?
基于XML的点对点通讯协议,实现通讯功能.
优点:可以跨平台开发.
缺点:丢包,只能发文字(图片发送发的是链接).
#49.应用程序如何省电?
获取请求不能过频.优化算法.
#50.写一个递归方法,计算n的阶乘.
-(NSInteger)digui:(NSInteger)i{
if (i>0) {
return i*[self digui:(i-1)];
} else{
return 1;
}
}
[[NSUserDefaults standardUserDefaults]setObject:@([self digui:3]) forKey:@"value"];
#51.NSArray和NSMutableArray的区别?多线程下那个更安全.
NSArray:不可变数组.
NSMutableArray:可变数组.
多线程下NSArray更安全.
#52.取出一个数组中的重复元素.
1.放进集
2.遍历删除
3.放进字典作为key,再取出key
#54.isKindOfClass,isMemberOfClass作用分别是什么?
isKindOfClass是某个类的实例或者子类的实例.
isMemberOfClass是某个类的实例
#55.请分别写出SEL,id的意思?
SEL:选择器.
id:范类型
OC中的对象就是C语言的指针.
#56.iPhone上,能被应用程序直接调用的系统程序是什么?
能:相册,相机,通讯录,音乐.
不能:计算器,天气,日历,指南针.
#57.以.mm为扩展名的文件里,可以包含哪些代码?
C++,C,OC
#58.说说后台如何运行程序.
在plist配置Application doesnotruninbackground设置NO(默认就是NO)的前提下.
添加required background modes,值是App registersforlocation updates和App playsauto orstreams audio/videousingAirPlay
#59.sizeof和strlen的区别和联系?
sizeof:占用空间大小.
strlen:字符串大小.
#60.sprintf,strcpy,memcpy的功能?使用上要注意哪些地方?
sprintf:将某些类型转换成字符串类型
strcpy:拷贝字符串,会越界,'/0'
memcpy:拷贝内存
#61.写一个函数实现strlen的功能?
intsl(const char*s)
{
int length = 0;
while (*s!='') {
s++;
length++;
}
return length;
}
#62.写一个代码片实现输入一个字符串"20130322152830",输出一个NSDate类型的对象,打印该对象输出2013-03-11 15:28:32
NSString * str = @"20130322152832";
NSDateFormatter * format = [[NSDateFormatter alloc]init];
format.dateFormat =@"yyyyMMddHHmmss";//设置格式
NSLog(@"%@",[[format dateFromString:str] dateByAddingTimeInterval:86060]);
#63.用变量a写出以下定义
a、一个整型数inta = 10
b、一个指向整型数的指针int*p = 10
c、一个指向指针的指针,它指向的指针是指向一个整型数int**p =10
d、一个有10个整型数的数组inta[10]
e、一个有10个指针的数组,该指针是指向一个整型数的int*a[10]
f、一个指向有10个整型数数组的指针int*a = {1,2,3,4,5,6,7,8,9,10};
g、一个指向函数的指针,该函数有一个整型参数,并返回一个整型数
int *a(int b){
return b;
}
#64.cocoa和cocoa touch?
cocoa包含Foundation和AppKit框架,可用于开发Mac OS X系统的应用程序
cocoa touch包含Foundation和UIKit框架,可用于开发iPhone OS系统的应用程序
Cocoa时Mac OS X的开发环境,cocoa Touch是Iphone OS的开发环境
#65.网络从下往上分为几层?
从下往上:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
IP协议对应网络层,TCP协议对应传输层,HTTP协议对应于应用层。
socket则是对TCP/IP协议的封装和应用。也可以说,TCP/IP协议是传输层协议,主要解决数据如何在网络中传输,而HTTTP是应用层协议,主要解决
如何包装数据。
#67.多线程的底层实现?
线程:进程中一个特立独行的控制单元(路径)。多线程:一个进程至少有一个线程,即主线程。
①、Mach是第一个以多线程方式处理任务的系统,因此多线程的底层实现机制就是基于Mach的线程。
②、开发中很少用到Mach级的线程,因为Mach级的线程没有提供多线程的基本特征,线程之间是独立的。
④、开发中实现多线程的方案:
NSThread、GCD、NSOperationQueue.NSOperation
#68.线程之间怎么通信?
①.performSelect:onThread:withObject:waitUntilDone:
②.NSMachPort
#69.网络图片问题中怎么解决一个相同的网络地址重复请求的问题.
利用字典:图片地址为key,下载操作为value.value
#70.用NSOperation和NSOperationQueue处理A.B.C三个线程,要求执行完A.B后才能执行?
//创建队列
NSOperationQueue * queue = [[NSOperationQueue alloc]init];
//创建三个操作
NSOperation * A = [NSBlockOperation blockOperationWithBlock:^{
NSLog{ @"A"};
}];
NSOperation * B = [NSBlockOperation blockOperationWithBlock:^{
NSLog{ @"B"};
}];
NSOperation * C = [NSBlockOperation blockOperationWithBlock:^{
NSLog{ @"C"};
}];
//添加依赖
[C addDependency:a];
[C addDependency:b];
//执行操作
[queue addOperation:a];
[queue addOperation:b];
[queue addOperation:c];
#71.GCD内部怎么实现的?
①.iOS和OSX的核心是XNU内核, GCD是基于XNU内核实现的(是由苹果电脑发展起来的操作系统内核).
②.GCD的API全部在libdispatch库中.
③.GCD底层实现主要有Dispatch Queue(管理block)和Dispatch Source(处理事件).
#72.怎么保证多人开发进行内存泄露检查。
使用Analuze进行代码的静态分析,为避免麻烦,多人开发尽量使用ARC.
#73、非自动内存管理情况下怎么做单例模式。
创建一个单例对象的静态实例,并初始化为nil。
创建一个类的类工厂方法,当且仅当这个类的实例为nil时生成一个类的实例。
实现NScopying协议,覆盖allocWithZone:方法,确保用户在直接分配对象时,不会产生另一个对象。
覆盖release、autorelease、retain、retainCount方法,确保单例的状态。
#74、对于类方法(静态方法)默认是autorelease的,所有类方法都会这样吗?
①、系统自带的绝大数类方法返回的对象,都是经过autorelease.
#75、block在ARC中和MRC中的方法有何区别?需要注意什么?
①.对于没有引用外部变量的Block,无论在ARC还是MRC下,类型都是_NSGlobalBlock_,这种类型的block可以理解为一种全局的block,不需要考虑作用域的问题。同时,对它进行Copy和Retain操作也是无效的。
②.避免循环引用。
根据isa指针,block一共有3种类型的block
_NSConcreteGlobalBlock全局静态
_NSConcreteStackBlock保存在栈中,出函数作用域就销毁
_NSConcreteMallocBlock保存在堆中,retainCount == 0销毁
#76.什么情况下会发生内存泄露和内存溢出?
当程序在申请内存后,无法释放已经申请的内存空间(例如一个对象或者变量在用完后没有释放,这个对象就一直占用着内存),一次内存泄露可以忽略,但如果泄露过多的话,就会造成内存溢出。
当程序在申请内存时,但存入了更大的数据,出现内存溢出。
#77.[NSArray arrayWithobject
不需要,这个对象会被放到自动释放池中。
#78.自动释放池如何实现?
自动释放池以栈的形式实现,当你创建一个新的自动释放池时,它将被添加到栈顶,当一个对象收到发送autorelease消息时,它将添加到当前线程的处于栈顶的自动释放池中,当自动释放池被回收时,它们从栈中被删除并且会给池子里所有对象都做一次release操作。
#79.KVO内部实现原理?
①.KVO是基于runtime机制实现的。
②.当某个类的对象第一次被观察时,系统就会在运行期动态的创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter方法。
派生类在被重写setter方法中实现了真正的通知机制。(Person->NSKVONotification Person)
#80.能否把比较耗时的操作放在NSNotificationCenter中。
如果在异步线程发出的通知,那么就可以把耗时操作放到NSNotificationCenter中
如果在主线程发的通知,那么就不可以把耗时操作放到NSNotificationCenter中。
#81.Foundation对象与Core Foundation对象有何区别?
Foundation对象是OC的,Core Foundation对象是C对象。
数据类型之间的转换:
ARC:_bridge_retained、_bridge_transfer
非ARC:_bridge
#82、不用第三变量,交换AB的值。
A=A+B
B=A-B
A=A-B
或者
A=A^B
B=A^B
A=A^B
#83.简单描述下对单例模式设计的理解?
节省内存资源,一个应用就一个对象。
#84.runtime实现的机制是什么?怎么用,一般用于干嘛。
运行时机制,runtime库里面包含了跟类、成员变量、方法相关的API,比如获取类里面的所有成员变量,为类动态添加成员变量、动态改变类的方法实现,为类动态添加新的方法等,需要导入<objc/message.h><objc/message.h>
①.runtime,运行时机制,它是一套C语言库。
②.实际上我们编写的所有OC代码,最终都是转换成为了runtime库的东西,比如类转换成了runtime库里面的结构体等数据类型,方法转换成了runtime库里面的C语言函数,平时调方法都是转成了objc_msgSend函数(所以说OC有个消息发送机制)
③、因此,可以说runtime是OC的底层实现,是OC的幕后执行者。
④、有了runtime库,能做什么呢?可以获取类里面的所有成员变量、为类动态的添加成员变量、动态的改变类的方法实现、为类动态添加新的方法等等。
#85.是否使用Core Text或者Core Image?
Core Text
随意修改文本的样式
图文混排(纯C语言)
Core Image(滤镜处理)
能够调节图片的各种属性(对比度、色温、色差等)
#86、NSNotification和KVO的区别和用法是什么?什么时候应该使用通知,什么时候应该使用KVO,他们的实现有何区别?如果用protocol和delegate来实现类似的功能可能吗?可能的话有何问题?不可能的话why?
通知比较灵活,一个通知能被多个对象接受,一个对象可以接受多个通知。
代理不交规范,但是代码较多(默认是一对一)
KVO性能不好(底层会产生新的类),只能监听某个对象属性的变化,不推荐使用。
#87、block内部的实现原理。
Objective-C是对C语言的扩展,block的实现是基于指针和函数指针。
#88、怎么解决缓存池满的问题?
iOS中不存在缓存池满的情况,通常在对象需要创建时才创建,比如UITableView中一般只会创建刚开始在屏幕中的cell,之后都是从缓存池里取,不会再创建新对象。
89、控制器View的生命周期及相关函数是什么?你在开发中是如何使用的?
1、首先判断控制器是否有视图,如果没有就调用loadView方法创建:通过storyBoard或者代码。
2、随后调用viewDidLoad,可以进行下一步的初始化操作,只会被调用一次。
3、在视图显示之前调用viewWillAppear,该函数可以多次调用。
4、视图viewDidAppear
5、在布局变化前后,调用viewWill/DidLayoutSubViews处理相关信息。
#90、有些图片加载比较慢怎么处理?你是怎么优化程序的性能的?
①、图片下载放在异步线程。
②、图片下载过程使用占位图片。
③、如果图片比较大,可以使用多线程断点下载。
#91.App需要加载大量数据,给服务器发送请求,但是服务器卡住了怎么办?
设置请求超时,给用户提示请求超时,根据用户操作再次请求。
#92、SDWebImage具体如何实现?
其实就是沙盒缓存机制,主要由三块组成:内存图片缓存,内存操作缓存,磁盘沙盒缓存。
①、利用NSOperationQueue和NSOperation下载图片,还使用了GCD(解析GIF图片)。
②、利用URL作为key,NSOperation作为value.
③、利用URL作为key,UIImage作为value
#93、AFNetWorking实现原理。
基于NSURL.采用block的方法处理请求,直接返回的是json、XML数据。AFN直接操作对象是AFHTTPClient,是一个实现了NSCoding和NSCopying协议的NSObject子类。AFGTTPClient是一个封装了一系列操作方法的工具类。AFN默认没有封装同步请求,如果开发者需要使用同步请求,需要重写相关的方法(getPath:parameters:failure),对AFHTTPRequestOperation进行同步处理。
#****************************************************************************
#什么是响应链,它是怎么工作的?
http://www.jianshu.com/p/9179e5d780c8
#有两种方法可以访问私有属性,一种是通过KVC获取,一种是通过runtime访问并修改私有属性
#创建一个Father类,声明一个私有属性name,并重写description打印name的值,在另外一个类中通过runtime来获取并修改Father中的属性
@interface Father ()
@property(nonatomic,copy) NSString *name;
@end
@implementationFather
- (NSString *)description
{
return [NSString stringWithFormat:@"name:%@",_name];
}
@implementation ViewController
- (void)viewDidLoad {
[ super viewDidLoad];
Father *father = [Father new];
// count记录变量的数量IVar是runtime声明的一个宏
unsigned int count = 0;
//获取类的所有属性变量
Ivar *menbers = class_copyIvarList([Father class], &count);
for (int i = 0; i < count; i++) {
Ivar ivar = menbers[i];
//将IVar变量转化为字符串,这里获得了属性名
const char *memberName = ivar_getName(ivar);
NSLog( @"%s",memberName);
Ivar m_name = menbers[0];
//修改属性值
object_setIvar(father, m_name, @"zhangsan");
//打印后发现Father中name的值变为zhangsan
NSLog( @"%@",[father description]);
}
}
#iOS Extension是什么?能列举几个常用的Extension么?
Extension是扩展,没有分类名字,是一种特殊的分类,类扩展可以扩展属性,成员变量和方法
常用的扩展是在.m文件中声明私有属性和方法,这里不知道还哪些,请大家补充
如何把一个包含自定义对象的数组序列化到磁盘?
自定义对象只需要实现NSCoding协议即可
- (void)viewDidLoad
{
[ super viewDidLoad];
User *user = [User new];
Account *account = [Account new];
NSArray *userArray = @[user, account];
//存到磁盘
NSData * tempArchive = [NSKeyedArchiver archivedDataWithRootObject: userArray];
}
//代理方法
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
self.user = [aDecoder decodeObjectForKey:@"user"];
self.account = [aDecoder decodeObjectForKey:@"account"];
}
return self;
}
//代理方法
-(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject: self.user forKey:@"user"];
[aCoder encodeObject: self.account forKey:@"account"];
}
#Apple Pay是什么?它的大概工作流程是怎样的?
这个笔者也没有详细了解过,大家可以百度谷歌一下具体的
#iOS的沙盒目录结构是怎样的?App Bundle里面都有什么?
1.沙盒结构
Application:存放程序源文件,上架前经过数字签名,上架后不可修改
Documents:常用目录,iCloud备份目录,存放数据,这里不能存缓存文件,否则上架不被通过
Library
Caches:存放体积大又不需要备份的数据,SDWebImage缓存路径就是这个
Preference:设置目录,iCloud会备份设置信息
tmp:存放临时文件,不会被备份,而且这个文件下的数据有可能随时被清除的可能
2.App Bundle里面有什么
Info.plist:此文件包含了应用程序的配置信息.系统依赖此文件以获取应用程序的相关信息
可执行文件:此文件包含应用程序的入口和通过静态连接到应用程序target的代码
资源文件:图片,声音文件一类的
其他:可以嵌入定制的数据资源
iOS的签名机制大概是怎样的?
假设,我们有一个APP需要发布,为了防止中途篡改APP内容,保证APP的完整性,以及APP是由指定的私钥发的。首先,先将APP内容通过摘要算法,得到摘要,再用私钥对摘要进行加密得到密文,将源文本、密文、和私钥对应的公钥一并发布即可。那么如何验证呢?
验证方首先查看公钥是否是私钥方的,然后用公钥对密文进行解密得到摘要,将APP用同样的摘要算法得到摘要,两个摘要进行比对,如果相等那么一切正常。这个过程只要有一步出问题就视为无效。
iOS 7的多任务添加了哪两个新的API?各自的使用场景是什么?
后台获取(Background Fetch):后台获取使用场景是用户打开应用之前就使app有机会执行代码来获取数据,刷新UI。这样在用户打开应用的时候,最新的内容将已然呈现在用户眼前,而省去了所有的加载过程。
推送唤醒(Remote Notifications):使用场景是使设备在接收到远端推送后让系统唤醒设备和我们的后台应用,并先执行一段代码来准备数据和UI,然后再提示用户有推送。这时用户如果解锁设备进入应用后将不会再有任何加载过程,新的内容将直接得到呈现。
#UIScrollView大概是如何实现的,它是如何捕捉、响应手势的?
我对UIScrollView的理解是frame就是他的contentSize,bounds就是他的可视范围,通过改变bounds从而达到让用户误以为在滚动,以下是一个简单的UIScrollView实现
在头文件定义一个contentSize属性
@interface MyScrollView : UIView
@property (nonatomic) CGSize contentSize;
@end
@implementationMyScrollView
-
(instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self == nil) {
return nil;
}
//添加一个滑动手势
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget: self action:@selector(panGesture:)];
[ self addGestureRecognizer:pan];
return self;
} -
(void)panGesture:(UIPanGestureRecognizer *)gestureRecognizer{
//改变bounds
CGPoint translation = [gestureRecognizer translationInView: self];
CGRect bounds = self.bounds;
CGFloat newBoundsOriginX = bounds.origin.x - translation.x;
CGFloat minBoundsOriginX = 0.0;
CGFloat maxBoundsOriginX = self.contentSize.width - bounds.size.width;
bounds.origin.x = fmax(minBoundsOriginX, fmin(newBoundsOriginX, maxBoundsOriginX));
CGFloat newBoundsOriginY = bounds.origin.y - translation.y;
CGFloat minBoundsOriginY = 0.0;
CGFloat maxBoundsOriginY = self.contentSize.height - bounds.size.height;
bounds.origin.y = fmax(minBoundsOriginY, fmin(newBoundsOriginY, maxBoundsOriginY));
self.bounds = bounds;
[gestureRecognizer setTranslation:CGPointZero inView: self];
}
#第二个问题个人理解是解决手势冲突,对自己添加的手势进行捕获和响应
//让UIScrollView遵守UIGestureRecognizerDelegate协议,实现这个方法,在这里方法里对添加的手势进行处理就可以解决冲突
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
#Objective-C如何对已有的方法,添加自己的功能代码以实现类似记录日志这样的功能?
这题目主要考察的是runtime如何交换方法
先在分类中添加一个方法,注意不能重写系统方法,会覆盖
- (NSString *)myLog
{
//这里写打印行号,什么方法,哪个类调用等等
}
然后交换方法
//加载分类到内存的时候调用
- (void)load
{
//获取imageWithName方法地址
Method description = class_getClassMethod( self, @selector(description));
//获取imageWithName方法地址
Method myLog = class_getClassMethod( self, @selector(myLog));
//交换方法地址,相当于交换实现方式
method_exchangeImplementations(description, myLog);
}
#+load和+initialize的区别是什么?
+(void)load;
当类对象被引入项目时, runtime会向每一个类对象发送load消息
load方法会在每一个类甚至分类被引入时仅调用一次,调用的顺序:父类优先于子类,子类优先于分类
load方法不会被类自动继承
+(void)initialize;
也是在第一次使用这个类的时候会调用这个方法
#如何让Category支持属性?
使用runtime可以实现
头文件
@interface NSObject (test)
@property (nonatomic, copy) NSString *name;
@end
.m文件
@implementation NSObject (test)
//定义关联的key
static const char*key ="name";
- (NSString *)name
{
//根据关联的key,获取关联的值。
return objc_getAssociatedObject(self, key);
} - (void)setName:(NSString *)name
{
//第一个参数:给哪个对象添加关联
//第二个参数:关联的key,通过这个key获取
//第三个参数:关联的value
//第四个参数:关联的策略
objc_setAssociatedObject( self, key, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
#NSOperation相比于GCD有哪些优势?
提供了在GCD中不那么容易复制的有用特性。
可以很方便的取消一个NSOperation的执行
可以更容易的添加任务的依赖关系
提供了任务的状态:isExecuteing, isFinished.
#strong / weak / unsafe_unretained的区别?
weak只能修饰OC对象,使用weak不会使计数器加1,对象销毁时修饰的对象会指向nil
strong等价与retain,能使计数器加1,且不能用来修饰数据类型
unsafe_unretained等价与assign,可以用来修饰数据类型和OC对象,但是不会使计数器加1,且对象销毁时也不会将对象指向nil,容易造成野指针错误
如何为Class定义一个对外只读对内可读写的属性?
在头文件中将属性定义为readonly,在.m文件中将属性重新定义为readwrite
Objective-C中,meta-class指的是什么?
meta-class是Class对象的类,为这个Class类存储类方法,当一个类发送消息时,就去那个类对应的meta-class中查找那个消息,每个Class都有不同的meta-class,所有的meta-class都使用基类的meta-class(假如类继承NSObject,那么他所对应的meta-class也是NSObject)作为他们的类
UIView和CALayer之间的关系?
UIView显示在屏幕上归功于CALayer,通过调用drawRect方法来渲染自身的内容,调节CALayer属性可以调整UIView的外观,UIView继承自UIResponder,CALayer不可以响应用户事件
UIView是iOS系统中界面元素的基础,所有的界面元素都继承自它。它内部是由Core Animation来实现的,它真正的绘图部分,是由一个叫CALayer(Core Animation Layer)的类来管理。UIView本身,更像是一个CALayer的管理器,访问它的根绘图和坐标有关的属性,如frame,bounds等,实际上内部都是访问它所在CALayer的相关属性
UIView有个layer属性,可以返回它的主CALayer实例,UIView有一个layerClass方法,返回主layer所使用的类,UIView的子类,可以通过重载这个方法,来让UIView使用不同的CALayer来显示
#+[UIView animateWithDuration:animations:completion:]内部大概是如何实现的?
animateWithDuration:这就等于创建一个定时器
animations:这是创建定时器需要实现的SEL
completion:是定时器结束以后的一个回调block
以上只是自己的理解,不一定正确,有对这个有研究的朋友请告知下
什么时候会发生「隐式动画」?
当改变CALayer的一个可做动画的属性,它并不能立刻在屏幕上体现出来.相反,它是从先前的值平滑过渡到新的值。这一切都是默认的行为,你不需要做额外的操作,这就是隐式动画
如何处理异步的网络请求?
#如何把一张大图缩小为1/4大小的缩略图?
let data = UIImageJPEGRepresentation(image, 0.25)