IOS面试题(收集整理)

来源:互联网 发布:linux打开隐藏文件 编辑:程序博客网 时间:2024/05/16 01:04

虽然是收集整理,但是在整理过程中收获还是很多

@property中有那些属性关键字

属性关键字 作用 Strong 在赋值时调用被指向对象的retain方法,使其引用计数加1 weak weak不增加对象的引用计数,也不持有对象,对象消失后,指针自动变成nil assign 不更改索引计数,使用基础数据类型(int float double等) copy 建立一个引用计数为1的对象,通常用于NSString和block atomic 原子操作,提供线程安全,默认是atomic的,耗费系统资源 readonly 属性只读 readwrite 属性可以读写,默认属性 unsafe_unretained 和weak类似,但是引用计数为0,变量不会置为nil setter 手动设置设置实例变量的方法 getter 手动设置获取实例变量的方法 nonnull 该属性不为nil,必须有值 nullable 表示可选的,可以为nil null_resettable 表示setter是nullable,可选的,但是getter是nonnull,一定会有值返回


weak属性需要在dealloc中置nil么?

不需要。

在ARC环境无论是强指针还是弱指针都无需在 dealloc 设置为 nil , ARC 会自动帮我们处理

即便是编译器不帮我们做这些,weak也不需要在 dealloc 中置nil:


@synthesize和@dynamic分别有什么作用

@synthesize
编译器期间,让编译器自动生成getter/setter方法。
当有自定义的存或取方法时,自定义会屏蔽自动生成该方法

@dynamic
告诉编译器,不自动生成getter/setter方法,避免编译期间产生警告
然后由自己实现存取方法
或存取方法在运行时动态创建绑定:主要使用在CoreData的实现NSManagedObject子>类时使用,由Core Data框架在程序运行的时动态生成子类属性


ARC下,不显示指定任何属性关键字时,默认的关键字都有那些

@property NSArray *user;
我没写这些关键词,效果如下
@property (strong, atomic, readwrite) NSArray *user;
strong 是内存的管理方式,其他的还有weak, copy, assign(基本类型时候)。
atomic 是线程安全的关键词,还有nonatomic。
readwrite 是读写关键词,还有readonly。


用@property声明的NSString(或NSArray,NSDictionary)经常使用copy关键字,为什么?如果改用strong关键字,可能造成什么问题?

当用@property声明NSString、NSArray、NSDictionary经常使用copy关键字,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向NSMutableString、NSMutableArray或者NSMutableDictionary类的实例,是因为他们是NSString、NSArray、NSDictionary的子类,意思就是说能做增删改查的功能,此时若是不用copy修饰,那么设置完之后,NSString、NSArray、NSDictionary的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变” (immutable)的,确保NSString、NSArray、NSDictionary对象中的值不会无意间更改.使用了Strong关键字,当子类NSMutableArray赋值了NSArray时,子NSMutableArray添加了新的元素时,NSArray实例也会被添加新元素.


@synthesize合成实例变量的规则是什么?假如property名为foo,存在一个名为_foo的实例变量,那么还会自动合成新变量么

不会
@synthesize 合成实例变量的规则,有以下几点:
如果指定了成员变量的名称,会生成一个指定的名称的成员变量,
如果这个成员已经存在了就不再生成了.
如果是 @synthesize foo; 还会生成一个名称为foo的成员变量,也就是说:
如果没有指定成员变量的名称会自动生成一个属性同名的成员变量,
如果是 @synthesize foo = _foo; 就不会生成成员变量了


有了自动合成属性实例变量之后,@synthesize还有哪些使用场景?

回答这个问题前,我们要搞清楚一个问题,什么情况下不会autosynthesis(自动合成)?
1.重写了 setter 和 getter 时
2.了只读属性的 getter 时
3.了dynamic 时
4.@potocol 中定义的所有属性
5.在 category 中定义的所有属性
6.重载的属性

