1术辐、在UIScorllView上添加UISlide,拖動slide的時候施无,scrollerview會跟著動辉词,解決方案
在項目開發(fā)時遇到一個問題,我在UIViewController上面直接創(chuàng)建了一個UIScrollerView猾骡,把UIScrollerView作為一個子視圖添加到了UIViewController瑞躺,
又再UIScrollerView中添加了一個UISlider的組件,在手勢滑動的過程中兴想,很難滑動到UISlider這個控件幢哨,經(jīng)常是滑動的時候UIScrollerView進行了滾動,
而UISlider這個控件沒有滑動嫂便,讓人很抓狂捞镰。
上網(wǎng)具體去了解了一下UIScrollerView的詳解,終于徹底明白了問題出在哪里
下面引用一下前輩的總結(jié)顽悼,因為自己覺得沒有他總結(jié)的詳細
UIScrollView重載了hitTest方法曼振,當手指touch的時候,UIScrollView會攔截所有event,然后等待150ms蔚龙,在這段時間內(nèi)冰评,如果沒有手指沒有移動,當時間結(jié)束時木羹,UIScrollView會發(fā)送tracking event到子視圖上甲雅,并且自身不滑動。在時間結(jié)束前坑填,手指發(fā)生了移動抛人,那么UIScrollView就會進行滑動,從而取消發(fā)送tracking脐瑰。
看來是UIScrollView的問題妖枚。直接拖動UISlider,此時touch時間在150ms以內(nèi)苍在,UIScrollView會認為是拖動自己绝页,從而攔截了event荠商,導(dǎo)致UISlider接受不到滑動的event。但是只要按住UISlider一會再拖動续誉,此時此時touch時間超過150ms莱没,因此滑動的event會發(fā)送到UISlider上。
期間試過幾種方法酷鸦,只有一種可行饰躲,就是重寫UIScrollView的hitTest方法:當滑動UISlider時,使UIScrollView不可滑動臼隔。
但是又出現(xiàn)了一個問題嘹裂,我的UIScrollerView是直接繼承了UIScrollerView,在UIViewController中是無法重寫的UIScrollerView的hitTest方法的躬翁,所以需要重新創(chuàng)建一個view焦蘑,繼承UIScrollerView,然后再重寫上述方法盒发,然后再導(dǎo)入UIViewController中就可以輕松實現(xiàn)了。
2狡逢、IOS 截屏模糊 的問題
情景: 遇到的分享的圖片 很模糊宁舰。
那么首先去搜索下 在你的代碼里面有沒有遇到
用 UIGraphicsBeginImageContext(<#CGSize size#>) 這個方法。
解決:
如果有那么 截屏的圖片肯定是模糊的奢浑,因為在iOS7 的分辨率會改為另外一種代替的方法
就是它 :
UIGraphicsBeginImageContextWithOptions(<#CGSize size#>, <#BOOL opaque#>, <#CGFloat scale#>)
代碼如下:
-(UIImage *)captureImageFromViewLow:(UIView *)orgView {
//獲取指定View的圖片
UIGraphicsBeginImageContextWithOptions(orgView.bounds.size, YES, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.navigationController.view.layer renderInContext:context];//如果截屏中不想帶有導(dǎo)航條的話這行代碼改為[orgView.layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
3蛮艰、側(cè)滑刪除
NSIndexPath *_indexPath;//判斷刪除的是那個cell(側(cè)滑刪除cell)
NSArray *_indexPathArr;
#pragma mark -- 側(cè)滑刪除
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self presentViewController:_alert animated:YES completion:nil];
MessageModel *model = _dataSource[indexPath.section];
_indexPath = indexPath;
_indexPathArr = [NSArray arrayWithObjects:indexPath, nil];
_studentId = model.studentId;
_messageId = model.messageId;
}
}
#pragma mark 給刪除命名為中文的
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
return @"刪除";
}
-(void)createUIAlertController
{
_alert = [UIAlertController alertControllerWithTitle:@"刪除后將不會恢復(fù),是否確認刪除" message:nil preferredStyle:UIAlertControllerStyleAlert];
[_alert addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSString *str = [NSString stringWithFormat:@"%@api/user/deleteMessage.do?messageId=%@&studentId=%@",baseUrl,_messageId,_studentId];
[AFNet JSONDataWithUrl:str success:^(id json) {
NSDictionary *dic = [NullToNone nullDic:json];
NSString *str = dic[@"msg"];
if ([str isEqualToString:@"success"]) {
[dataArray removeObjectAtIndex:_indexPath.row];
//從tableview中刪除指定行
[self.tableV deleteRowsAtIndexPaths:_indexPathArr withRowAnimation:UITableViewRowAnimationFade];
}else{
[SVProgressHUD showErrorWithStatus:@"刪除失敗" duration:1];
return ;
}
} fail:^{
}];
}]];
[_alert addAction:[UIAlertAction actionWithTitle:@"取消"style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {[self.tableView reloadRowsAtIndexPaths:_indexPathArr withRowAnimation:UITableViewRowAnimationFade];
}]];}
4雀彼、AFNetworking
https://www.baidu.com/baidu?tn=monline_3_dg&ie=utf-8&wd=afnetworking
請求頭:我們執(zhí)行網(wǎng)絡(luò)請求的時候給服務(wù)器發(fā)送的包頭信息(包括你當前使用什么設(shè)備請求的壤蚜、當前設(shè)備信息等等)
請求正文:上面例子網(wǎng)址的問號之后的都是請求正文
GET:請求一些簡單的數(shù)據(jù),一般都是明文顯示徊哑,攜帶數(shù)據(jù)量小
POST:處理復(fù)雜的業(yè)務(wù)袜刷,比如上傳圖片,加密參數(shù)等莺丑;與GET不同地方著蟹,1,并不是明文請求梢莽,請求正文被加載到了數(shù)據(jù)當中萧豆,從瀏覽器里很少能看到post請求所攜帶的參數(shù);2昏名,可以攜帶更多的參數(shù)
斷點下載:1涮雷,斷點下載需要服務(wù)器支持; 2轻局,在執(zhí)行請求時洪鸭,我們需要設(shè)定Request fields上的Range參數(shù)才能生效
5样刷、原生APP——優(yōu)缺點
優(yōu)點:1、運行效率高2卿嘲、可調(diào)用各種設(shè)備資源
缺點:1颂斜、人力成本高2、發(fā)布速度慢3拾枣、更新版本的問題(用戶就是不更新)4沃疮、實現(xiàn)圖文混排功能有各種坑(很麻煩)
6、WEBAPP核心思路
HTML5 css3 js? 開發(fā)完了之后打包(用phoneGap等打包)
7梅肤、代理
委托方:1.聲明協(xié)議2.聲明代理3.定義代理方法
.h文件里:
.m文件里:
代理方:1司蔬、遵守協(xié)議2.把自己設(shè)為代理3.實現(xiàn)代理方法
遵守協(xié)議sendDataAttributes;
把自己設(shè)為代理DataNameListController *dataName = [[DataNameListController alloc]init];
dataName.sendDataAttributesDelegate = self;
實現(xiàn)代理方法
-(void)sendDataAttributes:(NSArray *)array{}
8姨蝴、懶加載及self.和下劃線區(qū)別
a.懶加載:?被聲明為屬性的成員俊啼,在ios5之前需要使用編譯器指令@synthesize告訴編譯器幫助生成屬性的getter,setter方法。之后會默認生成左医。編譯器在生成getter,setter方法時先檢查有沒有自定義getter授帕,setter方法,如果有則使用自定義的浮梢,沒有才生成跛十。
懶加載就是重寫屬性的getter方法,然后加一個判斷秕硝,為空則賦值芥映,不為空則返回。代碼如下:
沒有懶加載的情況下远豺,如果想給一個數(shù)組_dataSource賦值奈偏,需要在viewDidload里面寫類似于
_dataSource = @[@"123",@"qe",@"123",@"ad",@"123",@"adasda"];
這就出現(xiàn)了一個問題,當然也不稱得上問題躯护,只是代碼需要優(yōu)化而已惊来,因為當_dataSource需不需要的時候你都要給_dataSource初始化并賦值。這就占用了沒必要的內(nèi)存榛做。如果你只想在用到_dataSource的時候才給它初始化并賦值的時候唁盏,這時你就用到了懶加載。
示例代碼:
- (void)viewDidLoad {
???? [super viewDidLoad];
}
-(NSArray *)dataSource{
?? if(!_dataSource){
????? _dataSource = @[@"123",@"qe",@"123",@"ad",@"123",@"adasda"];
?? }
??? return _dataSource;
}
當需要用到_dataSource的時候检眯,就會調(diào)用[self dataSource]的方法(即getter方法)厘擂。注意:需要注意在getter方法里切勿使用self.dataSource,因為self.dataSource會調(diào)用getter方法锰瘸,造成死循環(huán)刽严。
總結(jié):懶加載即用到時方去加載對象。
b.self.mtest和_mtest的區(qū)別
?在第一次使用時由于沒注意到兩者的區(qū)別眨补,在setter方法中調(diào)用self.mtest,結(jié)果導(dǎo)致了setter方法的循環(huán)調(diào)用甘晤。寫法如下:
?導(dǎo)致原因是,self.mtest會調(diào)用屬性的setter方法塞弊,觸發(fā)懶加載,但是_mtest只是訪問一個局部變量奏候。
9、assign,retain旷档,copy的區(qū)別
解釋一:
一鞋屈、assign屬性
當數(shù)據(jù)類型為int、float等原生類型時,可以使用assign拄氯,否則可能導(dǎo)致內(nèi)存泄露镣煮。例如當使用malloc分配了一塊內(nèi)存典唇,并把它的地址賦值給了指針a盟劫,后來如果希望指針b也共享這塊內(nèi)存塘装,于是講a賦值給(assgin)b。這時就用到了assgin猴娩,此時a和b指向同一塊內(nèi)存。但是現(xiàn)在問題出現(xiàn)了议忽,當a不再需要這塊內(nèi)存時栈幸,能都直接釋放呢?肯定是不能的壳繁,因為a并不知道b是否還在使用這塊內(nèi)存,如果a釋放了羡棵,那么b在使用這塊內(nèi)存的時候引起程序crash掉。
二、retain屬性
retain屬性就是為了解決上述問題而提出的舶胀,使用了引用計數(shù)(reference counting),還是上面那個例子,我們給那塊內(nèi)存設(shè)一個引用計數(shù)基茵,當內(nèi)存唄分配并且賦值給a時,引用計數(shù)是1.當把a賦值給b時引用計數(shù)增加到2.這時如果a不再使用這塊內(nèi)存醋火,它只需要把引用計數(shù)減1柿冲,表明自己不再擁有這塊內(nèi)存。b不再使用這塊內(nèi)存時也把引用計數(shù)減1.當引用計數(shù)變?yōu)?的時候熏瞄,代表該內(nèi)存不再被任何指針所引用,系統(tǒng)可以直接釋放掉邮丰。此時系統(tǒng)自動調(diào)用dealloc函數(shù)斗蒋,內(nèi)存被回收捧书。(自己想了個??:你在小區(qū)有一個車位吹泡,平時你把自己的車停那,你弟弟這時候也想用你的車位经瓷,于是你就retain了一下爆哑,把這個車位使用人數(shù)名字上又增加了一位(引用計數(shù)加一),然后你弟和你都可以共用這一個車位舆吮。當你或者你弟弟其中一個人不想用的時候(引用計數(shù)減一)揭朝,不想用的那個人能直接把車位上交給小區(qū)管理人員嗎(內(nèi)存釋放)彤悔?不可以!因為你不用了说敏,另外一個還在用谴忧,所以還不能把車位上交給小區(qū)管理人員爬虱,當你倆都不想用了的話就可以把車位上交給物業(yè)了)
三稀并、copy屬性
copy是你不希望a和b共享一塊內(nèi)存時會使用到境蜕。a和b各自有自己的內(nèi)存。
解釋二:
舉個例子:
NSString *str = [[NSString alloc] initWithString:@'abc'];
上面一段代碼會執(zhí)行以下兩個動作:
1 在堆上分配一段內(nèi)存用來存儲@'abc' ,比如:內(nèi)存地址為0X1111 內(nèi)容為 'abc'
2 在棧上分配一段內(nèi)存用來存儲str,比如:地址為0XAAAA 內(nèi)容自然為0X1111
下面分別看下(assign,retain,copy):
1.assign的情況:NSString *newStr = [str assign];
此時newStr和str完全相同,地址都是0XAAAA ,內(nèi)容為0X1111 ,即newStr只是str的別名,對任何一個操作就等于對另一個操作。因此retainCount不需要增加.
2.retain的情況:NSString * newStr = [str retain];
此時newStr的地址不再為0XAAAA,可能為0XAABB,但是內(nèi)容依然為0X1111.因此newStr和str都可以管理'abc'所在的內(nèi)存。因此 retainCount需要增加1.
3.copy的情況:NSString * newStr = [str copy];
此時會在堆上重新開辟一段內(nèi)存存放@‘a(chǎn)bc',比如0X1122,內(nèi)容為@'abc,同時會在棧上為newStr分配空間,比如地址:0XAACC,內(nèi)容為0X1122,因此retainCount增加1供newStr來管理0X1122這段內(nèi)存.
NSString為何要用copy?而不是strong?
strong和retain同義, weak和assign同義, 為什么要采用這種說法, 似乎是ARC出現(xiàn)后為了消除引用計數(shù)的觀念而采用的做法. 至于為什么要用copy, 由于純NSString是只讀的, 所以strong和copy的結(jié)果一樣,據(jù)stackOverflow上的說法,是為了防止mutable string被無意中修改, NSMutableString是NSString的子類, 因此NSString指針可以持有NSMutableString對象.
很簡單,假如有一個NSMutableString,現(xiàn)在用他給一個retain修飾 NSString賦值,那么只是將NSString指向了NSMutableString所指向的位置,并對NSMUtbaleString計數(shù)器加一,此時,如果對NSMutableString進行修改,也會導(dǎo)致NSString的值修改,原則上這是不允許的. 如果是copy修飾的NSString對象,在用NSMutableString給他賦值時,會進行深拷貝,及把內(nèi)容也給拷貝了一份,兩者指向不同的位置,即使改變了NSMutableString的值,NSString的值也不會改變.
所以用copy是為了安全,防止NSMutableString賦值給NSString時,前者修改引起后者值變化而用的.
10、view的frame和bounds的區(qū)別
參考這個哥們寫的:http://blog.csdn.net/mad1989/article/details/8711697
11虽另、int 和NSInteger的區(qū)別
原來在蘋果的api實現(xiàn)中暂刘,NSInteger是一個封裝族展,它會識別當前操作系統(tǒng)的位數(shù),自動返回最大的類型爷抓。
當需要使用int類型的變量的時候,可以像寫C的程序一樣虽抄,用int走搁,也可以用NSInteger,但更推薦使用NSInteger迈窟,因為這樣就不用考慮設(shè)備是32位的還是64位的热芹。
定義的代碼類似于下:
#if __LP64__ || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
12舷暮、NSInteger和NSNumber 的區(qū)別
NSNumber是NSValue的子類,一般情況下,其功能就是使得數(shù)字能夠添加到類似NSArray或者NSSet數(shù)據(jù)集合中纤房,NSNumber不僅僅能夠表示NSInteger類型的整形數(shù),還可以表示浮點數(shù)跳仿。
NSInteger a = 1;
NSMutableArray *arr = [[NSMutableArray alloc] init];
//[arr addObject:a]; // 程序奔潰嘴高,不能夠?qū)⒄翁砑拥綌?shù)組中
NSNumber *aNum = [NSNumber numberWithInt:a];
[arr addObject:aNum]; // 轉(zhuǎn)換為NSNumber后就OK了
NSNumber表示數(shù)字類,浮點娘摔,整形窄坦,長整形,無符號等凳寺,NSIntege只是NSNumber能表示的一種數(shù)字類而已鸭津。
13、Objective-C中@property的所有屬性詳解
1肠缨,assign :
簡單賦值逆趋,不更改索引計數(shù)
假設(shè)你用malloc分配了一塊內(nèi)存,并且把它的地址賦值給了指針a怜瞒,后來你希望指針b也共享這塊內(nèi)存父泳,于是你又把a賦值給(assign)了b。此時a 和b指向同一塊內(nèi)存吴汪,請問當a不再需要這塊內(nèi)存惠窄,能否直接釋放它?答案是否定的漾橙,因為a并不知道b是否還在使用這塊內(nèi)存杆融,如果a釋放了,那么b在使用這塊內(nèi)存的時候會引起程序crash掉
應(yīng)用場合:
對基礎(chǔ)數(shù)據(jù)類型 (例如NSInteger霜运,CGFloat)和C數(shù)據(jù)類型(int, float, double, char, 等)
適用簡單數(shù)據(jù)類型
2脾歇,retain:
與strong相對應(yīng)蒋腮,使用了引用計數(shù),retain+1,release -1;當引用 計數(shù)為0時藕各,dealloc會被調(diào)用池摧,內(nèi)存被釋放
3,copy:
用于非共享內(nèi)存時激况,每個指針有自己的內(nèi)存空間
4作彤,atomic//默認屬性
A,當一個變量聲明為atomic時乌逐,意味著在多線程中只能有一個線程能對它進行訪問
B竭讳,當一個變量聲明為atomic時,該變量為線程安全型浙踢,但是會影響訪問速度绢慢,
C,當一個變量聲明為atomic時洛波,在非ARC編譯環(huán)境下胰舆,需要設(shè)置訪問鎖來保證對該變量進行正確的get/set
5,nonatomic
A奋岁,? ? 當一個變量聲明為nonatomic時思瘟,意味著多個線程可以同時對其進行訪問
B,? ? 當一個變量聲明為nonatomic時闻伶,它是非線程安全型滨攻,訪問速度快;
C蓝翰,? ? 當一個變量聲明為nonatomic時光绕,當兩個不同的線程對其訪問時,容易失控畜份。
總結(jié):atomic和nonatomic用來決定編譯器生成的getter和setter是否為原子操作诞帐。在多線程環(huán)境下,原子操作是必要的爆雹,否則有可能引起錯誤的結(jié)果停蕉。加了atomic,setter函數(shù)會變成下面這樣:
if (property != newValue) {
[property release];
property = [newValue retain];
}
6.strong://ARC中默認屬性钙态,等于非ARC中的retain
與retain相對應(yīng)慧起,
應(yīng)用場景:
strong屬性用于ARC中
@property (strong,nonatomic) ViewController *viewController;
7,weak:
與assign 相對應(yīng),
應(yīng)用場景:
用于IBOutlets,如册倒,UIViewController的子類蚓挤,即一般的控件。
@property (weak, nonatomic) IBOutlet UIButton *myButton;
strong與weak的區(qū)別舉例:
前提:
我們把要用strong或者weak的對象比作一只風箏,風箏想掙脫線的束縛灿意,自由飛翔去估灿,如果此時有一根線,那么這只風箏就掙脫不了
過程分析
strong屬性的變量:
當我們把指向一只風箏的變量聲明為strong時缤剧,此時馅袁,你就擁有控制這只風箏的線,假如此時有五個人同時控制這只風箏(即這只風箏對象有三個strong類型的變量指向它)荒辕,那么只有一種情況司顿,這只風箏才會掙脫掉線的束縛:這三個人都放掉手中的線,(release掉)
weak屬性的變量:
當我們把指向一只風箏的變量聲明為weak時兄纺,此時,就像站在旁邊看風箏的觀眾們一樣化漆,當上面的三個人還握著手中的線時估脆,他們只能看到風箏,并不能控制它座云,他們能做的只能是用手指指向風箏疙赠,并大喊,“看朦拖,那只風箏飛得真高圃阳!”,然而璧帝,當上面的三個人把手中的線都放掉時捍岳,此時,風箏飛走了睬隶,看不見了锣夹,不管有再多的觀眾,他們再也看不到風箏了苏潜,這個故事告訴我們一個道理:當strong類型的指針被釋放掉之后银萍,所有的指向同一個對象的weak指針都會被清零。
8恤左,readonly
只有g(shù)et方法贴唇,沒有set方法
9,readwrite//默認屬性
有g(shù)et/set方法
10,unsafe_unretauined
用在ARC編譯環(huán)境下,在此環(huán)境下飞袋,與assign相似戳气。它只是告訴ARC如何正確地調(diào)用聲明為unsafe_unretauined變量的retain和release
14、線程安全
比如一個 ArrayList 類授嘀,在添加一個元素的時候物咳,它可能會有兩步來完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。
在單線程運行的情況下览闰,如果 Size = 0芯肤,添加一個元素后,此元素在位置 0压鉴,而且 Size=1崖咨;
而如果是在多線程情況下,比如有兩個線程油吭,線程 A 先將元素1存放在位置 0击蹲。但是此時 CPU 調(diào)度線程A暫停,線程 B 得到運行的機會婉宰。線程B向此 ArrayList 添加元素2歌豺,因為此時 Size 仍然等于 0 (注意,我們假設(shè)的是添加一個元素是要兩個步驟心包,而線程A僅僅完成了步驟1)类咧,所以線程B也將元素存放在位置0。然后線程A和線程B都繼續(xù)運行蟹腾,都增加 Size 的值痕惋,結(jié)果Size等于2。
那好娃殖,我們來看看 ArrayList 的情況值戳,期望的元素應(yīng)該有2個,而實際只有一個元素炉爆,造成丟失元素堕虹,而且Size 等于 2。這就是“線程不安全”了芬首。
如果你的代碼所在的進程中有多個線程在同時運行鲫凶,而這些線程可能會同時運行這段代碼。如果每次運行結(jié)果和單線程運行的結(jié)果是一樣的衩辟,而且其他的變量的值也和預(yù)期的是一樣的螟炫,就是線程安全的。
或者說:一個類或者程序所提供的接口對于線程來說是原子操作或者多個線程之間的切換不會導(dǎo)致該接口的執(zhí)行結(jié)果存在二義性,也就是說我們不用考慮同步的問題艺晴。
線程安全問題都是由全局變量及靜態(tài)變量引起的昼钻。
若每個線程中對全局變量、靜態(tài)變量只有讀操作封寞,而無寫操作然评,一般來說,這個全局變量是線程安全的狈究;若有多個線程同時執(zhí)行寫操作碗淌,一般都需要考慮線程同步(同步就是協(xié)同步調(diào),按預(yù)定的先后次序進行運行。如:你說完亿眠,我再說碎罚。),否則的話就可能影響線程安全纳像。
15荆烈、關(guān)于nil和 null和NSNull的區(qū)別及相關(guān)問題
nil -> Null-pointer to objective- c object
NIL -> Null-pointer to objective- c class
null-> null pointer to primitive type or absence of data.
1.nil
指向一個對象的指針為空
在Objective-C中用于id類型的對象
NSString *name = nil;
NSURL? ? *url? = nil;
id object? ? ? = nil;
2.Nil
指向一個類的指針為空
在Objective-C中用于Class類型的對象
Class aClass = Nil;
Clsss bClass = [NSURL class];
3.NULL
指向C類型的指針為空
多用于如下例子:
int ? *pInt ? ? = NULL;
char *chChar= NULL;
struct stStruct = NULL;
4.NSNull
在Objective-C中是一個類,只是名字中有個Null,NSNull有 + (NSNull *)null; 單例方法竟趾,多用于集合(NSArray,NSDictionary)中值為空的對象
NSArray *array = [NSArray arrayWithObjects:
[[NSObject alloc] init],
[NSNull null],
@"aaa",
nil,
[[NSObject alloc] init],
[[NSObject alloc] init], nil];
NSLog(@"%ld", array.count); // 輸出 3憔购,NSArray以nil結(jié)尾
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:
@"Object0", @"Key0",
@"Object1", @"Key1",
nil,? ? ? ? @"Key-nil"
@"Object2", @"Key2",
nil];
NSLog(@"%@", dictionary); // 輸出2個key-value,NSDictionary也是以nil結(jié)尾
NSMutableDictionary *mutableDictionary = [[NSMutableDictionary alloc] init];
[mutableDictionary setObject:nil forKey:@"Key-nil"]; // 會引起Crash
[mutableDictionary setObject:[NSNull null] forKey:@"Key-nil"]; // 不會引起Crash
所以在使用時,如下方法是比較安全的
[mutableDictionary setObject:(nil == value ? [NSNull null] : value)
forKey:@"Key"];
16岔帽、iOS開發(fā)網(wǎng)絡(luò)篇-HTTP協(xié)議
說明:apache tomcat服務(wù)器必須占用8080端口
一玫鸟、URL
1.基本介紹
URL的全稱是Uniform Resource Locator(統(tǒng)一資源定位符)
通過1個URL,能找到互聯(lián)網(wǎng)上唯一的1個資源
URL就是資源的地址犀勒、位置鞋邑,互聯(lián)網(wǎng)上的每個資源都有一個唯一的URL
2.URL中常見的協(xié)議
(1)HTTP
超文本傳輸協(xié)議,訪問的是遠程的網(wǎng)絡(luò)資源账蓉,格式是http://
http協(xié)議是在網(wǎng)絡(luò)開發(fā)中最常用的協(xié)議
(2)file
訪問的是本地計算機上的資源,格式是file://(不用加主機地址)
(3)mailto
訪問的是電子郵件地址逾一,格式是mailto:
(4)FTP
訪問的是共享主機的文件資源铸本,格式是ftp://
二、HTTP協(xié)議
1.HTTP協(xié)議簡介
不管是移動客戶端還是PC端遵堵,訪問遠程的網(wǎng)絡(luò)資源經(jīng)常使用HTTP協(xié)議
訪問百度主頁:http://www.baidu.com
獲得新浪的微博數(shù)據(jù)
獲得大眾點評的團購數(shù)據(jù)
2.HTTP協(xié)議的作用
HTTP的全稱是Hypertext Transfer Protocol箱玷,超文本傳輸協(xié)議
(1)規(guī)定客戶端和服務(wù)器之間的數(shù)據(jù)傳輸格式
(2)讓客戶端和服務(wù)器能有效地進行數(shù)據(jù)溝通
3.為什么選擇使用HTTP?
(1)簡單快速? 因為HTTP協(xié)議簡單陌宿,所以HTTP服務(wù)器的程序規(guī)模小锡足,因而通信速度很快
(2)靈活? HTTP允許傳輸任意類型的數(shù)據(jù)
(3)HTTP 0.9和1.0使用非持續(xù)連接? 限制每次連接只處理一個請求,服務(wù)器對客戶端的請求做出響應(yīng)后壳坪,馬上斷開連接舶得,這種方式可以節(jié)省傳輸時間
4.HTTP的通信過程
要想使用HTTP協(xié)議向服務(wù)器索取數(shù)據(jù),得先了解HTTP通信的完整過程
完整的http通信可以分為2大步驟
(1)請求:客戶端向服務(wù)器索要數(shù)據(jù)
(2)響應(yīng):服務(wù)器返回客戶端相應(yīng)的數(shù)據(jù)
三爽蝴、HTTP通信過程 - 請求和響應(yīng)
1.HTTP通信過程 - 請求
HTTP協(xié)議規(guī)定:1個完整的由客戶端發(fā)給服務(wù)器的HTTP請求中包含以下內(nèi)容
請求行:包含了請求方法沐批、請求資源路徑、HTTP協(xié)議版本
GET /MJServer/resources/images/1.jpg HTTP/1.1
請求頭:包含了對客戶端的環(huán)境描述蝎亚、客戶端請求的主機地址等信息
Host: 192.168.1.105:8080 // 客戶端想訪問的服務(wù)器主機地址
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9) Firefox/30.0// 客戶端的類型九孩,客戶端的軟件環(huán)境
Accept: text/html, */*// 客戶端所能接收的數(shù)據(jù)類型
Accept-Language: zh-cn // 客戶端的語言環(huán)境
Accept-Encoding: gzip // 客戶端支持的數(shù)據(jù)壓縮格式
請求體:客戶端發(fā)給服務(wù)器的具體數(shù)據(jù),比如文件數(shù)據(jù)
2.HTTP通信過程 - 響應(yīng)
客戶端向服務(wù)器發(fā)送請求发框,服務(wù)器應(yīng)當做出響應(yīng)躺彬,即返回數(shù)據(jù)給客戶端
HTTP協(xié)議規(guī)定:1個完整的HTTP響應(yīng)中包含以下內(nèi)容:
狀態(tài)行:包含了HTTP協(xié)議版本、狀態(tài)碼、狀態(tài)英文名稱
HTTP/1.1 200 OK
響應(yīng)頭:包含了對服務(wù)器的描述宪拥、對返回數(shù)據(jù)的描述
Server: Apache-Coyote/1.1 // 服務(wù)器的類型
Content-Type: image/jpeg // 返回數(shù)據(jù)的類型
Content-Length: 56811 // 返回數(shù)據(jù)的長度
Date: Mon, 23 Jun 2014 12:54:52 GMT // 響應(yīng)的時間
實體內(nèi)容:服務(wù)器返回給客戶端的具體數(shù)據(jù)仿野,比如文件數(shù)據(jù)
3.補充:推薦工具firebug-1.12.5-fx.xpi
蟲子的作用:攔截所有的http請求。
4.常見的響應(yīng)狀態(tài)碼
四江解、發(fā)送HTTP請求的方法
1.簡單說明
在HTTP/1.1協(xié)議中设预,定義了8種發(fā)送http請求的方法
GET、POST犁河、OPTIONS鳖枕、HEAD、PUT桨螺、DELETE宾符、TRACE、CONNECT灭翔、PATCH
根據(jù)HTTP協(xié)議的設(shè)計初衷魏烫,不同的方法對資源有不同的操作方式
PUT :增
DELETE :刪
POST:改
GET:查
提示:最常用的是GET和POST(實際上GET和POST都能辦到增刪改查)
2.get和post請求
要想使用GET和POST請求跟服務(wù)器進行交互,得先了解一個概念:參數(shù)就是傳遞給服務(wù)器的具體數(shù)據(jù)肝箱,比如登錄時的帳號哄褒、密碼。
GET和POST對比:GET和POST的主要區(qū)別表現(xiàn)在數(shù)據(jù)傳遞上煌张。
GET
在請求URL后面以?的形式跟上發(fā)給服務(wù)器的參數(shù)呐赡,多個參數(shù)之間用&隔開,比如http://ww.test.com/login?username=123&pwd=234&type=JSON
注意:由于瀏覽器和服務(wù)器對URL長度有限制骏融,因此在URL后面附帶的參數(shù)是有限制的链嘀,通常不能超過1KB
POST
發(fā)給服務(wù)器的參數(shù)全部放在請求體中
理論上,POST傳遞的數(shù)據(jù)量沒有限制(具體還得看服務(wù)器的處理能力)
3.GET和POST的選擇
選擇GET和POST的建議
(1)如果要傳遞大量數(shù)據(jù)档玻,比如文件上傳怀泊,只能用POST請求
(2)GET的安全性比POST要差些,如果包含機密\敏感信息误趴,建議用POST
(3)如果僅僅是索取數(shù)據(jù)(數(shù)據(jù)查詢)霹琼,建議使用GET
(4)如果是增加、修改凉当、刪除數(shù)據(jù)碧囊,建議使用POST
4.iOS中發(fā)送HTTP請求的方案
在iOS中,常見的發(fā)送HTTP請求(GET和POST)的解決方案有
(1)蘋果原生(自帶)
NSURLConnection:用法簡單纤怒,最古老最經(jīng)典最直接的一種方案
NSURLSession:iOS 7新出的技術(shù)糯而,功能比NSURLConnection更加強大
CFNetwork:NSURL*的底層,純C語言
(2)第三方框架
ASIHttpRequest:外號“HTTP終結(jié)者”泊窘,功能極其強大熄驼,可惜早已停止更新
AFNetworking:簡單易用像寒,提供了基本夠用的常用功能
建議:
為了提高開發(fā)效率,企業(yè)開發(fā)用的基本是第三方框架
5.ASI和AFN架構(gòu)對比
說明:AFN基于NSURL瓜贾,ASI基于CFHTTP诺祸,ASI的性能更好一些。
17祭芦、堆和棧
參考:http://my.oschina.net/openlab/blog/195068
18筷笨、計算緩存
- (long long)checkCache {
NSFileManager *fileManager=[NSFileManager defaultManager];
float folderSize;
if ([fileManager fileExistsAtPath:EBCACHE]) {
NSArray *childerFiles=[fileManager subpathsAtPath:EBCACHE];
for (NSString *fileName in childerFiles) {
NSString *absolutePath=[EBCACHE stringByAppendingPathComponent:fileName];
long long size=[fileManager attributesOfItemAtPath:absolutePath error:nil].fileSize;
folderSize += size;
}
folderSize+=[[EMSDImageCache sharedImageCache] getSize];
return folderSize;
}
return 0;
}
清除緩存:
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"緩存清除"message:@"確定清除緩存?"delegate:self cancelButtonTitle:@"取消"otherButtonTitles:@"確定",nil];
[alertView show];
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex ==1) {
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:EBCACHE error:nil];
}
}
備注:#define EBCACHE [NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask, YES) objectAtIndex:0]
19.各種xcode版本下載(官網(wǎng)):https://developer.apple.com/download/more/
20.設(shè)置狀態(tài)欄字體顏色分兩步:①,在appdelegate.m里設(shè)置
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];②龟劲,在plist文件里添加白名單:View controller-based status bar appearance胃夏,BOOL值為NO。
21.present到指定界面之后可以實現(xiàn)push的代碼:
LoginViewController?*login?=?[[LoginViewController?alloc]init];
UINavigationController?*nav?=?[[UINavigationController?alloc]initWithRootViewController:login];
然后再present昌跌,present到指定界面(此處為Login界面)之后仰禀,Login界面就可以push了
[self.navigationController?presentModalViewController:nav?animated:YES];
22.隱藏導(dǎo)航欄下面的黑線
ios 找出導(dǎo)航欄下面的黑線(可隱藏,改變樣式等)
根據(jù)UI的設(shè)計,navigationbar需要跟界面一體化,但是下面這根黑線是比較煩的問題,可能界面一需要隱藏,界面二就要出現(xiàn),也可能需要改變粗細之類的,又因為navigationbar會影響接下來的推棧,所以需要做一點小改動.
方法1:直接隱藏:
//在頁面出現(xiàn)的時候就將黑線隱藏起來
-(void)viewWillAppear:(BOOL)animated
{
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setShadowImage:[UIImage new]];
}
//在頁面消失的時候就讓navigationbar還原樣式
-(void)viewWillDisappear:(BOOL)animated{
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setShadowImage:nil];
}
這個方法唯一的不好就是會影響導(dǎo)航欄的translucent(透明)屬性
方法2:找出黑線,再做處理:
//通過一個方法來找到這個黑線(findHairlineImageViewUnder):
- (UIImageView *)findHairlineImageViewUnder:(UIView *)view {
if ([view isKindOfClass:UIImageView.class] && view.bounds.size.height <= 1.0) {
return (UIImageView *)view;
}
for (UIView *subview in view.subviews) {
UIImageView *imageView = [self findHairlineImageViewUnder:subview];
if (imageView) {
return imageView;
}
}
return nil;
}
//再定義一個imageview來等同于這個黑線
UIImageView *navBarHairlineImageView;
navBarHairlineImageView = [self findHairlineImageViewUnder:self.navigationController.navigationBar];
同樣的在界面出現(xiàn)時候開啟隱藏
-(void)viewWillAppear:(BOOL)animated
{
navBarHairlineImageView.hidden = YES;
}
//在頁面消失的時候就讓出現(xiàn)
-(void)viewWillDisappear:(BOOL)animated
{
navBarHairlineImageView.hidden = NO;
}
如果想要做一些更好的處理,比如說改變粗細,顏色之類的也在界面出現(xiàn)的時候?qū)懢托辛?
推薦使用第二種方法,因為整個項目都在使用導(dǎo)航欄推棧,出棧,很可能因為改變了樣式,導(dǎo)致后面的屬性混亂起來.
23.延時執(zhí)行方法:
[self performSelector:@selector(hiddenControlView) withObject:nil afterDelay:3];//延時3s執(zhí)行
[NSObject cancelPreviousPerformRequestsWithTarget:self];//取消延時執(zhí)行
24、監(jiān)聽屏幕是否旋轉(zhuǎn)
在viewdidload里面添加通知:[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarOrientationChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
//通知方法:
- (void)statusBarOrientationChange:(NSNotification *)notification
{
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationLandscapeRight) // home鍵靠右
{
}
if (orientation ==UIInterfaceOrientationLandscapeLeft) // home鍵靠左
{
}
if (orientation == UIInterfaceOrientationPortrait)
{
}
if (orientation == UIInterfaceOrientationPortraitUpsideDown)
{
}
}
25.
編碼:
- (NSString *)stringByAd
dingPercentE
scapesUsingEncoding:(NSStringEncoding)encoding
解碼:- (NSString *)stringByReplacingPercentEscapesUsingEncoding:(NSStringEncoding)encoding
26.調(diào)起打電話
NSMutableString * str=[[NSMutableString alloc] initWithFormat:@"telprompt://%@",@"xxxxx"];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:str]];
27.將圖片保存到相冊
UIImage *imgJPeg = [UIImage imageWithData:dJpeg];//建立UIIMage為jpeg格式
UIImageWriteToSavedPhotosAlbum(imgJpeg,nil,nil,nil);//保存到相冊
28.生成隨機數(shù)
Objective-C有個更方便的隨機數(shù)函數(shù)arc4random_uniform(x)蚕愤,可以用來產(chǎn)生0~(x-1)范圍內(nèi)的隨機數(shù)答恶,不需要再進行取模運算。如果要生成1~x的隨機數(shù)萍诱,可以這么寫:arc4random_uniform(x)+1悬嗓。
29.cocoapods使用教程(2017-01-17)(前提:已經(jīng)安裝cocoapods。簡單粗暴裕坊,以下所添加的第三方AFNetworking只是舉例包竹,具體按照自己需要添加)
30.label自適應(yīng)高度
#pragma mark? ------ Lable自適應(yīng)的方法1
-(CGRect)rectWidthAndHeightWithStr:(NSString *)str AndFont:(CGFloat)fontFloat
{
CGRect fcRect = [str boundingRectWithSize:CGSizeMake(600*WidthScale, 1000*HeightScale) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontFloat]} context:nil];
return fcRect;
}
#pragma mark? ------ Lable自適應(yīng)的方法2(更精確點)
- (CGRect)setupLabel:(UILabel *)textLabel withString:(NSString *)str andFont:(CGFloat)fontFloat {
//準備工作
textLabel.font = [UIFont systemFontOfSize:fontFloat];
textLabel.numberOfLines = 0;//根據(jù)最大行數(shù)需求來設(shè)置
textLabel.lineBreakMode = NSLineBreakByTruncatingTail;
CGSize maximumLabelSize = CGSizeMake(ScreenWidth-100, 9999);//labelsize的最大值
//關(guān)鍵語句
CGSize expectSize = [textLabel sizeThatFits:maximumLabelSize];
//別忘了把frame給回label,如果用xib加了約束的話可以只改一個約束的值
//? ? textLabel.frame = CGRectMake(20, 70, expectSize.width, expectSize.height);
CGRect rect = CGRectMake(20, 70, expectSize.width+20, expectSize.height);
return rect;
}
31.蘋果真機測試sdk文件路徑:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport
32.獲取當前app版本號
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
// app版本號
NSString *app_Version = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
33.推送消息的機制:
從上圖我們可以看到:
1碍庵、應(yīng)用程序注冊消息推送。
2悟狱、iOS從APNS Server獲取device token静浴,應(yīng)用程序接收device token。
3挤渐、應(yīng)用程序?qū)evice token發(fā)送給PUSH服務(wù)端程序苹享。
4、服務(wù)端程序向APNS服務(wù)發(fā)送消息浴麻。
5得问、APNS服務(wù)將消息發(fā)送給iPhone應(yīng)用程序。
34.打印工程中的方法名
NSLog(@"%s",__FUNCTION__);
35.自適應(yīng)一段文字(str)的高度
CGRect frame =[str boundingRectWithSize:CGSizeMake(SCREENW-70, MAXFLOAT) options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:FONTSIZE]} context:nil];
CGSize textSize =frame.size;
其中MAXFLOAT為0x1.fffffep+127f软免,float類型(float的最大值)
38.application:application openURL: sourceApplication: annotation: 方法不執(zhí)行
39.Archive的時候報錯:
我們的開發(fā)者賬號是企業(yè)開發(fā)賬號宫纬,剛開始打包的時候報了上面的警告,以為是證書有問題(畢竟菜鳥膏萧,不知道什么原因漓骚,只能根據(jù)他們描述的錯誤猜一猜)蝌衔,但是用同一臺電腦打包其他項目是可以的,所以排除證書問題蝌蹂;接著就可能是配置文件的問題噩斟,剛開始只配置了
但是這樣并不可以,后來把圖二和圖三也配置了之后再打包就可以了孤个;
40剃允、self.tableView.tableFooterView = [[UIView alloc]init];//防止沒內(nèi)容的空cell下劃線出現(xiàn)
41、手機內(nèi)APP相互跳轉(zhuǎn)
app1跳轉(zhuǎn)到app2:①首先在app2里的info里點擊URL Types齐鲤,然后添加一個URL Schemes斥废,URL Schemes的名字可以任意;②在app1的info.plist文件里LSApplicationQueriesSchemes
下添加一個string類型的item佳遂,名字為第一步給app2添加的那個URL Schemes的名字营袜;③在app1中需要跳轉(zhuǎn)的地方添加代碼:
NSString *requestUrlString = @"app2添加的那個URL Schemes的名字://";
NSURL *requestUrl = [NSURL URLWithString: requestUrlString];
if([[UIApplication sharedApplication] canOpenURL:requestUrl]) {
[[UIApplication sharedApplication] openURL:requestUrl];
}