iOS 底层学习方向、面试总结

iOS常见基础面试题(附参考答案)

2021-05-30  本文已影响0人  编程怪才_凌雨画

基础部分

1.为什么说OC是一门动态的语言?

2.讲一下MVC和MVVM,MVP

3.为什么代理要用weak?代理的delegate和dataSource有什么区别?block和代理的区别?

4.属性的实质是什么?包括哪几个部分?属性默认的关键字都有哪些?@dynamic关键字和@synthesize关键字是用来做什么的?

5.属性的默认关键字是什么?

ARC下:

MRC下:

6.NSString为什么要用copy关键字,如果用strong会有什么问题?(注意:这里没有说用strong就一定不行。使用copy和strong是看情况而定的)

@interface Person : NSObject

@property(nonatomic ,copy)NSString *cpName;
@property(nonatomic ,strong)NSString *stName;

@end

@implementation Person
@end

main(){
    NSMutableString *string = [NSMutableString stringWithFormat:@"name"];

    Person *person = [[Person alloc]init];
    person.cpName = string;
    person.stName = string;

    [string appendString:@"name"];
    NSLog(@"cpName:%@ stName:%@",person.cpName,person.stName);
}

打印结果如下:

cpName:name stName:namename

至于为什么要用copy, 大概是为了防止mutableString被无意中修改。

7.如何令自己所写的对象具有拷贝功能?

8.可变集合类 和 不可变集合类的 copy 和 mutablecopy有什么区别?如果是集合是内容复制的话,集合里面的元素也是内容复制么?

//不可变字符串
NSString *string = @"string";
NSString *cpString1 = [string copy];            //指针拷贝
NSString *mcpString1 = [string mutableCopy];    //内容拷贝,生成可变对象
NSMutableString *mstr = [string mutableCopy];   //同上
NSLog(@"%p %p %p %p",string,cpString1,mcpString1,mstr);
打印结果如下:
0x100001070 0x100001070 0x10051bbc0 0x100600e10

//可变字符串
NSMutableString *mstr1 = [[NSMutableString alloc]initWithString:@"abcde"];
NSMutableString *mstr2 = [mstr1 copy];          //内容拷贝,生成不可变字符串
NSString *cpstring2 = [mstr1 copy];             //同上
NSMutableString *mstr3 = [mstr1 mutableCopy];   //内容拷贝
NSLog(@"%p %p %p %p",mstr1,mstr2, cpstring2,mstr3);
打印结果如下:
0x102063110 0x656463626155 0x656463626155 0x102063160

NS* NSMutable*等集合类的copy、mutableCopy同上述一样,需要注意的是,集合里面的元素并没有内容拷贝!若集合层级很多,且需要完全内容拷贝,可以利用NSKeyedArchiver实现。

9.为什么IBOutlet修饰的UIView也适用weak关键字?

10.nonatomic和atomic的区别?atomic是绝对的线程安全么?为什么?如果不是,那应该如何实现?

11.UICollectionView自定义layout如何实现?

12.用StoryBoard开发界面有什么弊端?如何避免?

13.进程和线程的区别?同步异步的区别?并行和并发的区别?

14.线程间通信?

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;
dispatch_async(otherQueue, ^{
    // dosth
});

[otherQueue addOperationWithBlock:^{
    // dosth
}];

15.GCD的一些常用的函数?(group,barrier,信号量,线程同步)


- (void)gcdGroup{
    dispatch_group_t group =  dispatch_group_create();

    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // dosth1;
    });
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // dosth2;
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // dosthNotify;
    });
}
- (void)barrier {
    dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(queue, ^{
        // dosth1;
    });
    dispatch_async(queue, ^{
        // dosth2;
    });
    dispatch_barrier_async(queue, ^{
        // doBarrier;
    });
    dispatch_async(queue, ^{
        // dosth4;
    });
    dispatch_async(queue, ^{
        // dosth5;
    });
}

16.如何使用队列来避免资源抢夺?

17.数据持久化的几个方案(fmdb用没用过)