当你在子类中重载了父类中的属性,你必须 使用 @synthesize 来手动合成ivar。
除了后三条,对其他几个我们可以总结出一个规律:当你想手动管理 @property 的所有内容时,你就会尝试通过实现 @property 的所有“存取方法”(the accessor methods)或者使用 @dynamic 来达到这个目的,这时编译器就会认为你打算手动管理 @property,于是编译器就禁用了 autosynthesis(自动合成)。
因为有了 autosynthesis(自动合成),大部分开发者已经习惯不去手动定义ivar,而是依赖于 autosynthesis(自动合成),但是一旦你需要使用ivar,而 autosynthesis(自动合成)又失效了,如果不去手动定义ivar,那么你就得借助 @synthesize 来手动合成 ivar
其实,@synthesize 语法还有一个应用场景,但是不太建议大家使用:
可以在类的实现代码里通过 @synthesize 语法来指定实例变量的名字


objc中向一个nil对象发送消息将会发生什么?

如果一个方法返回值是一个对象,那么发送给nil的消息将返回0(nil)。例如:
Person * motherInlaw = [[aPerson spouse] mother];
如果 spouse 对象为 nil,那么发送给 nil 的消息 mother 也将返回 nil。 2. 如果方法返回值为指针类型,其指针大小为小于或者等于sizeof(void*),float,double,long double 或者 long long 的整型标量,发送给 nil 的消息将返回0。 2. 如果方法返回值为结构体,发送给 nil 的消息将返回0。结构体中各个字段的值将都是0。 2. 如果方法的返回值不是上述提到的几种情况,那么发送给 nil 的消息的返回值将是未定义的。


objc中向一个对象发送消息[obj foo]和objc_msgSend()函数之间有什么关系?

((void ()(id, SEL))(void )objc_msgSend)((id)obj, sel_registerName(“foo”));
也就是说:
[obj foo];在objc编译时,会被转意为:objc_msgSend(obj, @selector(foo));。


什么时候会报unrecognized selector的异常?

当调用该对象上某个方法,而该对象上没有实现这个方法的时候, 可以通过“消息转发”进行解决。


一个objc对象的isa的指针指向什么?有什么作用?

指向他的类对象,从而可以找到对象上的方法


runtime如何通过selector找到对应的IMP地址?(分别考虑类方法和实例方法)

每一个类对象中都一个方法列表,方法列表中记录着方法的名称,方法实现,以及参数类型,其实selector本质就是方法名称,通过这个方法名称就可以在方法列表中找到对应的方法实现.


使用runtime Associate方法关联的对象,需要在主对象dealloc的时候释放么?

ARC和MRC都不需要.被关联的对象在生命周期内要比对象本身释放的晚很多。它们会在被 NSObject -dealloc 调用的 object_dispose() 方法中释放。
1. 调用 -release :引用计数变为零
* 对象正在被销毁,生命周期即将结束.
* 不能再有新的 __weak 弱引用, 否则将指向 nil.
* 调用 [self dealloc]
2. 子类 调用 -dealloc
* 继承关系中最底层的子类 在调用 -dealloc
* 如果是 MRC 代码 则会手动释放实例变量们(iVars)
* 继承关系中每一层的父类 都在调用 -dealloc
3. NSObject 调 -dealloc
* 只做一件事:调用 Objective-C runtime 中的 object_dispose() 方法
4. 调用 object_dispose()
* 为 C++ 的实例变量们(iVars)调用 destructors
* 为 ARC 状态下的 实例变量们(iVars) 调用 -release
* 解除所有使用 runtime Associate方法关联的对象
* 解除所有 __weak 引用
* 调用 free()


objc中的类方法和实例方法有什么本质区别和联系?

类方法:
类方法是属于类对象的
类方法只能通过类对象调用
类方法中的self是类对象
类方法可以调用其他的类方法
类方法中不能访问成员变量
类方法中不能直接调用对象方法
实例方法:
实例方法是属于实例对象的
实例方法只能通过实例对象调用
实例方法中的self是实例对象
实例方法中可以访问成员变量
实例方法中直接调用实例方法
实例方法中也可以调用类方法(通过类名)

_objc_msgForward函数是做什么的,直接调用它将会发生什么?

_objc_msgForward是 IMP 类型,用于消息转发的:当向一个对象发送一条消息,但它并没有实现的时候,_objc_msgForward会尝试做消息转发。
一旦调用_objc_msgForward,将跳过查找 IMP 的过程,直接触发“消息转发”


