iOS一些面试题总结2019.3

1.id、instancetype、NSObject *、id的区别?

1.id与NSObject *
id是Objective-C对象,但是不一定是NSObject对象。
并非所有的Foundation/Cocoa对象都是继承于NSObject对象的,比如NSProxy。他们都遵守NSObject协议。
2.id与instancetype
instancetype只能作为返回值,不能像id那样作为参数。

instancetype可以返回和方法所在类相同类型的对象,id只能返回未知类型的对象(非关联返回类型的方法);

根据Cocoa的命名规则,满足下述规则的方法:
(1)类方法中,以alloc或new开头
(2)实例方法中,以autorelease,init,retain或self开头
会返回一个方法所在类类型的对象,这些方法就被称为是关联返回类型的方法。换句话说,这些方法的返回结果以方法所在的类为类型。

2.extern、static与const的作用?

extern

使用extern可以创建外部文件可以访问的全局变量。这样我们可以让多个类操控同一变量。通过它可以实现全局可变字符串。
例如:

1. 在需要初始化该变量的文件(如:func.m)中,定义变量
NSString *const SDWebImageDownloadStartNotification = @"SDWebImageDownloadStartNotification";
static NSString *const kProgressCallbackKey = @"progress";
2. 在需要用到这一变量的另一文件中使用语句:
extern NSString * const SDWebImageDownloadStartNotification;
声明变量,以表明它已在其他文件中定义。

static

1.作用于变量:
修饰局部变量
①延长局部变量的生命周期(静态数据区),程序结束才会销毁,作用域不变。
②局部变量只会生成一份内存,只会初始化一次。
修饰全局变量
①修改全局变量的作用域,使其只能在本文件中访问,生命周期不会改
②避免重复定义全局变量
2.作用于函数:
使用static用于函数定义时,对函数的连接方式产生影响,使得函数只在本文件内部有效,对其他文件是不可见的。这样的函数又叫作静态函数。使用静态函数的好处是,不用担心与其他文件的同名函数产生干扰,另外也是对函数本身的一种保护机制。

const

用const修饰右边的变量(基本数据变量p,指针变量*p),使其变为只读

 //用const修饰key,表示key只读,不允许修改。
 static  NSString * const key = @"name"; 
 //如果 const修饰 *key1,表示*key1只读,key1还是能改变。
 static  NSString const *key1 = @"name";

3.iOS中内存分区。

1.栈区(stack): 栈区地址从高到低分配,存放的局部变量(先进后出)一旦出了作用域就会被销毁。这个一般由编译器操作,或者说是系统管理,会存一些局部变量,函数跳转跳转时现场保护(寄存器值保存于恢复),这些系统都会帮我们自动实现,无需我们干预。 所以大量的局部变量,深递归,函数循环调用都可能耗尽栈内存而造成程序崩溃 。

2.堆区(heap): 堆区的地址是从低到高分配。一般由程序员管理,比如alloc申请内存,free释放内存。我们创建的对象也都放在这里。

3.全局区(静态区 static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 程序结束后由系统释放。举例:int a;未初始化的。int a = 10;已初始化的。

4.常量区:常量字符串就是放在这里的,还有const常量。

5.代码区:存放代码,app程序会拷贝到这里。


iOS一些面试题总结2019.3_第1张图片

4. __bridge的作用

__bridge可以实现Objective-C与C语言变量 和 Objective-C与Core Foundation对象之间的互相转换
__bridge不会改变对象的持有状况,既不会retain,也不会release
__bridge_retained用于将OC变量转换为C语言变量 或 将OC对象转换为Core Foundation对象
__bridge_retained类似于retain,“被转换的变量”所持有的对象在变量赋值给“转换目标变量”后持有该对象
__bridge_transfer用于将C语言变量转换为OC变量 或 将Core Foundation对象转换为OC对象
__bridge_transfer类似于release,“被转换的变量”所持有的对象在变量赋值给“转换目标变量”后随之释放

    //常见使用
    CGColorRef color =[UIColor redColor].CGColor;
    NSMutableArray *mArray = [NSMutableArray arrayWithCapacity:1];
    [mArray addObject:(__bridge id _Nonnull)(color)];

5.block的使用

block所在函数中的,捕获外部变量。但是不能修改它,不然就是“编译错误”。但是可以改变全局变量、静态变量、全局静态变量。其实这两个特点不难理解:
不能修改外部变量的值是因为:block捕获的是外部变量的const值,名字一样,不能修改。
可以修改静态变量的值:静态变量属于类的,不是某一个变量。由于block内部不用调用self指针。所以block可以调用。
解决block不能修改自动变量的值,这一问题的另外一个办法是使用__block修饰符。 __block 所起到的作用就是只要观察到该变量被 block 所持有,就将“外部变量”在栈中的内存地址放到了堆中。进而在block内部也可以修改外部变量的值。

     __block int a = 0;
    NSLog(@"定义前:%p", &a);         //栈区
    void (^foo)(void) = ^{
        a = 1;
        NSLog(@"block内部:%p", &a);    //堆区
    };
    NSLog(@"定义后:%p", &a);         //堆区
    foo();

你可能感兴趣的:(iOS一些面试题总结2019.3)