18.说一下AppDelegate的几个方法?从后台到前台调用了哪些方法?第一次启动调用了哪些方法?从前台到后台调用了哪些方法?

// 当应用程序启动时(不包括已在后台的情况下转到前台),调用此回调。launchOptions是启动参数,假如用户通过点击push通知启动的应用,这个参数里会存储一些push通知的信息
– (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions NS_AVAILABLE_IOS(3_0);
– (void)applicationDidBecomeActive:(UIApplication *)application;

//应用即将从前台状态转入后台
- (void)applicationWillResignActive:(UIApplication *)application;
– (void)applicationDidEnterBackground:(UIApplication *)application NS_AVAILABLE_IOS(4_0);

//从后台到前台调用了:
– (void)applicationWillEnterForeground:(UIApplication *)application NS_AVAILABLE_IOS(4_0);
– (void)applicationDidBecomeActive:(UIApplication *)application;

App启动过程如下:


输入图片说明

19.NSCache优于NSDictionary的几点?

20.知不知道Designated Initializer(指定初始化)?使用它的时候有什么需要注意的问题?

NSObject *object = [[NSObject alloc] init];

类方法+ alloc,其根据要创建的实例对象对应的类来分配足够的内存空间。除了分配内存空间,其实+ alloc方法还做了其他事情,包括将对象的引用计数记为1,将对象的isa指针指向对应的运行时类对象,以及将对象的成员变量置为对应的0值(0、nil、NULL)。但是+ alloc方法返回的对象还是不可用的,在之后完成初始化方法的调用后,对象的创建工作才算完成。初始化方法会设置对象的成员变量为一个正确的合理的值,以及获取一些其他额外的资源。

1.Designated Initializer 指定初始化方法

所有对象都是要初始化的,而且很多情况下,对象在初始化时是需要接收额外的参数,这就可能会提供多个初始化方法。

- (instancetype)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)ti NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithTimeIntervalSinceNow:(NSTimeInterval)secs;
- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)secs;
- (instancetype)initWithTimeInterval:(NSTimeInterval)secsToBeAdded sinceDate:(NSDate *)date;

根据规范,通常选择一个接收参数最多的初始化方法作为指定初始化方法,真正的数据分配和其他相关初始化操作在这个方法中完成。而其他的初始化方法则作为便捷初始化方法去调用这个指定初始化方法。这样当实现改变时,只要修改指定初始化方法就可以了。便捷初始化方法接收的参数更少,它会在内部调用指定初始化方法时,直接设置未接收参数的默认值。便捷初始化方法也可以不直接调用指定初始化方法,它可以调用其他便捷初始化方法,但不管调用几层,最终是要调用到指定初始化方法的,因为真正的实现操作是在指定初始化方法中完成的。所有初始化方法统一以- init开始。如上例代码所示,- initWithTimeIntervalSinceReferenceDate方法是一个指定初始化方法,而其他初始化方法最终是要调用它的。

2.子类实现指定初始化方法

当子类继承父类后实现了新的指定初始化方法,此时如果调用父类中的指定初始化方法则无法调用到子类新实现的初始化逻辑,所以子类同时还要重写父类的指定初始化方法,将其变为一个便捷初始化方法,最终去调用子类自己的指定初始化方法。而为了保证父类初始化逻辑的执行,在子类指定初始化方法中,首先要通过关键字super调用父类的指定初始化方法。 详见正确编写Designated Initializer的几个原则

3.initWithCoder

如果父类也实现了协议,首先要调用父类的- initWithCoder:方法,如果父类没有实现,则调用父类的指定初始化方法。

4.NS_DESIGNATED_INITIALIZER

当在接口中指定初始化方法的后面加上该宏,编译器就会检查我们实现的初始化调用链是否符合规则,并提示相应的警告。

- (instancetype)init NS_DESIGNATED_INITIALIZER;复制代码

21.实现description方法能取到什么效果?

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

文末推荐:iOS热门文集&视频解析

上一篇下一篇

猜你喜欢

热点阅读