有哪些场景需要直接调用_objc_msgForward?

最常见的场景是:你想获取某方法所对应的NSInvocation对象

runtime如何实现weak变量的自动置nil?

runtime 对注册的类, 会进行布局,对于 weak 对象会放入一个 hash 表中。 用 weak 指向的对象内存地址作为 key,当此对象的引用计数为0的时候会 dealloc,假如 weak 指向的对象内存地址是a,那么就会以a为键, 在这个 weak 表中搜索,找到所有以a为键的 weak 对象,从而设置为 nil。

objc_storeWeak(&a, b)函数:
objc_storeWeak函数把第二个参数–赋值对象(b)的内存地址作为键值key,将第一个参数–weak修饰的属性变量(a)的内存地址(&a)作为value,注册到 weak 表中。如果第二个参数(b)为0(nil),那么把变量(a)的内存地址(&a)从weak表中删除


能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么?

不能向编辑后的类中增加实例变量
可以向运行时创建的类中添加实例变量

因为编译后的类已经注册在runtime中,类结构体中objc_ivar_list实例变量的链表和instance_size实例变量内存大小已经确定了。同时rumtime会调用class_setIVarLayout或class_setWeakIvarLayout来处理strong weak引用.所以不能向存在的类中添加实例变量

运行时创建的类是可以添加实例变量,调用class_addIvar函数.但是得在调用,objc_alloccateClassPair之后,objc_registerClassPair之前.原因同上

runloop和线程有什么关系?

可以这样说run loop是为了线程而生,没有线程,它就没有存在的必要.

对其它线程来说,run loop默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动,如果线程只是去执行一个长时间的已确定的任务则不需要。

在任何一个 Cocoa 程序的线程中,都可以通过以下代码来获取到当前线程的 run loop 。NSRunLoop *runloop = [NSRunLoop currentRunLoop];


runloop的mode作用是什么?

用来控制一些特殊操作只能在指定模式下运行,一般可以通过指定操作的运行mode来控制执行时机,以提高用户体验
系统默认注册了5个mode
1. KCFRunLoopDefaultMode:App的默认Mode通常主线程是在这个Mode下运行.对应OC中的:NSDefaultRunLoopMode
2. UITrackingRunLoopMode:界面跟踪Mode,用于scrollView追踪触摸滑动,保证界面滑动时不受其他Mode影响
3. kCFRunLoopCommonModes:这是一个标记Mode,不是一种真正的Mode,事件可以在运行在所有标有common modes标记的模式中,对应OC NSRunLoopCommonModes.带有common modes标记的模式有:UITrackingRunLoopModekCFRunLoopDefultMode
4. UIInitializationRunLoopMode:在启动App时进入第一Mode启动完成后就不再使用了
5.GSEventReceiveRunloopMode:接受系统事件的内部Mode,通常用不到


以+ scheduledTimerWithTimeInterval…的方式触发的timer,在滑动页面上的列表时,timer会暂定回调,为什么?如何解决

//将timer添加到NSDefaultRunLoopMode中[NSTimer scheduledTimerWithTimeInterval:1.0     target:self     selector:@selector(timerTick:)     userInfo:nil     repeats:YES];//然后再添加到NSRunLoopCommonModes里NSTimer *timer = [NSTimer timerWithTimeInterval:1.0     target:self     selector:@selector(timerTick:)     userInfo:nil     repeats:YES];[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];


猜想runloop内部是如何实现的?

 //程序一直运行状态 while (AppIsRunning) {      //睡眠状态,等待唤醒事件      id whoWakesMe = SleepForWakingUp();      //得到唤醒事件      id event = GetEvent(whoWakesMe);      //开始处理事件      HandleEvent(event); }


objc使用什么机制管理对象内存?

通过 retainCount 的机制来决定对象是否需要释放。 每次 runloop 的时候,都会检查对象的 retainCount,如果retainCount 为 0,说明该对象没有地方需要继续使用了,可以释放掉了。


ARC通过什么方式帮助开发者管理内存?

