问题一 HTTP 中 GET 与 POST 的区别
1.GET在浏览器回退时是无害的,而POST会再次提交请求。
2.GET产生的URL地址可以被Bookmark,而POST不可以
3.GET请求会被浏览器主动cache,而POST不会,除非手动设置。
4.GET请求只能进行url编码,而POST支持多种编码方式。
5.GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
6.GET请求在URL中传送的参数是有长度限制的,而POST么有。
7.对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
8.GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
9.GET参数通过URL传递,POST放在Request body中。
GET和POST是什么?HTTP协议中的两种发送请求的方法。
HTTP是什么?HTTP是基于TCP/IP的关于数据如何在万维网中如何通信的协议。
HTTP的底层是TCP/IP。所以GET和POST的底层也是TCP/IP,也就是说,GET/POST都是TCP链接。GET和POST能做的事情是一样一样的。你要给GET加上request body,给POST带上url参数,技术上是完全行的通的。
GET和POST还有一个重大区别:
简单的说:
GET产生一个TCP数据包;POST产生两个TCP数据包。
长的说:
对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
为什么不推荐用 GET 替换 POST 优化网站性能:
1. GET与POST都有自己的语义,不能随便混用。
2. 据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。
3. 并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。
问题二 手写一个单例
static ZManager *instance = nil;
+ (instancetype)shareInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
+ (id)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone: zone];
});
return instance;
}
- (id)copyWithZone:(NSZone *)zone {
return instance;
}
问题三 如何高效的切圆角
切圆角共有以下三种方案:
1. cornerRadius + masksToBounds:适用于单个视图或视图不在列表上且量级较小的情况,会导致离屏渲染。
2. CAShapeLayer+UIBezierPath:会导致离屏渲染,性能消耗严重,不推荐使用。
3. Core Graphics:不会导致离屏渲染,推荐使用。
问题四 修饰符 copy 和 strong 的区别
对于普通的 NSString 字符串类型来说:
1. 如果赋值给该字符串的源字符串是不可变类型,那么 copy 和 strong 就是等价的,都是浅拷贝,地址都一样。
2. 如果赋值给该字符串的源字符串是可变类型, 那么 copy 执行的操作就是深拷贝,后面改变了可变字符串的值,但是该字符串的值是不会变的。strong 还是浅拷贝。
举个例子:
@property (nonatomic, strong) NSString *strongStr;
@property (nonatomic, copy) NSString *copyedStr;
//不可变字符串赋值
- (void)testString {
NSString *string = [NSString stringWithFormat:@"lalala"];
self.strongStr = string;
self.copyedStr = string;
NSLog(@"origin string: %p, %p", string, &string);
NSLog(@"strong string: %p, %p", _strongStr, &_strongStr);
NSLog(@"copyed string: %p, %p", _copyedStr, &_copyedStr);
}
//可变字符串赋值
- (void)testMutbleString {
NSMutableString *mutbleString = [NSMutableString stringWithFormat:@"hahaha"];
self.strongStr = mutbleString;
self.copyedStr = mutbleString;
NSLog(@"mut origin string: %p, %p", mutbleString, &mutbleString);
NSLog(@"mut strong string: %p, %p", _strongStr, &_strongStr);
NSLog(@"mut copyed string: %p, %p", _copyedStr, &_copyedStr);
[mutbleString appendString:@"wawawa"];
NSLog(@"mut origin string: %p, %p", mutbleString, &mutbleString);
NSLog(@"mut strong string: %p, %p", _strongStr, &_strongStr);
NSLog(@"mut copyed string: %p, %p", _copyedStr, &_copyedStr);
}
但是问题来了:既然copy安全,那为什么不都用copy?
这里我们需要了解一点,copy 修饰的 NSString 在进行 set 操作时,进行 str = sourceStr 操作时,底层是这样实现的:
str = [sourceStr copy];
if ([str isMemberOfClass:[str class]])
没错,就是进行一次判断,判断来源是可变的还是不可变的。如果是不可变,接下来的操作就跟 strong 修饰的没有区别,进行浅拷贝;如果是可变的,那么会进行一次深拷贝。所以 copy 操作内部会进行判断,别小看了这个 if 操作所消耗的内存,一次不重要,十次可能也可以忽略不计,但当你的项目十分庞大时,有成百上千个 NSString 对象,多多少少会对你的 App 的性能造成一定的影响!