iOS開發(fā)技術(shù)點(diǎn)總結(jié)(一)

1、在UIScorllView上添加UISlide,拖動slide的時(shí)候,scrollerview會跟著動,解決方案

在項(xiàng)目開發(fā)時(shí)遇到一個問題,我在UIViewController上面直接創(chuàng)建了一個UIScrollerView,把UIScrollerView作為一個子視圖添加到了UIViewController,

又再UIScrollerView中添加了一個UISlider的組件,在手勢滑動的過程中,很難滑動到UISlider這個控件,經(jīng)常是滑動的時(shí)候UIScrollerView進(jìn)行了滾動,

而UISlider這個控件沒有滑動,讓人很抓狂。

上網(wǎng)具體去了解了一下UIScrollerView的詳解,終于徹底明白了問題出在哪里

下面引用一下前輩的總結(jié),因?yàn)樽约河X得沒有他總結(jié)的詳細(xì)

UIScrollView重載了hitTest方法,當(dāng)手指touch的時(shí)候,UIScrollView會攔截所有event,然后等待150ms,在這段時(shí)間內(nèi),如果沒有手指沒有移動,當(dāng)時(shí)間結(jié)束時(shí),UIScrollView會發(fā)送tracking event到子視圖上,并且自身不滑動。在時(shí)間結(jié)束前,手指發(fā)生了移動,那么UIScrollView就會進(jìn)行滑動,從而取消發(fā)送tracking。

看來是UIScrollView的問題。直接拖動UISlider,此時(shí)touch時(shí)間在150ms以內(nèi),UIScrollView會認(rèn)為是拖動自己,從而攔截了event,導(dǎo)致UISlider接受不到滑動的event。但是只要按住UISlider一會再拖動,此時(shí)此時(shí)touch時(shí)間超過150ms,因此滑動的event會發(fā)送到UISlider上。

期間試過幾種方法,只有一種可行,就是重寫UIScrollView的hitTest方法:當(dāng)滑動UISlider時(shí),使UIScrollView不可滑動。

但是又出現(xiàn)了一個問題,我的UIScrollerView是直接繼承了UIScrollerView,在UIViewController中是無法重寫的UIScrollerView的hitTest方法的,所以需要重新創(chuàng)建一個view,繼承UIScrollerView,然后再重寫上述方法,然后再導(dǎo)入U(xiǎn)IViewController中就可以輕松實(shí)現(xiàn)了。

2、IOS 截屏模糊 的問題

情景: 遇到的分享的圖片 很模糊。

那么首先去搜索下 在你的代碼里面有沒有遇到

用 UIGraphicsBeginImageContext(<#CGSize size#>) 這個方法。

解決:

如果有那么 截屏的圖片肯定是模糊的,因?yàn)樵趇OS7 的分辨率會改為另外一種代替的方法

就是它 :

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ù),是否確認(rèn)刪除" 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ò)請求的時(shí)候給服務(wù)器發(fā)送的包頭信息(包括你當(dāng)前使用什么設(shè)備請求的、當(dāng)前設(shè)備信息等等)

請求正文:上面例子網(wǎng)址的問號之后的都是請求正文

GET:請求一些簡單的數(shù)據(jù),一般都是明文顯示,攜帶數(shù)據(jù)量小

POST:處理復(fù)雜的業(yè)務(wù),比如上傳圖片,加密參數(shù)等;與GET不同地方,1,并不是明文請求,請求正文被加載到了數(shù)據(jù)當(dāng)中,從瀏覽器里很少能看到post請求所攜帶的參數(shù);2,可以攜帶更多的參數(shù)

斷點(diǎn)下載:1,斷點(diǎn)下載需要服務(wù)器支持; 2,在執(zhí)行請求時(shí),我們需要設(shè)定Request fields上的Range參數(shù)才能生效

5、原生APP——優(yōu)缺點(diǎn)

