强力iOS面试题

以下是问题

[※]@property中有什么属性关键字?

特性相关的显要字,可以按照一些功效来分类

runtime.h(类在runtime中的定义)
struct objc_class {
  Class isa OBJC_ISA_AVAILABILITY; //isa指针指向Meta Class,因为Objc的类的本身也是一个Object,为了处理这个关系,runtime就创造了Meta Class,当给类发送[NSObject alloc]这样消息时,实际上是把这个消息发给了Class Object
  #if !__OBJC2__
  Class super_class OBJC2_UNAVAILABLE; // 父类
  const char *name OBJC2_UNAVAILABLE; // 类名
  long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0
  long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识
  long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小
  struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表
  struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表
  struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法缓存,对象接到一个消息会根据isa指针查找消息对象,这时会在method Lists中遍历,如果cache了,常用的方法调用时就能够提高调用的效率。
  struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表
  #endif
  } OBJC2_UNAVAILABLE;

objc在向一个对象发送音信时,runtime库会依据目的的isa指针找到该目标实际所属的类,然后在此类中的方法列表以及其父类方法列表中查找办法运行,然后在殡葬音讯的时候,objc_msgSend方法不会再次来到值,所谓的回来内容都是现实调用时实施的。
那么,回到本题,假使向一个nil对象发送消息,首先在追寻目的的isa指针时就是0地址再次来到了,所以不会油不过生其他不当。

[※※※]objc中向一个目的发送消息[obj
foo]和objc_msgSend()函数之间有咋样关系?

同上题:[obj foo];在objc动态编译时,会被转意为:objc_msgSend(obj, @selector(foo));

[※※※]咋样时候会报unrecognized selector的异常?

这里也有一篇随笔讲的很清楚。

http://tech.glowing.com/cn/objective-c-runtime/

一句话来说的流水线如下,在上一题中也提到过:

objc是动态语言,每个方法在运行时会被动态转为音讯发送,即:objc_msgSend(receiver, selector)

objc在向一个目的发送消息时,runtime库会依照目的的isa指针找到该对象实际所属的类,然后在此类中的方法列表以及其父类方法列表中寻找办法运行,假诺,在最顶层的父类中依旧找不到对应的章程时,程序在运作时会挂掉并抛出非凡***unrecognized
selector sent to XXX
***。不过在这前边,objc的运作时会给出五遍营救程序崩溃的机遇:

  1. Method resolution
    objc运行时会调用+resolveInstanceMethod:或者
    +resolveClassMethod:,让你有时机提供一个函数实现。如若您添加了函数并赶回
    YES,这运行时系统就会重新启航两遍音信发送的过程,即使 resolve
    方法重返 NO ,运行时就会移到下一步,消息转发(Message
    Forwarding)
  2. Fast forwarding
    万一目的对象实现了-forwardingTargetForSelector:,Runtime
    这时就会调用这多少个艺术,给您把这一个信息转发给其他对象的空子。
    如果这一个办法重返的不是nil和self,整个信息发送的经过就会被重启,当然发送的目的会化为你回到的异常目的。否则,就会延续Normal
    Fowarding

    此间叫Fast,只是为了区别下一步的转会机制。因为这一步不会创立任何新的靶子,但下一步转发会创造一个NSInvocation对象,所以相对更快点。
  3. Normal forwarding
    这一步是Runtime最终一回给您挽救的时机。首先它会发送-methodSignatureForSelector:音信得到函数的参数和再次回到值类型。假设-methodSignatureForSelector:回到nil,Runtime则会时有发生-doesNotRecognizeSelector:新闻,程序这时也就挂掉了。假设回到了一个函数签名,Runtime就会创制一个NSInvocation对象并发送-forwardInvocation:信息给目标对象。

[※※※※]一个objc对象如何开展内存布局?(考虑有父类的意况)

先是发一篇网上最多的答案:

https://github.com/ChenYilong/iOSInterviewQuestions/commit/0e7b5e2b13a5aec84c2d976bfe4f35b4d292383b

以此答案这几天思考了众多,也参照了众四人家的答案,这里写一下和谐的精通。
如故要把objc中class定义的源代码贴上来:

ARC之前

assgin:默认类型,set方法中为间接赋值,即直接针对了一个地点,没有其它引用计数的变动。
retain:set方法中,首先释放(release)此前的靶子,即除去对于旧目的的引用计数,并直接针对新的目的的地址,并使新目的的引用计数加一。
copy:set方法中,与retain类似,先release旧对象,然后对于新的对象举行copy,实质为利用新的内存空间和地点,引用计数唯一,并将对象对象的内容拷贝过来。可以认为是内容拷贝。

