1 super、superClass、class
-
self -> 当前对象
class:获取当前方法调用者的类。
superClass:获取当前方法调用者的父类。 -
super:仅仅是一个编译器指示器,就是给编译器看的,不是一个指针。
本质:只要编译器看到super这个标志,就会让当前对象去调用父类方法,本质还是当前对象在调用。
NSLog(@"%@ %@ %@ %@",[self class], [self superclass], [super class], [super superclass]);
2 添加文件未加入勾选target以及重复编译问题
Snip20191223_1.png Snip20191223_2.png Snip20191223_3.png3 const
1 const与宏区别
宏:常用字符串,常见基本变量
const:苹果推荐使用方式,而不是宏
const与宏的区别
- 编译时刻不同:宏:预编译 const:编译
- 编译时刻:宏没有编译检查,const有编译检查
- 宏的好处:定义函数,方法,const不可以
- 宏的坏处:大量使用宏,会导致预编译时间过长
2 const基本使用
- 用于修饰右边的基本变量(int a)或者指针变量(int *p)
- 被const修饰的变量只读
//修饰基本变量: 两种方式效果一样
const int a = 3
int const a = 3
// 修饰指针变量
int b = 3
int * const p = &a;
int c = 4;
p = &b; //会报错
int const *q = &a;
*q = 5; // 会报错
int * const p; // *p:变量 p:只读
int const *p1; // *p1:只读 p1:遍历
const int *p2; // *p2:只读 p2:变量
const int * const p3; // *p3:只读 p3:只读
int const * const p4; // *p4:只读 p4:只读
3 const使用场景
- 修饰全局变量 => 全局只读变量
- 修饰方法中参数
NSString * const cellReuseIndentifier = @"resueCell";
// 这种方法不能在方法内部修改变量值
- (void)test:(int const *)a {
....
}
4 static和extern
1 static
- 修饰局部变量,
1.被static修饰的局部变量,延长生命周期,跟整个应用程序有关
2.被static修饰的局部变量,只会分配一次内存
3.被static修饰的局部变量,程序运行就会给static修饰变量分配内存 - 修饰全局变量
被static修饰的全局变量,作用域会修改,只能在当前文件下使用
2 extern
- 声明外部的全局变量
注意:extern只能用于声明,不能用于定义 - 工作原理:先会去当前文件下查找有没有全局变量,如果没有,才会去其他文件查找
- 全局变量也是在系统运行的时候就会分配内存
3 static和const的联合使用
- 使用static修饰的全局变量只能在当前文件夹下使用
4 extern和const联合使用
开发规范:全局变量不能定义在自己的类中,自己创建全局文件管理全局东西。
5 通知
- 通知顺序:通知需要先进行监听,再发送通知。
- (void)viewDidLoad {
[super viewDidLoad];
// 监听通知
// name:通知名字
// object:谁发的通知
// queue:决定block在哪个线程执行,nil:在发布通知的线程中执行
// usingBlock:只要监听到通知,就会执行block
self.observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"name" object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
NSLog(@"%@",[NSThread currentThread]);
}];
// 发送通知
// 通知名字
// 谁发的通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"note" object:nil];
}
- (void)dealloc {
// 移除通知
[[NSNotificationCenter defaultCenter] removeObserver:self.observer];
}
- 发送的通知在哪个线程,那么处理通知就是在哪儿线程,但是如果使用block的方式,并且设置了队列为主队列,那么接收通知都是在主线程处理。
- (void)viewDidLoad {
[super viewDidLoad];
// 监听通知
// name:通知名字
// object:谁发的通知
// queue:决定block在哪个线程执行,nil:在发布通知的线程中执行
// usingBlock:只要监听到通知,就会执行block
self.observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"note" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
NSLog(@"%@",[NSThread currentThread]);
}];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// 发送通知
// 通知名字
// 谁发的通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"note" object:nil];
});
}
- (void)dealloc {
// 移除通知
[[NSNotificationCenter defaultCenter] removeObserver:self.observer];
}
6 assign和weak区别
- weak:__weak 修饰 弱指针,不会让引用计数器+1,如果指针对象被销毁,指针会自动清空,ARC才有weak
- assign:__unsafe__unretained修饰,不会让引用计数+1,如果指向对象被销毁,指针不会清空
7 bounds和frame
frame:以父控件左上角为原点
bounds:以自己的左上角为原点
frame和bounds都是用来描述一块区域
frame:描述可视范围
bounds:描述可视范围在内容的区域
所有子控件都是相对于内容
bounds:修改内容原点
相对性:可视范围相对于父控件位置永远不变
可视范围相对于内容,位置改变
- (void)viewDidLoad {
[super viewDidLoad];
UIView *redView = [UIView new];
redView.backgroundColor = [UIColor redColor];
redView.frame = CGRectMake(50, 50, 200, 200);
_redView = redView;
UISwitch *swith = [UISwitch new];
[_redView addSubview:swith];
[self.view addSubview:redView];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
CGRect bounds = self.redView.bounds;
bounds.origin.y += 10;
self.redView.bounds = bounds;
}
scrollView底层滑动其实就是改变其bounds
- (void)viewDidLoad {
[super viewDidLoad];
// => 手指往上拖动,bounds y++ ,内容才会往上走
UIView *scrollView = [[UIView alloc] init];
scrollView.frame = self.view.bounds;
[self.view addSubview:scrollView];
UISwitch *swich = [[UISwitch alloc] init];
[scrollView addSubview:swich];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
[scrollView addGestureRecognizer:pan];
}
- (void)pan:(UIPanGestureRecognizer *)gester {
// 获取手指偏移
CGPoint transitonP = [gester translationInView:gester.view];
// 修改bounds
CGRect bounds = gester.view.bounds;
bounds.origin.y -= transitonP.y;
gester.view.bounds = bounds;
// 复位
[gester setTranslation:CGPointZero inView:gester.view];
}
网友评论