優(yōu)點(diǎn):1、運(yùn)行效率高2、可調(diào)用各種設(shè)備資源

缺點(diǎn):1、人力成本高2、發(fā)布速度慢3、更新版本的問題(用戶就是不更新)4、實(shí)現(xiàn)圖文混排功能有各種坑(很麻煩)

6、WEBAPP核心思路

HTML5 css3 js? 開發(fā)完了之后打包(用phoneGap等打包)

7、代理

委托方:1.聲明協(xié)議2.聲明代理3.定義代理方法

.h文件里:

.m文件里:

代理方:1、遵守協(xié)議2.把自己設(shè)為代理3.實(shí)現(xiàn)代理方法

遵守協(xié)議sendDataAttributes;

把自己設(shè)為代理DataNameListController *dataName = [[DataNameListController alloc]init];

dataName.sendDataAttributesDelegate = self;

實(shí)現(xiàn)代理方法

-(void)sendDataAttributes:(NSArray *)array{}

8、懶加載及self.和下劃線區(qū)別

a.懶加載:?被聲明為屬性的成員,在ios5之前需要使用編譯器指令@synthesize告訴編譯器幫助生成屬性的getter,setter方法。之后會默認(rèn)生成。編譯器在生成getter,setter方法時(shí)先檢查有沒有自定義getter,setter方法,如果有則使用自定義的,沒有才生成。

懶加載就是重寫屬性的getter方法,然后加一個判斷,為空則賦值,不為空則返回。代碼如下:

沒有懶加載的情況下,如果想給一個數(shù)組_dataSource賦值,需要在viewDidload里面寫類似于

_dataSource = @[@"123",@"qe",@"123",@"ad",@"123",@"adasda"];

這就出現(xiàn)了一個問題,當(dāng)然也不稱得上問題,只是代碼需要優(yōu)化而已,因?yàn)楫?dāng)_dataSource需不需要的時(shí)候你都要給_dataSource初始化并賦值。這就占用了沒必要的內(nèi)存。如果你只想在用到_dataSource的時(shí)候才給它初始化并賦值的時(shí)候,這時(shí)你就用到了懶加載。

示例代碼:

- (void)viewDidLoad {

???? [super viewDidLoad];

}

-(NSArray *)dataSource{

?? if(!_dataSource){

????? _dataSource = @[@"123",@"qe",@"123",@"ad",@"123",@"adasda"];

?? }

??? return _dataSource;

}

當(dāng)需要用到_dataSource的時(shí)候,就會調(diào)用[self dataSource]的方法(即getter方法)。注意:需要注意在getter方法里切勿使用self.dataSource,因?yàn)閟elf.dataSource會調(diào)用getter方法,造成死循環(huán)。

總結(jié):懶加載即用到時(shí)方去加載對象。

b.self.mtest和_mtest的區(qū)別

?在第一次使用時(shí)由于沒注意到兩者的區(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屬性

當(dāng)數(shù)據(jù)類型為int、float等原生類型時(shí),可以使用assign,否則可能導(dǎo)致內(nèi)存泄露。例如當(dāng)使用malloc分配了一塊內(nèi)存,并把它的地址賦值給了指針a,后來如果希望指針b也共享這塊內(nèi)存,于是講a賦值給(assgin)b。這時(shí)就用到了assgin,此時(shí)a和b指向同一塊內(nèi)存。但是現(xiàn)在問題出現(xiàn)了,當(dāng)a不再需要這塊內(nèi)存時(shí),能都直接釋放呢?肯定是不能的,因?yàn)閍并不知道b是否還在使用這塊內(nèi)存,如果a釋放了,那么b在使用這塊內(nèi)存的時(shí)候引起程序crash掉。

二、retain屬性