ARC相对于MRC,不是在编译时添加retain/release/autorelease这么简单。应该是编译期和运行期两部分共同帮助开发者管理内存。
在编译期,ARC用的是更底层的C接口实现的retain/release/autorelease,这样做性能更好,也是为什么不能在ARC环境下手动retain/release/autorelease,同时对同一上下文的同一对象的成对retain/release操作进行优化(即忽略掉不必要的操作);ARC也包含运行期组件,这个地方做的优化比较复杂,但也不能被忽略


不手动指定autoreleasepool的前提下,一个autorealese对象在什么时刻释放?(比如在一个vc的viewDidLoad中创建)

如果在一个vc的viewDidLoad中创建一个 Autorelease对象,那么该对象会在 viewDidAppear 方法执行前就被销毁了。

分两种情况:手动干预释放时机、系统自动去释放。
1. 手动干预释放时机–指定autoreleasepool 就是所谓的:当前作用域大括号结束时释放。
2.系统自动去释放–不手动指定autoreleasepool
Autorelease对象出了作用域之后,会被添加到最近一次创建的自动释放池中,并会在当前的 runloop 迭代结束时释放。
下图表示

自定义的 NSOperation 和 NSThread 需要手动创建自动释放池。比如: 自定义的 NSOperation 类中的 main 方法里就必须添加自动释放池。否则出了作用域后,自动释放对象会因为没有自动释放池去处理它,而造成内存泄露。


BAD_ACCESS在什么情况下出现?

访问了僵尸对象 , 比如对一个已经释放的对象执行了release、访问已经释放对象的成员变量或者发消息

苹果是如何实现autoreleasepool的?

autoreleasepool 以一个队列数组的形式实现,主要通过下列三个函数完成.
1. objc_autoreleasepoolPush
2. objc_autoreleasepoolPop
3. objc_autorelease


使用block时什么情况会发生引用循环,如何解决

一个对象中强引用了block,在block中又强引用了该对象,就会发射循环引用。
解决方法是将该对象使用__weak或者__block修饰符修饰之后再在block中使用。
id weak weakSelf = self; 或者 weak __typeof(&*self)weakSelf = self该方法可以设置宏
id __block weakSelf = self;
或者将其中一方强制制空 xxx = nil。

在block内如何修改block外部变量?

默认情况下,在block中访问的外部变量是复制过去的,即:写操作不对原变量生效。但是你可以加上 __block 来让其写操作生效
我们都知道:Block不允许修改外部变量的值,这里所说的外部变量的值,指的是栈中指针的内存地址。__block 所起到的作用就是只要观察到该变量被 block 所持有,就将“外部变量”在栈中的内存地址放到了堆中。进而在block内部也可以修改外部变量的值。

使用系统的某些block api(如UIView的block版本写动画时),是否也考虑引用循环问题?

系统的某些block api中,UIView的block版本写动画时不需要考虑,但也有一些api 需要考虑:

但如果你使用一些参数中可能含有 ivar 的系统 api ,如 GCD 、NSNotificationCenter就要小心一点:比如GCD 内部如果引用了 self,而且 GCD 的其他参数是 ivar,则要考虑到循环引用:例如下面

 __weak __typeof__(self) weakSelf = self; _observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"testKey"                                                               object:nil                                                                queue:nil                                                           usingBlock:^(NSNotification *note) {     __typeof__(self) strongSelf = weakSelf;     [strongSelf dismissModalViewControllerAnimated:YES]; }];

检测代码中是否存在循环引用问题,可使用 Facebook 开源的一个检测工具 FBRetainCycleDetector 。


GCD的队列(dispatch_queue_t)分哪两种类型?

串行队列Serial Dispatch Queue
并行队列Concurrent Dispatch Queue


dispatch_barrier_async的作用是什么?

在并行队列中,为了保持某些任务的顺序,需要等待一些任务完成后才能继续进行,使用 barrier 来等待之前任务完成,避免数据竞争等问题。 dispatch_barrier_async 函数会等待追加到Concurrent Dispatch Queue并行队列中的操作全部执行完之后,然后再执行 dispatch_barrier_async 函数追加的处理,等 dispatch_barrier_async 追加的处理执行结束之后,Concurrent Dispatch Queue才恢复之前的动作继续执行。

