【问题总结】

265 阅读6分钟

一、init的实现

  • 代码

    - (instancetype)init
    {
      if (self = [super init]) 
      {
        // 给属性赋值
        _xxx = @"xxx";
      }
      return self;
    }
    
  • 为什么用instancetype而不用id

    www.jianshu.com/p/bd913b3a8…

    • 区别1:

      • instancetype用来在编译期确定实例的类型
      • 而使用id的话,编译期不检查类型,运行时检查类型
    • 区别2:

      • id可以作为方法的参数
      • instancetype不可以,instancetype只适用于初始化方法和便利构造器的返回值类型
  • 扩展1:手写一个类

    // Person.h
    @interface Person : NSObject
    ​
    @property (nonatomic , strong , readonly)NSString *name;
    ​
    @end
    
    // Person.m
    #import "Person.h"@interface Person ()@property (nonatomic , strong , readwrite)NSString *name;
    ​
    @end@implementation Person
    ​
    - (instancetype)initWithName:(NSString *)name
    {
        if (self = [self init])
        {
            _name = name;
        }
        return  self;
    }
    @end
    
  • 扩展2:手写分类

    www.jianshu.com/p/94813aece…

    // Person+Net.h
    #import "Person.h"@interface Person(Net)@property(nonatomic,copy)NSString *nickName;
    ​
    @end
    //  Person+Net.m
    #import "Person+Net.h"
    #import <objc/runtime.h>static NSString *nickNameKey = @"nickNameKey"; //一个属性定义一个@implementation Person(nickName)
    ​
    -(void)setStr:(NSString *)str
    {
        objc_setAssociatedObject(self, &nickNameKey, str,OBJC_ASSOCIATION_COPY);
        /*
        strong修饰的类型用 OBJC_ASSOCIATION_RETAIN_NONATOMIC
        copy  修饰的类型用 OBJC_ASSOCIATION_COPY
        assin 修饰的类型用 OBJC_ASSOCIATION_ASSIGN
        */
    }
    ​
    -(NSString*)str
    {
        return objc_getAssociatedObject(self, &nickNameKey);
    }
    @end
    
  • 扩展3:手写单例

    //  ChangeNameEngine.h
    @interface ChangeNameEngine : NSObject
    ​
    +(instancetype)shareManager;
    ​
    @end
    
    //  ChangeNameEngine.m
    #import "ChangeNameEngine.h"@implementation ChangeNameEngine
    ​
    + (instancetype)shareManager
    {
        static ChangeNameEngine *shareManager = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            shareManager = [[ChangeNameEngine alloc] init];
        });
        return shareManager;
    }
    @end
    
  • 补充:OC中的static

    www.jianshu.com/p/4bfd96c57…

    • 局部变量

      // age没有被static修饰的时候
      - (void)Aboutstatic
      {
          int age = 21;
          age--;
          NSLog(@"age==%d",age);
      }
      ​
      - (void)viewDidLoad {
          [super viewDidLoad];
          
          //在此打印三次结果,看看输出
          [self Aboutstatic];
          [self Aboutstatic];
          [self Aboutstatic];
      }
      ​
      //控制台输出结果可以看到,变量age每次都被初始化为21,所以三次打印结果都为20
      2016-01-15 14:41:47.907 [1754:258152] age==20
      2016-01-15 14:41:47.908 [1754:258152] age==20
      2016-01-15 14:41:47.908 [1754:258152] age==20//age通过static修饰之后
      - (void)Aboutstatic
      {
          static int age = 21;
          age--;
          NSLog(@"age==%d",age);
      }
      //看看控制台输出结果
      2016-01-15 14:49:58.475 [1768:266933] age==20
      2016-01-15 14:49:58.476 [1768:266933] age==19
      2016-01-15 14:49:58.476 [1768:266933] age==18
      
      • 只会被初始化一次,也就是只有一份内存。
      • 生命周期被改变,一直到程序结束才释放
    • 全局变量

      // 1.第一个类中声明一个全局变量和一个方法
      int age_ = 21;
      ​
      - (void)logAge
      {
          NSLog(@"age_==%d",age_);
      }
      ​
      2.在第二个类中使用extern来访问age_
          extern int age_;
          NSLog(@"%d",age_);
      看到控制台打印输出
      2016-01-15 15:26:50.224 [1810:289550] 21// 2.被static修饰的情况下
      static int age_ = 21;
      当继续使用extern引用的时候,就会报错
      Undefined symbols for architecture x86_64:
        "_age_", referenced from:
            -[2eController viewDidLoad] in 2Controller.o
      错误是说在引用age_的时候,找不到这个变量,是因为使用了static修饰,所以除了第一个类自己除外,都访问不到
      
      • 默认情况没有被static修饰的情况下 ①作用域是整个项目,项目中任何地方都能通过extern关键字来引用 ②还是只会被初始化一次,内存地址同样只有一份

      • 被static修饰的情况下

        ①作用域只限于当前文件,项目中任何地方都不能通过extern关键字来引用 ②改变了作用域,但是没有改变生命周期