retain屬性就是為了解決上述問題而提出的,使用了引用計(jì)數(shù)(reference counting),還是上面那個例子,我們給那塊內(nèi)存設(shè)一個引用計(jì)數(shù),當(dāng)內(nèi)存唄分配并且賦值給a時(shí),引用計(jì)數(shù)是1.當(dāng)把a(bǔ)賦值給b時(shí)引用計(jì)數(shù)增加到2.這時(shí)如果a不再使用這塊內(nèi)存,它只需要把引用計(jì)數(shù)減1,表明自己不再擁有這塊內(nèi)存。b不再使用這塊內(nèi)存時(shí)也把引用計(jì)數(shù)減1.當(dāng)引用計(jì)數(shù)變?yōu)?的時(shí)候,代表該內(nèi)存不再被任何指針?biāo)茫到y(tǒng)可以直接釋放掉。此時(shí)系統(tǒng)自動調(diào)用dealloc函數(shù),內(nèi)存被回收。(自己想了個??:你在小區(qū)有一個車位,平時(shí)你把自己的車停那,你弟弟這時(shí)候也想用你的車位,于是你就retain了一下,把這個車位使用人數(shù)名字上又增加了一位(引用計(jì)數(shù)加一),然后你弟和你都可以共用這一個車位。當(dāng)你或者你弟弟其中一個人不想用的時(shí)候(引用計(jì)數(shù)減一),不想用的那個人能直接把車位上交給小區(qū)管理人員嗎(內(nèi)存釋放)?不可以!因?yàn)槟悴挥昧耍硗庖粋€還在用,所以還不能把車位上交給小區(qū)管理人員,當(dāng)你倆都不想用了的話就可以把車位上交給物業(yè)了)

三、copy屬性

copy是你不希望a和b共享一塊內(nèi)存時(shí)會使用到。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];

此時(shí)newStr和str完全相同,地址都是0XAAAA ,內(nèi)容為0X1111 ,即newStr只是str的別名,對任何一個操作就等于對另一個操作因此retainCount不需要增加.

2.retain的情況:NSString * newStr = [str retain];

此時(shí)newStr的地址不再為0XAAAA,可能為0XAABB,但是內(nèi)容依然為0X1111.因此newStr和str都可以管理'abc'所在的內(nèi)存。因此 retainCount需要增加1.

3.copy的情況:NSString * newStr = [str copy];

此時(shí)會在堆上重新開辟一段內(nèi)存存放@‘a(chǎn)bc',比如0X1122,內(nèi)容為@'abc,同時(shí)會在棧上為newStr分配空間,比如地址:0XAACC,內(nèi)容為0X1122,因此retainCount增加1供newStr來管理0X1122這段內(nèi)存.

NSString為何要用copy?而不是strong?

strong和retain同義, weak和assign同義, 為什么要采用這種說法, 似乎是ARC出現(xiàn)后為了消除引用計(jì)數(shù)的觀念而采用的做法. 至于為什么要用copy, 由于純NSString是只讀的, 所以strong和copy的結(jié)果一樣,據(jù)stackOverflow上的說法,是為了防止mutable string被無意中修改, NSMutableString是NSString的子類, 因此NSString指針可以持有NSMutableString對象.

很簡單,假如有一個NSMutableString,現(xiàn)在用他給一個retain修飾 NSString賦值,那么只是將NSString指向了NSMutableString所指向的位置,并對NSMUtbaleString計(jì)數(shù)器加一,此時(shí),如果對NSMutableString進(jìn)行修改,也會導(dǎo)致NSString的值修改,原則上這是不允許的. 如果是copy修飾的NSString對象,在用NSMutableString給他賦值時(shí),會進(jìn)行深拷貝,及把內(nèi)容也給拷貝了一份,兩者指向不同的位置,即使改變了NSMutableString的值,NSString的值也不會改變.

所以用copy是為了安全,防止NSMutableString賦值給NSString時(shí),前者修改引起后者值變化而用的.

10、view的frame和bounds的區(qū)別

