1.const 修饰的右边的部分,不可改变
2.static 修饰的变量,程序结束时才释放,变量的地址只创建一次
3.宏 指定的字符串,并不会创建多次,而是只创建一个,它增加的只是预编译的时间
4.extern工作原理:先会去当前文件下查找有没有对应全局变量,如果没有,才会去其他文件查找
5.https的非对称加密,只是在握手时进行一次确认对称加密的密钥,之后大多数都用这个密钥通信,至于这个密钥什么时候失效,还不清楚。
6.抗压缩优先级
两个水平布局的label,两边间隔分别是12,中间间隔为8(懂意思就行)。如果两个label 都不设置宽度,则左边 label 会拉长,右边 label 自适应。
UILabel *label1 = [[UILabel alloc] initWithFrame:CGRectZero];
label1.backgroundColor = [UIColor redColor];
label1.text = @"我是标题";
[self.view addSubview:label1];
[label1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.view);
make.left.equalTo(@(12));
}];
UILabel *label2 = [[UILabel alloc] initWithFrame:CGRectZero];
label2.backgroundColor = [UIColor redColor];
label2.text = @"我是描述";
[self.view addSubview:label2];
[label2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(label1);
make.left.equalTo(label1.mas_right).offset(8);
make.right.equalTo(self.view).offset(-12);
}];
如果想让左边 label 自适应,右边 label 拉升,可以设置控件拉升阻力(即抗拉升),拉升阻力越大越不容易被拉升。所以只要 label1 的拉升阻力比 label2 的大就能达到效果。
//UILayoutPriorityRequired = 1000
[label1 setContentHuggingPriority:UILayoutPriorityRequired
forAxis:UILayoutConstraintAxisHorizontal];
// //UILayoutPriorityDefaultLow = 250
[label2 setContentHuggingPriority:UILayoutPriorityDefaultLow
forAxis:UILayoutConstraintAxisHorizontal];
Content Hugging Priority:拉伸阻力,即抗拉伸。值越大,越不容易被拉伸。
Content Compression Resistance Priority:压缩阻力,即抗压缩。值越大,越不容易被压缩。
7.约束优先级
从左到右依次为红、蓝、黄三个视图三等分,蓝色视图布局依赖红色,黄色视图布局依赖蓝色,如果突然将中间的蓝色视图移除,红色和黄色视图的宽度就无法计算。此种情况可以设置最后一个黄色视图的做约束优先级,移除中间蓝色视图后,红色和黄色视图二等分。
//红 left bottom height
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.view.mas_left).with.offset(20);
make.bottom.mas_equalTo(self.view.mas_bottom).with.offset(-80);
make.height.equalTo(@50);
}];
//蓝 left bottom height width=红色
[blueView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(redView.mas_right).with.offset(40);
make.height.width.bottom.mas_equalTo(redView);
}];
//黄 left right height width=红色
[yellowView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(blueView.mas_right).with.offset(40);
make.right.mas_equalTo(self.view.mas_right).with.offset(-20);
make.height.width.bottom.mas_equalTo(redView);
//优先级
//必须添加这个优先级,否则blueView被移除后,redView 和 yellowView 的宽度就不能计算出来
make.left.mas_equalTo(redView.mas_right).with.offset(20).priority(250);
}];
//移除蓝色
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[blueView removeFromSuperview];
[UIView animateWithDuration:3 animations:^{
//不加这行代码就直接跳到对应的地方,加这行代码就可以执行动画。
//另外还要注意调用layoutIfNeeded的对象必须是执行动画的父视图。
//[blueView.superview layoutIfNeeded];
[self.view layoutIfNeeded];
}];
});
8.为什么数组下标从零开始
数组下标最确切的定义应该偏移(offset),如果用 a 来表示数组的首地址,a[0] 就是偏移为 0 的位置,也就是首地址,a[k] 就表示偏移 k 个 type_size 的位置,所以计算 a[k] 的内存地址只需要用这个公式:
a[k]_address = base_address + k * type_size
但是,如果数组从 1 开始计数,那我们计算数组元素 a[k]的内存地址就会变为:
a[k]_address = base_address + (k-1)*type_size
对比两个公式,不难发现,从 1 开始编号,每次随机访问数组元素都多了一次减法运算,对于 CPU 来说,就是多了一次减法指令。数组作为非常基础的数据结构,通过下标随机访问数组元素又是其非常基础的编程操作,效率的优化就要尽可能做到极致。所以为了减少一次减法操作,数组选择了从 0 开始编号,而不是从 1 开始。
9.通过zone实现单例
+ (instancetype)sharedInstance {
return [[self alloc] init];
}
- (instancetype)init {
if (self = [super init]) {
}
return self;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static LogManager * _sharedInstanc = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedInstanc = [super allocWithZone:zone];//最先执行,只执行了一次
});
return _sharedInstanc;
}
1
2
3
-(id)copyWithZone:(struct _NSZone *)zone{
return [LogManager sharedInstance];
}
1
2
3
-(id)mutableCopyWithZone:(NSZone *)zone{
return [LogManager sharedInstance];
}
8.weakSelf和strongSelf
weakSelf 是为了block不持有self,避免Retain Circle循环引用。在 Block 内如果需要访问 self 的方法、变量,建议使用 weakSelf。 strongSelf的目的是因为一旦进入block执行,假设不允许self在这个执行过程中释放,就需要加入strongSelf。block执行完后这个strongSelf 会自动释放,没有不会存在循环引用问题。如果在 Block 内需要多次 访问 self,则需要使用 strongSelf。
9.xcode打包路径/Users/yanxuefeng/Library/Developer/Xcode/Archives