面了20多家总结出来的部分iOS面试题(二)

8. load 和 initilze 的调用情况,以及子类的调用顺序问题?

  • initialize 这个方法是第一次给某给类发送消息的时候调用,并且只会调用一次。 如果某一个类一直没有被用到,此方法也不会执行。
  • initialize先初始化父类, 在初始化子类,子类的initialize 会覆盖父类的方法。
  • 分类中实现了initialize会覆盖本来的initialize方法,如果多个分类都执行了initialize ,那么只是执行最后编译的那个。

  • load当程序被加载的时候就会调用, 其加载顺序为, 如果子类实现类load 先执行父类
    -> 在执行子类,而分类的在最后执行。
  • 如果子类不实现load,父类的load就不会被执行。
  • load是线程安全的,其内部使用了锁,所以我们应该避免在load方法中线程阻塞。
  • load在分类中,重写了load方法, 不会影响其主类的方法。即不会覆盖本类的load方法
  • 当有多个类的时候,每个类的load的执行顺序和编译顺序一致。

9. 什么是线程安全?

  • 多条线程同时访问一段代码,不会造成数据混乱的情况

10. 你接触到的项目,哪些场景运用到了线程安全?

答: 举例说明,12306 同一列火车的车票, 同一时间段多人抢票!
如何解决
互斥锁使用格式

synchronized(锁对象) { // 需要锁定的代码  }
注意:锁定1份代码只用1把锁,用多把锁是无效的

Tips: 互斥锁的优缺点
优点:能有效防止因多线程抢夺资源造成的数据安全问题
缺点:需要消耗大量的CPU资源
 
互斥锁的使用前提:多条线程抢夺同一块资源 
相关专业术语:线程同步,多条线程按顺序地执行任务
互斥锁,就是使用了线程同步技术
 
Objective-C中的原子和非原子属性
OC在定义属性时有nonatomic和atomic两种选择
atomic:原子属性,为setter/getter方法都加锁(默认就是atomic)
nonatomic:非原子属性,不加锁
 
atomic加锁原理:
property (assign, atomic) int age;
 - (void)setAge:(int)age
{ 
    @synchronized(self) {  
       _age = age;
    }
}

- (int)age {
    int age1 = 0;
    @synchronized(self) {
        age1 = _age;
    }
}


原子和非原子属性的选择
nonatomic和atomic对比
atomic:线程安全,需要消耗大量的资源
nonatomic:非线程安全,适合内存小的移动设备
 
iOS开发的建议
所有属性都声明为nonatomic
尽量避免多线程抢夺同一块资源
尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力

atomic就一定能保证线程安全么?
不能,还需要更深层的锁定机制才可以,因为一个线程在连续多次读取某条属性值的时候,与此同时别的线程也在改写值,这样还是会读取到不同的属性值!  或者 一个线程在获取当前属性的值, 另外一个线程把这个属性释放调了, 有可能造成崩溃

11. 你实现过单例模式么? 你能用几种实现方案?

1. 运用GCD:
import "Manager.h"
implementation Manager
+ (Manager *)sharedManager {
  static dispatch_once_t onceToken;
  static Manager * sharedManager;
  dispatch_once(&onceToken, ^{
    sharedManager=[[Manager alloc] init];
  });
  return sharedManager;
}
end
注明:dispatch_once这个函数,它可以保证整个应用程序生命周期中某段代码只被执行一次!


2. 不使用GCD的方式:
static Manager *manager;
implementation Manager
+ (Manager *)defaultManager {
    if(!manager)
        manager=[[self allocWithZone:NULL] init];
    return  manager;
}
end

3. 正常的完整版本
+(id)shareInstance{
     static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{
      if(_instance == nil)
            _instance = [MyClass alloc] init]; 
    });
     return _instance;
}

//重写allocWithZone,里面实现跟方法一,方法二一致就行.
+(id)allocWithZone:(struct _NSZone *)zone{
   return [self shareInstance];
} 

//保证copy时相同
-(id)copyWithZone:(NSZone *)zone{  
    return _instance;  
} 
//  方法3创建的目的的是  为了方式开发者在调用单例的时候并没有用shareInstance方法来创建 而是用的alloc  或者copy的形式创建造成单例不一致的情况

//   

引申1. 单例是怎么销毁的?

//必须把static dispatch_once_t onceToken; 这个拿到函数体外,成为全局的.
+ (void)attempDealloc {
    onceToken = 0; // 只有置成0,GCD才会认为它从未执行过.它默认为0,这样才能保证下次再次调用shareInstance的时候,再次创建对象.
    _sharedInstance = nil;
}

dispatch_once_t 的工作原理是,static修饰会默认将其初始化为0, 当且仅当其为0的时候dispatch_once(&onceToken, ^{})这个函数才能被调用, 如果执行了这个函数  这个dispatch_once_t 静态变成- 1了  就永远不会被调用

引申2. 不使用dispatch_once 如何 实现单例


1.第一种方式,重写+allocWithZone:方法;
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    static id instance = nil;
    @synchronized (self) { // 互斥锁
        if (instance == nil) {
            instance = [super allocWithZone:zone];
        }
    }
    return instance;
}

2.第二种方式,不用重写+allocWithZone:方法,而是直接用@synchronized 来保证线程安全,其它与上面这个方法一样;
+ (instancetype)sharedSingleton {
    static id instance = nil;
    @synchronized (self) {
        if (!instance) {
            instance = [[self alloc] init];
        }
    }
    return instance;
}

12. 项目开发中,你用单例都做了什么?

答 :整个程序公用一份资源的时候 例如 :

  • 设置单例类访问应用的配置信息
  • 用户的个人信息登录后用的NSUserDefaults存储,对登录类进一步采用单例封装方便全局访问
  • 防止一个单例对 应用 多处 对同意本地数据库存进行操作

13.APNS的基本原理

  • 基本
  • 第一阶段:应用程序的服务器端把要发送的消息、目的iPhone的标识打包,发给APNS。
  • 第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发送到iPhone。
  • 第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。
  • 详细说明

首先是注册

  • Device(设备)连接APNs服务器并携带设备序列号(UUID)
  • 连接成功,APNs经过打包和处理产生devicetoken并返回给注册的Device(设备)
  • Device(设备)携带获取的devicetoken发送到我们自己的应用服务器
  • 完成需要被推送的Device(设备)在APNs服务器和我们自己的应用服务器的注册

推送过程

  • 1、首先手机装有当前的app,并且保持有网络的情况下,APNs服务器会验证devicetoken,成功那个之后会处于一个长连接。 (这里会有面试问? 如果app也注册成功了, 也下载了,也同意了打开推送功能, 这个时候在把App删除了, 还能接受推送了么? )
  • 2、当我们推送消息的时候,我们的服务器按照指定格式进行打包,结合devicetoken 一起发送给APNs服务器,
  • 3、APNs 服务器将新消息推送到iOS 设备上,然后在设备屏幕上显示出推送的消息。
  • 4、iOS设备收到推送消息后, 会通知给我们的应用程序并给予提示

// 推送过程如下图


Alt text

很奇怪 每天最多两篇文文章 全文一共6篇。 每天更新两篇!

你可能感兴趣的:(面了20多家总结出来的部分iOS面试题(二))