iOS日常开发之面试题集锦(持续更新中...)

目录


最近开始找工作,日常记录一些遇到的面试题,可能会有重复发,持续更新、修改,如果那里不对、不准确,欢迎留言,共同进步

1、block的本质

1.1 block的本质

block的本质就是一个object-c对象。
block:存储位置,可能分为3个地方:代码去,堆区、栈区(ARC情况下会自动拷贝到堆区,因此ARC下只能有两个地方:代码去、堆区)
代码区:不访问栈区的变量(如局部变量),且不访问堆区的变量(alloc创建的对象),此时block存放在代码去。
堆区:访问了处于栈区的变量,或者堆区的变量,此时block存放在堆区。–需要注意实际是放在栈区,在ARC情况下会自动拷贝到堆区,如果不是ARC则存放在栈区,所在函数执行完毕就回释放,想再外面调用需要用copy指向它,这样就拷贝到了堆区,strong属性不会拷贝、会造成野指针错区。

1.2 为什么在默认情况下无法修改被block捕获的变量? __block都做了什么?

默认情况下,block里面的变量,拷贝进去的是变量的值,而不是指向变量的内存的指针。
当使用__block修饰后的变量,拷贝到block里面的就是指向变量的指针,所以我们就可以修改变量的值。

1.3 block反向传值

在前一个控制器的touchesBegan:方法内实现如下代码。

// OneViewController.m 
TwoViewController *twoVC = [[TwoViewController alloc] init];      
twoVC.valueBlcok = ^(NSString *str) {
   

      NSLog(@"OneViewController拿到值:%@", str);      
};
      [self presentViewController:twoVC animated:YES completion:nil]; 
     
      
// TwoViewController.h   (在.h文件中声明一个block属性) 
@property (nonatomic ,strong) void(^valueBlcok)(NSString *str);
       
// TwoViewController.m   (在.m文件中实现方法)        
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    
       // 传值:调用block 
       if (_valueBlcok) {
   
            _valueBlcok(@"123456");
        }
    }

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

可变集合类使用copy表示深拷贝,不可变集合类使用copy的时候是浅拷贝。
可变集合类、不可边类型使用mutablecopy表示深拷贝
当是浅拷贝的时候,容器的内容是没有复制的。如果是深拷贝的话,容器的内容都会收到一条copy消息,拷贝出新的内容,从新组成新的容器返回。

3、关于nonatomic和atomic

3.1 区别

nonatomic:表示非原子,不安全,但是效率高。
atomic:表示原子行,安全,但是效率低。

nonatomic的内存管理语义是非原子性的,非原子性的操作本来就是线程不安全的,而atomic的操作是原子性的,但是并不意味着它是线程安全的,它会增加正确的几率,能够更好的避免线程的错误,但是它仍然是线程不安全的。

3.2 atomic是绝对的线程安全么?为什么?

当使用nonatomic的时候,属性的setter,getter操作是非原子性的,所以当多个线程同时对某一属性读和写操作时,属性的最终结果是不能预测的。

当使用atomic时,虽然对属性的读和写是原子性的,但是仍然可能出现线程错误:当线程A进行写操作,这时其他线程的读或者写操作会因为该操作而等待。当A线程的写操作结束后,B线程进行写操作,然后当A线程需要读操作时,却获得了在B线程中的值,这就破坏了线程安全,如果有线程C在A线程读操作前release了该属性,那么还会导致程序崩溃。所以仅仅使用atomic并不会使得线程安全,我们还要为线程添加lock来确保线程的安全。

也就是要注意:atomic所说的线程安全只是保证了getter和setter存取方法的线程安全,并不能保证整个对象是线程安全的。如下列所示:

比如:@property(atomic,strong)NSMutableArray *arr;

如果一个线程循环的读数据,一个线程循环写数据,那么肯定会产生内存问题,因为这和setter、getter没有关系。如使用[self.arr objectAtIndex:index]就不是线程安全的。

据说,atomic要比nonatomic慢大约20倍

3.3 如果不是,那应该如何实现?

好的解决方案就是加锁
具体请见保证线程安全的方式

4、objc在向一个对象发送消息时,发生了什么?

根据对象的isa指针找到类对象id,在查询类对象里面的methodLists方法函数列表,如果没有在好到,在沿着superClass,寻找父类,再在父类methodLists方法列表里面查询,最终找到SEL,根据id和SEL确认IMP(指针函数),在发送消息;

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

1.不能向编译后得到的类增加实例变量
编译后的类已经注册在runtime中,类结构体中的objc_ivar_list实例变量的链表和instance_size实例变量的内存大小已经确定,runtime会调用class_setvarlayout或class_setWeaklvarLayout来处理strong weak引用.所以不能向存在的类中添加实例变量
2.能向运行时创建的类中添加实例变量
运行时创建的类是可以添加实例变量,调用class_addIvar函数.但是的在调用objc_allocateClassPair之后,objc_registerClassPair之前,原因同上.

6 为什么把NSTimer对象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主运行循环以后,滑动scrollview的时候NSTimer却不动了?

nstime对象是在 NSDefaultRunLoopMode下面调用消息的,但是当我们滑动scrollview的时候,NSDefaultRunLoopMode模式就自动切换到UITrackingRunLoopMode模式下面,却不可以继续响应nstime发送的消息。所以如果想在滑动scrollview的情况下面还调用nstime的消息,我们可以把nsrunloop的模式更改为NSRunLoopCommonModes

7 有没有用过运行时,用它都能做什么?

7.1 交换方式

一般写在类的+(void)load方法里面

   /** 获取原始setBackgroundColor方法 */
Method originalM = class_getInstanceMethod([self class], @selector(setBackgroundColor:));
/** 获取自定义的pb_setBackgroundColor方法 */
Method exchangeM = class_getInstanceMethod([self class], @selector(pb_setBackgroundColor:));
/** 交换方法 */
method_exchangeImplementations(originalM, exchangeM);

7.2 创建类

Class MyClass = objc_allocateClassPair([NSObject class], "Person", 0);

7.3 添加方法

/**参数一、类名参数
   二、SEL 添加的方法名字参数
    三、IMP指针 (IMP就是Implementation的缩写,它是指向一个方法实现的指针,每一个方法都有一个对应的IMP)
  参数四、其中types参数为"i@:@“,按顺序分别表示:具体类型可参照[官方文档](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html)i 返回值类型int,若是v则表示void@ 参数id(self): SEL(_cmd)@ id(str)
  V@:表示返回值是void 带有SEL参数 (An object (whether statically typed or typed id))
  */
class_addMethod(Person, @selector(addMethodForMyClass:), (IMP)addMethodForMyClass, "V@:");

7.4 添加实例变量

/**参数一、类名参数
  二、属性名称参数
  三、开辟字节长度参数
  四、对其方式参数
  五、参数类型 “@” 官方解释 An object (whether statically typed or typed id) (对象 静态类型或者id类型) 具体类型可参照[官方文档](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html)return: BOOL 是否添加成功
  */
BOOL isSuccess = class_addIvar(Person, "name", sizeof(NSString *), 0, "@");
isSuccess?NSLog(@"添加变量成功"):NSLog
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值