參考這個哥們寫的:http://blog.csdn.net/mad1989/article/details/8711697

11、int 和NSInteger的區(qū)別

原來在蘋果的api實(shí)現(xiàn)中,NSInteger是一個封裝,它會識別當(dāng)前操作系統(tǒng)的位數(shù),自動返回最大的類型。

當(dāng)需要使用int類型的變量的時(shí)候,可以像寫C的程序一樣,用int,也可以用NSInteger,但更推薦使用NSInteger,因?yàn)檫@樣就不用考慮設(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ù),還可以表示浮點(diǎn)數(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ù)字類,浮點(diǎn),整形,長整形,無符號等,NSIntege只是NSNumber能表示的一種數(shù)字類而已。

13、Objective-C中@property的所有屬性詳解

1,assign :

簡單賦值,不更改索引計(jì)數(shù)

假設(shè)你用malloc分配了一塊內(nèi)存,并且把它的地址賦值給了指針a,后來你希望指針b也共享這塊內(nèi)存,于是你又把a(bǔ)賦值給(assign)了b。此時(shí)a 和b指向同一塊內(nèi)存,請問當(dāng)a不再需要這塊內(nèi)存,能否直接釋放它?答案是否定的,因?yàn)閍并不知道b是否還在使用這塊內(nèi)存,如果a釋放了,那么b在使用這塊內(nèi)存的時(shí)候會引起程序crash掉

應(yīng)用場合:

對基礎(chǔ)數(shù)據(jù)類型 (例如NSInteger,CGFloat)和C數(shù)據(jù)類型(int, float, double, char, 等)

適用簡單數(shù)據(jù)類型

2,retain:

與strong相對應(yīng),使用了引用計(jì)數(shù),retain+1,release -1;當(dāng)引用 計(jì)數(shù)為0時(shí),dealloc會被調(diào)用,內(nèi)存被釋放

3,copy:

用于非共享內(nèi)存時(shí),每個指針有自己的內(nèi)存空間

4,atomic//默認(rèn)屬性

A,當(dāng)一個變量聲明為atomic時(shí),意味著在多線程中只能有一個線程能對它進(jìn)行訪問

B,當(dāng)一個變量聲明為atomic時(shí),該變量為線程安全型,但是會影響訪問速度,

C,當(dāng)一個變量聲明為atomic時(shí),在非ARC編譯環(huán)境下,需要設(shè)置訪問鎖來保證對該變量進(jìn)行正確的get/set

5,nonatomic

A,? ? 當(dāng)一個變量聲明為nonatomic時(shí),意味著多個線程可以同時(shí)對其進(jìn)行訪問

B,? ? 當(dāng)一個變量聲明為nonatomic時(shí),它是非線程安全型,訪問速度快;

C,? ? 當(dāng)一個變量聲明為nonatomic時(shí),當(dāng)兩個不同的線程對其訪問時(shí),容易失控。

總結(jié):atomic和nonatomic用來決定編譯器生成的getter和setter是否為原子操作。在多線程環(huán)境下,原子操作是必要的,否則有可能引起錯誤的結(jié)果。加了atomic,setter函數(shù)會變成下面這樣:

if (property != newValue) {

[property release];

property = [newValue retain];

}

6.strong://ARC中默認(rèn)屬性,等于非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的對象比作一只風(fēng)箏,風(fēng)箏想掙脫線的束縛,自由飛翔去,如果此時(shí)有一根線,那么這只風(fēng)箏就掙脫不了

過程分析

strong屬性的變量:

當(dāng)我們把指向一只風(fēng)箏的變量聲明為strong時(shí),此時(shí),你就擁有控制這只風(fēng)箏的線,假如此時(shí)有五個人同時(shí)控制這只風(fēng)箏(即這只風(fēng)箏對象有三個strong類型的變量指向它),那么只有一種情況,這只風(fēng)箏才會掙脫掉線的束縛:這三個人都放掉手中的線,(release掉)