runtime.h(类在runtime中的定义)
struct objc_class {
  Class isa OBJC_ISA_AVAILABILITY; //isa指针指向Meta Class,因为Objc的类的本身也是一个Object,为了处理这个关系,runtime就创造了Meta Class,当给类发送[NSObject alloc]这样消息时,实际上是把这个消息发给了Class Object
  #if !__OBJC2__
  Class super_class OBJC2_UNAVAILABLE; // 父类
  const char *name OBJC2_UNAVAILABLE; // 类名
  long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0
  long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识
  long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小
  struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表
  struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表
  struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法缓存,对象接到一个消息会根据isa指针查找消息对象,这时会在method Lists中遍历,如果cache了,常用的方法调用时就能够提高调用的效率。
  struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表
  #endif
  } OBJC2_UNAVAILABLE;

第一,其实自己也不可以说知道内存布局到底是个什么样意思,这些期待有意中人可以帮我解答一下

[※※※※]一个objc对象的isa的指针指向哪些?有什么听从?

[※※※※]下面的代码输出什么?

@implementation Son : Father
- (id)init
{
    self = [super init];
    if (self) {
        NSLog(@"%@", NSStringFromClass([self class]));
        NSLog(@"%@", NSStringFromClass([super class]));
    }
    return self;
}
@end

[※※※※]runtime怎么着通过selector找到呼应的IMP地址?(分别考虑类措施和实例方法)

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

[※※※※※]objc中的类格局和实例方法有什么本质区别和联络?

[※※※※※]_objc_msgForward函数是做如何的,直接调用它将会时有发生如何?

[※※※※※]runtime如何兑现weak变量的电动置nil?

[※※※※※]能否向编译后取得的类中追加实例变量?能否向运行时创立的类中添加实例变量?为啥?

[※※※]runloop和线程有什么关联?

[※※※]runloop的mode成效是何等?

[※※※※]以+scheduled提姆(Tim)erWith提姆(Tim)eInterval…的形式触发的timer,在滑行页面上的列表时,timer会暂定回调,为何?咋样解决?

[※※※※※]揣度runloop内部是什么样促成的?

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

[※※※※]ARC通过哪些点子帮衬开发者管理内存?

[※※※※]不手动指定autoreleasepool的前提下,一个autorealese对象在怎样时刻释放?(比如在一个vc的viewDidLoad中创制)

[※※※※]BAD_ACCESS在哪些动静下冒出?

[※※※※※]苹果是怎么兑现autoreleasepool的?

[※※]运用block时怎么状态会生出引用循环,怎么样缓解?

[※※]在block内什么修改block外部变量?

[※※※]利用系统的某些block
api(如UIView的block版本写动画时),是否也设想引用循环问题?

[※※]GCD的队列(dispatch_queue_t)分哪两种档次?

[※※※※]咋样用GCD同步若干个异步调用?(如基于若干个url异步加载多张图片,然后在都下载完成后合成一张整图)

[※※※※]dispatch_barrier_async的功力是何许?

[※※※※※]苹果为什么要丢弃dispatch_get_current_queue?

[※※※※※]以下代码运行结果什么?

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"1");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"2");
    });
    NSLog(@"3");
}

[※※]addObserver:forKeyPath:options:context:各样参数的意义分别是怎么,observer中需要实现哪个方法才能博取KVO回调?

[※※※]怎么着手动触发一个value的KVO

[※※※]若一个类有实例变量NSString
*_foo,调用setValue:forKey:时,可以以foo还是_foo作为key?

[※※※※]KVC的keyPath中的集合运算符咋样接纳?

[※※※※]KVC和KVO的keyPath一定是属性么?

[※※※※※]怎么样关闭默认的KVO的默认实现,并跻身自定义的KVO实现?

[※※※※※]apple用什么样措施贯彻对一个目的的KVO?

[※※]IBOutlet连出去的视图属性为啥可以被安装成weak?

[※※※※※]IB中User Defined Runtime Attributes咋样利用?

[※※※]怎么调试BAD_ACCESS错误

[※※※]lldb(gdb)常用的调节命令?

来源:http://blog.sunnyxx.com/2015/07/04/ios-interview/


此起彼伏我会把种种对应的答案填上来。

PS:所有答案都是个人见解,有问题请留言我们一块研究~


From:强力iOS面试题

.h文件
#import <Foundation/Foundation.h>
@interface TestClass : NSObject
{
    NSObject *_object;
}
@property (nonatomic, retain) NSObject *object;
@end
@dynamic

该重大字不会自动生成set和get方法,同时避免了编译警告,可是需要我们和好去实现set和get方法,一般在动态绑定或一些需要特别定义读写方法时利用该重大字。

