iOS面试题总结

2017-08-17  本文已影响0人  youngfisher

1. @property 的本质是什么?ivar、getter、setter 是如何生成并添加到这个类中的

2. @synthesize和@dynamic分别有什么作用?

  1. @property与@synthesize@property与@dynamic,是一一对应并且成对出现的,@property只起到getter和setter方法声明的作用,而实现则是由@synthesize来完成。如果 @synthesize@dynamic都没写,那么编译器默认添加的就是@syntheszie var = _var
  2. @synthesize语义是如果没有手动生成getter 和setter,那么编译器自动生成。并且它自动合成的一共有三项_ivarsettergetter,合成规则:要么合成三项,要么都不合成。
  3. @dynamic语义是告诉编译器不要为我生成_ivar变量、和getter 和setter方法,我要自己实现

3. runtime 如何实现 weak 属性

4. @property中有哪些属性关键字

  1. 原子性:nonatomicatomic(默认)
    在默认情况下,由编译器合成的方法(set和get方法)会通过锁定机制确保其原子性(atomicity)。如果属性具备 nonatomic 特质,则不使用自旋锁。
  2. 读写:readwrite(读写)readonly (只读)
  3. 内存语义:assign、strong、 weak、unsafe_unretained、copy、retain
  4. 方法名:getter=<name>setter=<name>
    @property (nonatomic, getter=isOn) BOOL on;

5. weak属性需要在dealloc中置nil吗

不需要:ARC下不需要在dealloc中置nil,ARC会自动置nil。

6. ARC下,不显式指定任何属性关键字时,默认的关键字都有哪些

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

7. 一个objc对象如何进行内存布局?(考虑有父类的情况)

  1. 内部存储所有父类的成员变量和自己的成员变量
  2. isa指针

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

无论在MRC下还是ARC下均不需要。

9. 直接_objc_msgForward调用它将会发生什么

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

11. runloop的mode作用是什么?

12. dispatch_barrier_async的作用是什么?

12. 以下代码运行结果如何?

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

以上代码执行后只输出1。因为主线程发生了死锁

原因:在主队列中以同步(sync)的方式派发一个任务会出现一下两种情况:这样就发生“你等我我等你的状况”谁也不执行(挂起状态),所以死锁

  1. 当前任务需要等待主队列中的任务执行完成以后才能执行(因为是穿行队列)
  2. 而当前执行的派发任务(dispatch_sync)要等block中的任务执行完成以后才能执行

13. addObserver:forKeyPath:options:context:各个参数的作用分别是什么,observer中需要实现哪个方法才能获得KVO回调?

// 添加键值观察
/*
1 观察者,负责处理监听事件的对象
2 观察的属性
3 观察的选项
4 上下文
*/
[self.person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:@"Person Name"];
// 所有的 kvo 监听到事件,都会调用此方法
/*
 1. 观察的属性
 2. 观察的对象
 3. change 属性变化字典(新/旧)
 4. 上下文,与监听的时候传递的一致
 */
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;

14. 如何手动通知KVO

//  Student.h

#import <Foundation/Foundation.h>

@interface Student : NSObject
{
    NSString  *_age;
}
- (void)setAge:(NSString *)age;
- (NSString *)age;

@property (nonatomic, strong) NSString  *name;

@end
//  Student.m

#import "Student.h"

@implementation Student

@synthesize name = _name;
- (void)setName:(NSString *)name
{
    _name = name;
}
- (NSString *)name
{
    return _name;
}


// 手动设定KVO
- (void)setAge:(NSString *)age
{
    // 最重要的就是下面两个方法(手动通知kvo)
    [self willChangeValueForKey:@"age"];
    _age = age;
    // 在didChangeValueForKey中调用观察者的observerValueForKey
    [self didChangeValueForKey:@"age"];
}
- (NSString *)age
{
    return _age;
}
// 在注册kvo的时候(调用addObserver:)会调用下面方法,返回NO则禁用传入的key的kvo
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
{
    // 如果监测到键值为age,则指定为非自动监听对象
    if ([key isEqualToString:@"age"])
    {
        return NO;
    }
    
    return [super automaticallyNotifiesObserversForKey:key];
}
@end

15. IBOutlet连出来的视图属性为什么可以被设置成weak?

因为既然有外链那么视图在xib或者storyboard中肯定存在,视图已经对它有一个强引用了。
参考stackoverflow
不过这个回答漏了个重要知识,使用storyboard(xib不行)创建的vc,会有一个叫_topLevelObjectsToKeepAliveFromStoryboard的私有数组强引用所有top level的对象,所以这时即便outlet声明成weak也没关系

16. oc中protocol、category和继承的区别

16. Category和Protocol的使用场景,使用时应注意什么

17. 如何检测僵尸对象


18. gcd和NSOperation区别

  1. GCD是底层的C语言构成的API,而NSOperationQueue及相关对象是Objc的对象。在GCD中,在队列中执行的是由block构成的任务,这是一个轻量级的数据结构;而Operation作为一个对象,为我们提供了更多的选择(GCD更轻量,Operation更多元)
  2. NSOperation能方便的取消已经放入队列中的任务、设置任务依赖、设置NSOperation的priority优先级即:使同一个并发队列中的任务区分先后的执行,而在GCD中职能区分不同队列的优先级。而gcd要完成这些则需要编写大量代码。
  3. 我们能将KVO应用在NSOperation中,可以监听一个Operation是否完成或取消,这样子能比GCD更加有效地掌控我们执行的后台任务;
  4. 我们能够对NSOperation进行继承,在这之上添加成员变量与成员方法,提高整个代码的复用度,这比简单地将block任务排入执行队列更有自由度,能够在其之上添加更多自定制的功能。

总的来说当我们的需求能够以更简单的底层代码完成的时候,简洁的GCD或许是个更好的选择,而Operation queue 为我们提供能更多的选择。

19. __block和__weak区别

  1. __block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型,__block修饰基本数据类型的作用就是扩大变量的生命周期(将变量的内存搬到了堆中)
  2. __weak只能在ARC模式下使用,并且只能修饰对象,不能修饰基本数据类型
  3. __block能够在MRC下解决循环引用问题,并且__block修饰的变量能够在block中修改,并且出了block访问外部变量,此时这个外部变量的值是修改过的值。__weak是在ARC下解决循环引用的问题(__weak是__unsafe_unretained的替代品,__unsafe_unretained不会自动置空)
  4. __weak 本身是可以避免循环引用的问题的,但是其会导致外部对象释放了之后,block 内部也访问不到这个对象的问题,我们可以通过在 block 内部声明一个 __strong 的变量来指向 weakObj,使外部对象既能在 block 内部保持住,又能避免循环引用的问题。
    __weak MyObject *weakObj = obj;
     
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    __strong MyObject *strongObj = weakObj;
        if (strongObj) {
            // do something ...
      }
     });
    

20. mrc和arc下block什么时候会持有外部对象

21. oc调用js,js调用oc

上一篇 下一篇

猜你喜欢

热点阅读