weak屬性的變量:

當(dāng)我們把指向一只風(fēng)箏的變量聲明為weak時(shí),此時(shí),就像站在旁邊看風(fēng)箏的觀眾們一樣,當(dāng)上面的三個人還握著手中的線時(shí),他們只能看到風(fēng)箏,并不能控制它,他們能做的只能是用手指指向風(fēng)箏,并大喊,“看,那只風(fēng)箏飛得真高!”,然而,當(dāng)上面的三個人把手中的線都放掉時(shí),此時(shí),風(fēng)箏飛走了,看不見了,不管有再多的觀眾,他們再也看不到風(fēng)箏了,這個故事告訴我們一個道理:當(dāng)strong類型的指針被釋放掉之后,所有的指向同一個對象的weak指針都會被清零。

8,readonly

只有g(shù)et方法,沒有set方法

9,readwrite//默認(rèn)屬性

有g(shù)et/set方法

10,unsafe_unretauined

用在ARC編譯環(huán)境下,在此環(huán)境下,與assign相似。它只是告訴ARC如何正確地調(diào)用聲明為unsafe_unretauined變量的retain和release

14、線程安全

比如一個 ArrayList 類,在添加一個元素的時(shí)候,它可能會有兩步來完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。

在單線程運(yùn)行的情況下,如果 Size = 0,添加一個元素后,此元素在位置 0,而且 Size=1;

而如果是在多線程情況下,比如有兩個線程,線程 A 先將元素1存放在位置 0。但是此時(shí) CPU 調(diào)度線程A暫停,線程 B 得到運(yùn)行的機(jī)會。線程B向此 ArrayList 添加元素2,因?yàn)榇藭r(shí) Size 仍然等于 0 (注意,我們假設(shè)的是添加一個元素是要兩個步驟,而線程A僅僅完成了步驟1),所以線程B也將元素存放在位置0。然后線程A和線程B都繼續(xù)運(yùn)行,都增加 Size 的值,結(jié)果Size等于2。

那好,我們來看看 ArrayList 的情況,期望的元素應(yīng)該有2個,而實(shí)際只有一個元素,造成丟失元素,而且Size 等于 2。這就是“線程不安全”了。

如果你的代碼所在的進(jìn)程中有多個線程在同時(shí)運(yùn)行,而這些線程可能會同時(shí)運(yùn)行這段代碼。如果每次運(yùn)行結(jié)果和單線程運(yùn)行的結(jié)果是一樣的,而且其他的變量的值也和預(yù)期的是一樣的,就是線程安全的。

或者說:一個類或者程序所提供的接口對于線程來說是原子操作或者多個線程之間的切換不會導(dǎo)致該接口的執(zhí)行結(jié)果存在二義性,也就是說我們不用考慮同步的問題。

線程安全問題都是由全局變量及靜態(tài)變量引起的。

若每個線程中對全局變量、靜態(tài)變量只有讀操作,而無寫操作,一般來說,這個全局變量是線程安全的;若有多個線程同時(shí)執(zhí)行寫操作,一般都需要考慮線程同步(同步就是協(xié)同步調(diào),按預(yù)定的先后次序進(jìn)行運(yùn)行。如:你說完,我再說。),否則的話就可能影響線程安全。

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

所以在使用時(shí),如下方法是比較安全的

[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é)議,訪問的是遠(yuǎn)程的網(wǎng)絡(luò)資源,格式是http://

http協(xié)議是在網(wǎng)絡(luò)開發(fā)中最常用的協(xié)議

(2)file

訪問的是本地計(jì)算機(jī)上的資源,格式是file://(不用加主機(jī)地址)

(3)mailto

訪問的是電子郵件地址,格式是mailto:

(4)FTP

訪問的是共享主機(jī)的文件資源,格式是ftp://

二、HTTP協(xié)議

1.HTTP協(xié)議簡介