[※※※]ARC下,不显式指定其他性质关键字时,默认的要紧字都有怎么着?

ARC下默认的显要字为:atomic,weak,strong(经@Chrisss校友指正,谢谢),readwrite。
非ARC下默认的机要字为:atomic,retain,readwrite。

实际说起来就是线程相关,内存相关,读写相关。

[※※※]用@property讲明的NSString(或NSArray,NSDictionary)通常采用copy关键字,为何?假使改用strong关键字,可能引致哪些问题?

此间根本考虑的是copy关键字接纳情况,首先要明了copy关键字的真相,copy相当于是展开了一回内容拷贝,其指针地址和内存空间都与被拷贝的对象不同,可是内容是同样的。那么,copy关键字的利用意况就赢得了:

当需要对此一个被赋值的对象内容举办修改,并且无法修改原对象内容时,就应用copy关键字。

重返原题,NSString、NSArray等类都是用于封装数据的结构类,这一个类的目的平日是亟需开展内容改动的。所以,为了避免对于本来赋值对象内容的改动,而只是针对当前类中的对象内容展开修改,就需要接纳copy关键字了。当然,假使确定使用过程中都不需要对目的内容开展改动,那么依据ARC环境使用retain或者strong都是可以的,在必然水平上还是能压缩对于内存的应用。

[※※※]@synthesize合成实例变量的条条框框是什么样?假诺property名为foo,存在一个名为_foo的实例变量,那么还会自动合成新变量么?

以下内容是遵照个人的知晓和阅历。

ARC之后

weak:弱引用,与assgin类似,只是当目的释放后,weak类型会活动置空,即将指针设为nil,制止野指针。
strong:强引用,默认类型,与retain类似。

内存计数方面的首要字是objc首要内容。

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

不需要,可以参照下边的答案,weak类型的性能会在目的释放后自行将指针设为nil,制止野指针。

[※※]@synthesize和@dynamic分别有什么效果?

@synthesize

该重大字会在编译期间自动生成set和get方法。当自定义了set或get方法时,会活动覆盖编译器生产的措施。

线程相关

atomic:默认为该属性,功效为在多线程的情状下,编译器自动生成相应的线程安全代码,达到互斥加锁的目标,避免所对应的变量出现读写不同步的题目。
nonatomic:当该变量不需要考虑多线程的景观时利用该重大字,可以增进性能和频率。

atomic首要用以线程保护的,可以避免当一个线程在对一个地点进行走访时防备另一个线程对此地方同时展开访问,制止了多少失实。众所周知,线程锁会耗费系统资源,所以在其实使用时,假若没无线程相关的情节,提议利用nonatomic。
当下多数的iOS app中,nonatomic的广泛接纳也是基于性能考虑的。

读写相关

readwrite:默认类型,会自动生成相应的读写方法。
readonly:只变动对应的get方法,不生成set方法。

重点使用目的:控制外部类对该属性的造访权限。

内存引用相关

这边又遵照系统版本分为两类,一类是iOS 5.0事先,一类是iOS
5.0投入了ARC机制之后。

网上乱逛看到的强力面试题list,问人家问自己都是好干货,存了。

@synthesize合成实例变量的条条框框是:

在代码的兑现公文(.m文件)里面自动生成指定实例的get和set方法。

只要在代码的注明文件(.h文件)中未定义ivar注解,在当前Xcode
6.0本子中,只要定义了property类型,不需要写@synthesize关键字,编译器会动态创设相呼应的ivar变量,如:@synthesize foo = _foo;
在头里的Xcode版本不会动态变化对应的合成代码,需要手写,完整的写法如下:

.m文件
#import "TestClass.h"
@implementation TestClass
@synthesize object = _object; //这里写成@synthesize object;也是可以的,但是相应的属性名称和ivar名称就是相同的了。在调用时,如果直接写object,就是ivar调用;如果是self.object则是调用get方法。
@end
当存在一个名为_foo的实例变量,那么还会自动合成新变量么?

不会。

程序员都不在乎的warning众

[※※※※※]在有了自动合成属性实例变量之后,@synthesize还有什么使用情况?

这里有一个答案,看起来挺合适的。

http://stackoverflow.com/questions/19784454/when-should-i-use-synthesize-explicitly

切实说起来就是:

不会自动生成的地点,又不想协调写get和set方法,就用那多少个。

[※※]objc中向一个nil对象发送音信将会生出什么?

不会暴发什么样。那个答案讲的很详细:

http://blog.csdn.net/hanangellove/article/details/45013581

切实原因如下:

objc是动态语言,每个方法在运作时会被动态转为音讯发送,即:objc_msgSend(receiver, selector)

那么,为了便于了然这些情节,如故贴一个objc的源代码:


相关文章