問題一 HTTP 中 GET 與 POST 的區(qū)別
1.GET在瀏覽器回退時是無害的,而POST會再次提交請求。
2.GET產生的URL地址可以被Bookmark,而POST不可以
3.GET請求會被瀏覽器主動cache,而POST不會,除非手動設置。
4.GET請求只能進行url編碼,而POST支持多種編碼方式。
5.GET請求參數(shù)會被完整保留在瀏覽器歷史記錄里,而POST中的參數(shù)不會被保留。
6.GET請求在URL中傳送的參數(shù)是有長度限制的,而POST么有。
7.對參數(shù)的數(shù)據(jù)類型,GET只接受ASCII字符,而POST沒有限制。
8.GET比POST更不安全,因為參數(shù)直接暴露在URL上,所以不能用來傳遞敏感信息。
9.GET參數(shù)通過URL傳遞,POST放在Request body中。
GET和POST是什么?HTTP協(xié)議中的兩種發(fā)送請求的方法。
HTTP是什么?HTTP是基于TCP/IP的關于數(shù)據(jù)如何在萬維網中如何通信的協(xié)議。
HTTP的底層是TCP/IP。所以GET和POST的底層也是TCP/IP,也就是說,GET/POST都是TCP鏈接。GET和POST能做的事情是一樣一樣的。你要給GET加上request body,給POST帶上url參數(shù),技術上是完全行的通的。
GET和POST還有一個重大區(qū)別:
簡單的說:
GET產生一個TCP數(shù)據(jù)包;POST產生兩個TCP數(shù)據(jù)包。
長的說:
對于GET方式的請求,瀏覽器會把http header和data一并發(fā)送出去,服務器響應200(返回數(shù)據(jù));
而對于POST,瀏覽器先發(fā)送header,服務器響應100 continue,瀏覽器再發(fā)送data,服務器響應200 ok(返回數(shù)據(jù))。
為什么不推薦用 GET 替換 POST 優(yōu)化網站性能:
1. GET與POST都有自己的語義,不能隨便混用。
2. 據(jù)研究,在網絡環(huán)境好的情況下,發(fā)一次包的時間和發(fā)兩次包的時間差別基本可以無視。而在網絡環(huán)境差的情況下,兩次包的TCP在驗證數(shù)據(jù)包完整性上,有非常大的優(yōu)點。
3. 并不是所有瀏覽器都會在POST中發(fā)送兩次包,F(xiàn)irefox就只發(fā)送一次。
問題二 手寫一個單例
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 的區(qū)別
對于普通的 NSString 字符串類型來說:
1. 如果賦值給該字符串的源字符串是不可變類型,那么 copy 和 strong 就是等價的,都是淺拷貝,地址都一樣。
2. 如果賦值給該字符串的源字符串是可變類型, 那么 copy 執(zhí)行的操作就是深拷貝,后面改變了可變字符串的值,但是該字符串的值是不會變的。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 操作時,底層是這樣實現(xiàn)的:
str = [sourceStr copy];
if ([str isMemberOfClass:[str class]])
沒錯,就是進行一次判斷,判斷來源是可變的還是不可變的。如果是不可變,接下來的操作就跟 strong 修飾的沒有區(qū)別,進行淺拷貝;如果是可變的,那么會進行一次深拷貝。所以 copy 操作內部會進行判斷,別小看了這個 if 操作所消耗的內存,一次不重要,十次可能也可以忽略不計,但當你的項目十分龐大時,有成百上千個 NSString 對象,多多少少會對你的 App 的性能造成一定的影響!