不管是移動客戶端還是PC端,訪問遠(yuǎn)程的網(wǎng)絡(luò)資源經(jīng)常使用HTTP協(xié)議

訪問百度主頁:http://www.baidu.com

獲得新浪的微博數(shù)據(jù)

獲得大眾點(diǎn)評的團(tuán)購數(shù)據(jù)

2.HTTP協(xié)議的作用

HTTP的全稱是Hypertext Transfer Protocol,超文本傳輸協(xié)議

(1)規(guī)定客戶端和服務(wù)器之間的數(shù)據(jù)傳輸格式

(2)讓客戶端和服務(wù)器能有效地進(jìn)行數(shù)據(jù)溝通

3.為什么選擇使用HTTP?

(1)簡單快速? 因?yàn)镠TTP協(xié)議簡單,所以HTTP服務(wù)器的程序規(guī)模小,因而通信速度很快

(2)靈活? HTTP允許傳輸任意類型的數(shù)據(jù)

(3)HTTP 0.9和1.0使用非持續(xù)連接? 限制每次連接只處理一個請求,服務(wù)器對客戶端的請求做出響應(yīng)后,馬上斷開連接,這種方式可以節(jié)省傳輸時(shí)間

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)境描述、客戶端請求的主機(jī)地址等信息

Host: 192.168.1.105:8080 // 客戶端想訪問的服務(wù)器主機(jī)地址

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)當(dāng)做出響應(yīng),即返回?cái)?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ù)器的描述、對返回?cái)?shù)據(jù)的描述

Server: Apache-Coyote/1.1 // 服務(wù)器的類型

Content-Type: image/jpeg // 返回?cái)?shù)據(jù)的類型

Content-Length: 56811 // 返回?cái)?shù)據(jù)的長度

Date: Mon, 23 Jun 2014 12:54:52 GMT // 響應(yīng)的時(shí)間

實(shí)體內(nèi)容:服務(wù)器返回給客戶端的具體數(shù)據(jù),比如文件數(shù)據(jù)

3.補(bǔ)充:推薦工具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è)計(jì)初衷,不同的方法對資源有不同的操作方式

PUT :增

DELETE :刪

POST:改

GET:查

提示:最常用的是GET和POST(實(shí)際上GET和POST都能辦到增刪改查)

2.get和post請求

要想使用GET和POST請求跟服務(wù)器進(jìn)行交互,得先了解一個概念:參數(shù)就是傳遞給服務(wù)器的具體數(shù)據(jù),比如登錄時(shí)的帳號、密碼。

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要差些,如果包含機(jī)密\敏感信息,建議用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更加強(qiáng)大

CFNetwork:NSURL*的底層,純C語言

(2)第三方框架

ASIHttpRequest:外號“HTTP終結(jié)者”,功能極其強(qiáng)大,可惜早已停止更新

AFNetworking:簡單易用,提供了基本夠用的常用功能

建議:

為了提高開發(fā)效率,企業(yè)開發(fā)用的基本是第三方框架

5.ASI和AFN架構(gòu)對比

說明:AFN基于NSURL,ASI基于CFHTTP,ASI的性能更好一些。

17、堆和棧

參考:http://my.oschina.net/openlab/blog/195068

18、計(jì)算緩存

- (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到指定界面之后可以實(shí)現(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è)計(jì),navigationbar需要跟界面一體化,但是下面這根黑線是比較煩的問題,可能界面一需要隱藏,界面二就要出現(xiàn),也可能需要改變粗細(xì)之類的,又因?yàn)閚avigationbar會影響接下來的推棧,所以需要做一點(diǎn)小改動.

方法1:直接隱藏:

//在頁面出現(xiàn)的時(shí)候就將黑線隱藏起來

-(void)viewWillAppear:(BOOL)animated

{

[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];

[self.navigationController.navigationBar setShadowImage:[UIImage new]];

}