打个比方:比如你们公司周末跟团旅游,高速休息站上,司机说:大家都去上厕所,速战速决,上完厕所就上高速。超大的公共厕所,大家同时去,程序猿很快就结束了,但程序媛就可能会慢一些,即使你第一个回来,司机也不会出发,司机要等待所有人都回来后,才能出发。 dispatch_barrier_async 函数追加的内容就如同 “上完厕所就上高速”这个动作。

(注意:使用 dispatch_barrier_async ,该函数只能搭配自定义并行队列 dispatch_queue_t 使用。不能使用: dispatch_get_global_queue ,否则 dis`patch_barrier_async 的作用会和 dispatch_async 的作用一模一样。 )

苹果为什么要废弃dispatch_get_current_queue?

dispatch_get_current_queue容易造成死锁

如何手动触发一个value的KVO

- (void)viewDidLoad {   [super viewDidLoad];   [self addObserver:self forKeyPath:@"now" options:NSKeyValueObservingOptionNew context:nil];   NSLog(@"1");   [self willChangeValueForKey:@"now"]; // “手动触发self.now的KVO”,必写。   NSLog(@"2");   [self didChangeValueForKey:@"now"]; // “手动触发self.now的KVO”,必写。   NSLog(@"4");}- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {   NSLog(@"3");}


__block在arc和非arc下含义一样吗?

在非arc中,block修饰的变量的引用计算是不变的。
在arc中,会引用到,并且计算+1;
非arc下可使用(arc直接使用__weak即可)


使用atomic一定是线程安全的吗?

不是

但是如果有个C也在写,D在读取,D会读到一些随机的值(ABC修改的值),这就不是线程安全的了。最好的方法是使用lock。Thread A:[p lock]; // << wait for it… … … …// Thread B now cannot access pp.firstName = @"Rob";NSString fullName = p.fullName;[p unlock];// Thread B can now access plabel.string = fullName;Thread B:[p lock]; // << wait for it… … … …// Thread A now cannot access p…[p unlock];


+(void)load; +(void)initialize;有什么用处

两个方法都可以进行一些类的初始化操作。其中有些小区别。
+(void)load 方法只要加入了工程中,进行了编译,且.m中实现了这个方法,都会调用一次,值得注意的时没实现的子类是不会调用的,就算父类实现了也不行。
+(void)initialize 在发送第一条消息给类的时候进行调用,跟load方法的不同之处在于,比较迟,可实现懒加载,且父类.m实现了该方法,子类不实现也会调用父类,跟正常的方法一样


使用drawRect有什么影响?

用来画图,这个方法会在intiWithRect时候调用。
这个方法的影响在于有touch event的时候之后,会重新绘制,很多这样的按钮的话就会比较影响效率。以下都会被调用
1、如果在UIView初始化时没有设置rect大小,将直接导致drawRect不被自动调用。drawRect 掉用是在Controller->loadView, Controller->viewDidLoad 两方法之后掉用的.所以不用担心在 控制器中,这些View的drawRect就开始画了.这样可以在控制器中设置一些值给View(如果这些View draw的时候需要用到某些变量 值).
2、该方法在调用sizeToFit后被调用,所以可以先调用sizeToFit计算出size。然后系统自动调用drawRect:方法。
3、通过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。
4、直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0。


ASIHttpRequest或者SDWebImage里面给UIImageView加载图片的逻辑是什么样的?

1、设置一个展位图(可选择);
2、根据URL去内存中找,找到返回图片
3、内存找不到,硬盘找,找到返回图片,内存做备份
4、硬盘还找不到,去下载,返回图片,并进行存储(硬盘,内存)。


麻烦你设计个简单的图片内存缓存器(移除策略是一定要说的)

写一个FIFO的存储机制,设置一定量的内存大小。每次添加新的图片后检查是否超出容量,如果超出则释放队列最前面的图片。


讲讲你用Instrument优化动画性能的经历吧

Core Graphics 可以查看帧数… 像collectionview,tableview,mapview这样高速拖动的时候帧数50~60多是不错的…40多就略卡需要优化了…
优化的话,基础的的,reuse大家都知道,然后把opaque都设置为yes(有个选项可以显示那些为false的UIView),然后把cornerRadius和shadow(主要是shadow)优化,不要用代码写。然后不要在delegate方法里使用类似 tableview.cellForIndexpath 还是 indexpathForCell 类似的方法 。
要求高一点,就尽可能缓存和预加载。而且不在delegate里减少需要计算的东西,和占内存的东西。VVebo有一个极致优化tableView的例子,是在后台进程先把layer的image绘制好,然后缓存起来要显示的时候再加载。


loadView是干嘛用的?

当你访问一个ViewController的view属性时,如果此时view的值是nil,那么,ViewController就会自动调用loadView这个方法。这个方法就会加载或者创建一个view对象,赋值给view属性。

loadView默认做的事情是:如果此ViewController存在一个对应的nib文件,那么就加载这个nib。否则,就创建一个UIView对象。

如果你用Interface Builder来创建界面,那么不应该重载这个方法。

如果你想自己创建view对象,那么可以重载这个方法。此时你需要自己给view属性赋值。你自定义的方法不应该调用super。如果你需要对view做一些其他的定制操作,在viewDidLoad里面去做。


GCD里面有哪几种Queue?你自己建立过串行queue吗?背后的线程模型是什么样的?

两种 并发和串行

ads

用过coredata或者sqlite吗?读写是分线程的吗?遇到过死锁没?咋解决的?

如果不是要求特别高,推荐在同一线程内读写,这样你会省很多事(最好的办法并不一定是速度最快
当然如果你必须要coredata多线程。注意
1、只用一个NSPersistentStoreCoordinator
2、每个线程创建一个NSManagedObjectContext
3、不要传递NSManagedObject,传objectID,通过fetch获得。
4、先存后取,利用NSManagedObjectContext
-mergeChangesFromContextDidSaveNotification:
5、保护思路清晰。
关于sqlite,这个其实要简单的多,它的存储都是优化的,你自己建一个串行的线程,用来存储就好了,FMDB可以看看。


我知道你大学毕业过后就没接触过算法数据结构了,但是请你一定告诉我什么是Binary search tree? search的时间复杂度是多少?

inary search tree:二叉搜索树。
主要由四个方法:(用C语言实现或者Python)
1.search:时间复杂度为O(h),h为树的高度
2.traversal:时间复杂度为O(n),n为树的总结点数。
3.insert:时间复杂度为O(h),h为树的高度。
4.delete:最坏情况下,时间复杂度为O(h)+指针的移动开销。


最小尺寸和最大尺寸的应用图标分别是什么样子的

asfsa


应用图标能否包含透明的部分?

不能


问题[◆◆◆]:Newsstand的图标与常规应用有何不同?

所有期刊图标的大小比例都应介于1:2和2:1之间。
所有的图标都应是扁平的,并有90°角。
不要为Newsstand图标添加透视效果


自动布局(Auto Layout)的作用是什么?请概括一下它是如何运行的。

在Xcode4中,当你在给视图添加了一个不完整的活着无效的约束条件,Interface Builder将会使用一个尽量不会产生影响的新约束条件来替换掉该约束条件。这回给开发者造成显著的问题。在Xcode5中,使用Auto Layout变得更加简单,当一个视图上的约束条件无效时,Xcode将会给你提示活着警告,而不是简单粗暴地强制改变你的约束条件。


设计软件时为什么要加上动画?

提升用户体验.

请描述一下软件设计中的交互和Feedback有什么作用。

提升用户体验。听取用户意见改善不足

设计iPhone和iPad应用时,应分别考虑哪些因素?

1设备分辨率问题,IPad运行Iphone应用导致有黑边
2.由于软件兼容性不同,可能会导致部分iPhone软件在iPad上无法运行而出现闪退或者部分功能无法正常使用。
3.由于屏幕大小不同,导致部分软件在iPad上运行时,应用程序界面模糊,视觉效果欠佳。

请描述一下原型设计对于软件开发的意义。其作用是什么?

原型设计对于软件开发非常重要,概括了软件的产品方向,最终实现的大致效果,理清业务逻辑.


应用内购买(In-App Purchases)是怎么回事?IAP能够为用户带来哪些新体验?

应用内购买可以让开发者通过苹果的Store Kit框架在应用中内嵌一个商店。
带来哪些新的体验:首先,苹果提供了安全的交易平台。其次,让更多的付费应用转变为免费+应用内购买的模式,用户可以提前体验应用的功能,对增值的服务和内容采取应用内购买的模式,让用户和开发者达到双赢的目的。


你是否在App Store上发布过应用?能否概括一下过程?

  1. 注册App ID,在Xcode中指定Bundle Identifier
  2. 创建发布证书(Distribution Certificate)
  3. 创建Distribution Provisioning Profile
  4. 用Distribution Profile为应用签名
  5. 打包App
  6. 在iTunes Connect上传App


CoreData 多线程处理大量数据同步时的操作 .

.每一个线程使用私有的manager context,共享一个 persistent store coordin


什么时候处理多线程,有多少种方式 什么优缺点

处理需要耗时的方法,比如请求数据,图片等
C语言的POSIX接口 pthread
OC的NSThread、NSOperation、NSOperationQueue、
C语言的GCD

NSThread     优点:NSThread比其他两个轻量级,使用简单     缺点:需要管理线程的生命周期、线程同步、加锁、睡眠、以及唤醒NSOperation     优点:不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上. 可以监听线程的状态。operation的优先级      缺点:性能没有GCD好.默认情况下 单独使用NSOperation在同步操作,并没有开辟新线程的能力.只有配合NSOperationQueue才能实现异步执行。

代理, 通知,KVO的优缺点

代理   优点:     1.所有将听到的事件必须是在delegate协议中有清晰的定义。     2.如果delegate中的一个方法没有实现那么就会出现编译警告/错误     3.必须在@protocol @end 定义方法和属性     4.在一个控制器中可以定义定义多个不同的协议,每个协议有不同的delegates     5.没有第三方对象监听通信过程     6.能够接受协议的返回值   缺点:     1.在释放代理对象时,需要小心的将delegate改为nil。     2.在一个controller中有多个delegate对象,并且delegate是遵守同一个协议,但还是很难告诉多个                  对象同一个事件,不过有可能。通知    优点:      1.不需要编写多少代码,实现比较简单;      2..对于一个发出的通知,多个对象能够做出反应,即1对多的方式实现简单      3.能够传递context对象(dictionary),context对象携带了关于发送通知的自定义的信息   缺点:      1..在编译期不会检查通知是否能够被观察者正确的处理      2.在释放注册的对象时,需要在通知中心取消注册      3.在调试的时候应用的工作控制过程难跟踪      4.需要提前注册观察者      5.发送通知。不能获取任何反馈信息 KVO     优点:     1.能够提供一种简单的方法实现两个对象间的同步。例如:model和view之间同步;     2.能够对内部对象的状态改变作出相应     3.能够获取旧值和新值     4.用key paths来观察属性,因此也可以观察嵌套对象     缺点:     1.我们观察的属性必须使用strings来定义。因此在编译器不会出现警告以及检查;     2.对属性重构将导致我们的观察代码不再可用;     3.复杂的“IF”语句要求对象正在观察多个值。这是因为所有的观察代码通过一个方法来指向     4.需要释放观察者

+(void)load 在那个函数调用的?

由libSystem dyld里的_read_images函数


rumtime下category的结构?

struct _category_t {    const char *name; // 1注意,并不是category小括号里写的名字,而是类的名字    struct _class_t *cls; // 2要扩展的类对象,编译期间这个值是不会有的,在app被runtime加载时才会根据name对应到类对象    const struct _method_list_t *instance_methods; // 3这个category所有的-方法    const struct _method_list_t *class_methods; // 4这个category所有的+方法    const struct _protocol_list_t *protocols; // 5这个category实现的protocol,比较不常用在category里面实现协议,但是确实支持的    const struct _prop_list_t *properties; // 6这个category所有的property,这也是category里面可以定义属性的原因,不过这个property不会@synthesize实例变量,一般有需求添加实例变量属性时会采用objc_setAssociatedObject和objc_getAssociatedObject方法绑定方法绑定,不过这种方法生成的与一个普通的实例变量完全是两码事。}