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个区
- 栈区(stack):
- 存放的局部变量、函数的参数值、函数跳转地址
- 先进后出,一旦出了作用域就会被销毁
- 栈区地址从高到低分配
- 自动管理内存
- 堆区(heap):
- 堆区的内存分配使用的是alloc;
- ARC的内存的管理,是编译器再便宜的时候自动添加 retain、release、autorelease;
- 堆区的地址是从低到高分配)
- 需要程序猿管理内存;
- 全局区/静态区(static):
- 存放全局变量和静态变量(未初始化过 、初始化过)
- 初始化的全局变量和静态变量存放在一块区域,未初始化的全局变量和静态变量在相邻的另一块区域
- 程序结束后由系统释放
- 常量区:常量字符串就是放在这里;
- 存放常量字符串
- 程序结束后由系统释放
- 代码区:
- 存放App代码
- 程序结束后由系统释放

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