//在頁面消失的時(shí)候就讓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)時(shí)候開啟隱藏

-(void)viewWillAppear:(BOOL)animated

{

navBarHairlineImageView.hidden = YES;

}

//在頁面消失的時(shí)候就讓出現(xiàn)

-(void)viewWillDisappear:(BOOL)animated

{

navBarHairlineImageView.hidden = NO;

}

如果想要做一些更好的處理,比如說改變粗細(xì),顏色之類的也在界面出現(xiàn)的時(shí)候?qū)懢托辛?

推薦使用第二種方法,因?yàn)檎麄€項(xiàng)目都在使用導(dǎo)航欄推棧,出棧,很可能因?yàn)楦淖兞藰邮?導(dǎo)致后面的屬性混亂起來.

23.延時(shí)執(zhí)行方法:

[self performSelector:@selector(hiddenControlView) withObject:nil afterDelay:3];//延時(shí)3s執(zhí)行

[NSObject cancelPreviousPerformRequestsWithTarget:self];//取消延時(shí)執(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.生成隨機(jī)數(shù)

Objective-C有個更方便的隨機(jī)數(shù)函數(shù)arc4random_uniform(x),可以用來產(chǎn)生0~(x-1)范圍內(nèi)的隨機(jī)數(shù),不需要再進(jìn)行取模運(yùn)算。如果要生成1~x的隨機(jī)數(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(更精確點(diǎn))

- (CGRect)setupLabel:(UILabel *)textLabel withString:(NSString *)str andFont:(CGFloat)fontFloat {

//準(zhǔn)備工作

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.蘋果真機(jī)測試sdk文件路徑:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport

32.獲取當(dāng)前app版本號

NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];

// app版本號

NSString *app_Version = [infoDictionary objectForKey:@"CFBundleShortVersionString"];

33.推送消息的機(jī)制:


從上圖我們可以看到:

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的最大值)

36.數(shù)據(jù)持久化存儲的幾個方法

37.ios內(nèi)存管理機(jī)制

38.application:application openURL: sourceApplication: annotation: 方法不執(zhí)行

39.Archive的時(shí)候報(bào)錯:

Archive報(bào)錯圖片

我們的開發(fā)者賬號是企業(yè)開發(fā)賬號,剛開始打包的時(shí)候報(bào)了上面的警告,以為是證書有問題(畢竟菜鳥,不知道什么原因,只能根據(jù)他們描述的錯誤猜一猜),但是用同一臺電腦打包其他項(xiàng)目是可以的,所以排除證書問題;接著就可能是配置文件的問題,剛開始只配置了

圖一

但是這樣并不可以,后來把圖二和圖三也配置了之后再打包就可以了;

圖二


圖三

40、self.tableView.tableFooterView = [[UIView alloc]init];//防止沒內(nèi)容的空cell下劃線出現(xiàn)

41、手機(jī)內(nèi)APP相互跳轉(zhuǎn)

app1跳轉(zhuǎn)到app2:①首先在app2里的info里點(diǎn)擊URL Types,然后添加一個URL Schemes,URL Schemes的名字可以任意;②在app1的info.plist文件里L(fēng)SApplicationQueriesSchemes
下添加一個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];

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,211評論 30 472
  • 史上最全的iOS面試題及答案 iOS面試小貼士———————————————回答好下面的足夠了----------...
    Style_偉閱讀 2,434評論 0 35
  • iOS面試小貼士 ———————————————回答好下面的足夠了------------------------...
    不言不愛閱讀 2,013評論 0 7
  • 多線程、特別是NSOperation 和 GCD 的內(nèi)部原理。運(yùn)行時(shí)機(jī)制的原理和運(yùn)用場景。SDWebImage的原...
    LZM輪回閱讀 2,039評論 0 12
  • __block和__weak修飾符的區(qū)別其實(shí)是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用,...
    LZM輪回閱讀 3,364評論 0 6