二、非对称加密原理

  • 对称加密:知道如何加密的同时,便知道如何解密
  • RSA(非对称加密):即使知道了如何加密(公钥),也不知道如何解密(私钥)
    • 例:两个质数的积为公钥,这两个质数为私钥
    • 如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
  • 情景:
    1. 乙方生成一对密钥(公钥和私钥)并将公钥向其它方公开。
    2. 得到该公钥的甲方使用该密钥对机密信息进行加密后再发送给乙方。
    3. 乙方再用自己保存的另一把专用密钥(私钥)对加密后的信息进行解密。乙方只能用其专用密钥(私钥)解密由对应的公钥加密后的信息。
    4. 在传输过程中,即使攻击者截获了传输的密文,并得到了乙的公钥,也无法破解密文,因为只有乙的私钥才能解密密文。
    5. 同样,如果乙要回复加密信息给甲,那么需要甲先公布甲的公钥给乙用于加密,甲自己保存甲的私钥用于解密。

三、不用set和get方法如何设置或获取属性的值

四、int转64位字符串,怎么实现

  • 题目:leetcode-cn.com/problems/co…

  • 解答:

        string toHex(int num1) 
        {
            if (num1 == 0)
                return "0";
            unsigned int num = num1;
            string result = "";
            while (num > 0)
            {
                result.push_back(num % 16 > 9 ? num % 16 - 10 + 'a' : num % 16 + '0');
                num /= 16;
            }
            reverse(result.begin(),result.end());
            return result;
        }
    

五、Layer和view的关系

  • UIView有个layer属性,可以返回它的主CALayer实例,UIView有一个layerClass方法,返回主layer所使用的 类,UIView的子类,可以通过重载这个方法,来让UIView使用不同的CALayer来显示 -UIView 实现了CALayer的delegate
  • UIView本身,更像是一个CALayer的管理器,访问它的跟绘图和跟坐标有关的属性,例如framebounds等等,实际上内部都是在访问它所包含的CALayer的相关属性。
  • UIViewCALayer类似UIView的子View树形结构,也可以向它的layer上添加子layer,来完成某些特殊的表示
  • 区别
    1. 首先UIView可以响应事件,CALayer不可以响应事件
    2. 一个 Layer 的 frame 是由它的 anchorPoint,position,bounds,和 transform 共同决定的,而一个 View 的 frame 只是简单的返回 Layer的 frame
    3. UIView主要是对显示内容的管理而 CALayer 主要侧重显示内容的绘制
    4. 在做 iOS 动画的时候,修改非 RootLayer的属性(譬如位置、背景色等)会默认产生隐式动画,而修改UIView则不会。

六、view和vc的关系

七、Readonly修饰属性,会生成set方法吗?

只读,只生成 getter 方法的声明和实现。为了达到封装的目的,我们应该只在确有必要时才将属性对外暴露,并且尽量把对外暴露的属性设为 readonly。如果这时候想在对象内部通过 setter 修改属性,可以在类扩展中将属性重新声明为 readwrite;如果仅在对象内部通过 _ivar 修改,则不需要重新声明为 readwrite。