iOS笔记

ios基础-一直更新中

2020-06-25  本文已影响0人  狗蛋的春天

1、new 和 alloc init区别

1、new和alloc/init在功能上几乎是一致的,分配内存并完成初始化。
2、差别在于,采用new的方式只能采用默认的init方法完成初始化,采用alloc的方式可以用其他定制的初始化方法。

2、Objec-C本质

我们平常写的oc代码底层会转成C/C++代码 然后汇编,再机器语言
1、Objec-C--->C/C++------>汇编语言------>机器语言
2、所以Objec-C面向对象都是基于C/C++的数据结构实现的  (结构体)
3、可以clang查看底层实现
4、通过xcode创建一个macOS创建一个Command Line Tool,在main.m里写oc代码进行clang查看。

3、Blcok相关

为什么block对auto和static变量捕获有差异?

      1、auto 变量(函数中声明的变量)是在栈中的,函数结束后释放,随时都能销毁,值传递,不能更改。
           int age=10;
           void (^Block)(void) = ^{
           NSLog(@"age:%d",age);
           };
           age = 20;
           Block();
            打印是10;
      2、static 变量 指针传递。
            2.1 在函数内部声明, 当函数结束后, 不会从内存中释放, 再次调用函数时, 直接使用上次的结果.
            2.2 在全局声明,在当前类作用域。
            static int age=10;
            void (^Block)(void) = ^{
            NSLog(@"age:%d",age);
            };
            age = 20;
            Block();
            打印20;

4、交换a,b两个变量的值

临时变量tmp

    tmp = a;
    a = b;
    b = tmp;

变量相加代理中间值

    a = a+b;
    b = a -b;
    a = a-b;

位运算(^)异或

    异或运算是位运算中的一种,当对应为不相同的时候才置为1(1010^1100= 0110)
    a = a^b;
    b = a^b;
    a = a^b;
    题外话:正数左移<<1 数值翻倍  ,正数右移>>1 数值减半

5、isKindOfClass 和 isMemberOfClass

isKindOfClass判断是不是传进来类的对象,或者是该类父类的对象

isMemberOfClass判断是不是传进来类的对象

    + (BOOL)isMemberOfClass:(Class)cls {
            return self->ISA() == cls;
        }

    - (BOOL)isMemberOfClass:(Class)cls {
         return [self class] == cls;
      }

  + (BOOL)isKindOfClass:(Class)cls {
          for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {
                if (tcls == cls) return YES;
           }
        return NO;
       }

  - (BOOL)isKindOfClass:(Class)cls {
          for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
              if (tcls == cls) return YES;
          }
         return NO;
    }
   Test继承自NSObject ,TTT继承自Test
    Test *tst = [[Test alloc]init];
    TTT *tt = [[TTT alloc]init];     
    NSLog(@"---1---%d",[tst isKindOfClass:[Test class]]);//1
    NSLog(@"---2---%d",[tst isKindOfClass:[NSObject class]]);//1
    NSLog(@"---3---%d",[tt isKindOfClass:[TTT class]]);//1
    NSLog(@"---4---%d",[tt isKindOfClass:[Test class]]);//1

    NSLog(@"---11---%d",[tst isMemberOfClass:[Test class]]);//1
    NSLog(@"---22---%d",[tst isMemberOfClass:[NSObject class]]);//0
    NSLog(@"---33---%d",[tt isMemberOfClass:[TTT class]]);//1
    NSLog(@"---44---%d",[tt isMemberOfClass:[Test class]]); //0

6、KVO实现原理

  1、KVO不会对成员变量进行观察,只对属性进行观察。由此可猜想KVO和属性的setter进行了关联.
  2、KVO是基于Runtime机制实现的
  3、当某个类的对象属性第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何            
  被观察属性的setter方法。派生类在被重写的setter方法内实现真正的通知机制
  4、如果原类为Person,那么生成的派生类名为NSKVONotifying_Person
  5、每个类对象中都有一个isa指针指向当前类,当一个类对象的第一次被观察,那么系统就会偷偷将isa指针指向动态生成的派 
  生类,从而在给被监控属性赋值是执行的是派生类的setter方法
  6、键值观察通知依赖于NSObject的两个方法:willChangeValueForKey:和didChangeValueForKey:,在一个被观察属性发生改变 
  之前,willChangeValueForKey:一定会被调用,这就会记录旧的值。而当改变发生后,didChangeValueForKey:会被调用,继 
       而observeValueForKey:ofObject:change:context:也会被调用

RAM

二、程序(App)启动运行

App安装到手机后,存储在 ROM中,程序启动后,系统会把App程序从ROM里面拷贝到RAM,然后从RAM里面执行代码。

三、RAM内存分布

RAM内存中分5个区

image
#import "ViewController.h"
@interface ViewController ()
@end

NSInteger a = 10;  //全局初始化区
NSArray *array;    //全局未初始化区

@implementation ViewController

- (void)viewDidLoad {

    //UIView *subView 指针存在栈区, [[UIView alloc] init] 对象保存在堆区
    UIView *subView = [[UIView alloc] init];
    NSString *string = @"8888";  // string存在栈上, @"8888" 在常量区。
    static NSInteger count = 0;  // 全局(静态)初始化区, 0 在常量区

}
@end

四、注意事项:

1.栈区中的变量由编译器负责分配和释放,内存随着函数的运行分配,随着函数的结束而释放,由系统自动完成。只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出

2.当App启动后,代码区,常量区,全局区大小已固定,而堆区和栈区是时时刻刻变化的(堆的创建销毁,栈的弹入弹出),所以当使用一个指针指向这两个区里面的内存时,一定要注意内存是否已经被释放,否则会产生程序崩溃。

上一篇 下一篇

猜你喜欢

热点阅读