IOS開發(fā)和Web開發(fā)一樣,網(wǎng)絡(luò)請(qǐng)求方式包括Get和Post方式。Get和Post兩者有和特點(diǎn)和區(qū)別,在本篇博客中不做過(guò)多的論述,本篇的重點(diǎn)在于如何GET數(shù)據(jù)和POST數(shù)據(jù)。下面還會(huì)提到如何在我們的項(xiàng)目中使用CocoaPods, CocoaPods的安裝和使用教程請(qǐng)參考鏈接http://code4app.com/article/cocoapods-install-usage。上面詳細(xì)的介紹了CocoaPods的安裝過(guò)程和如何通過(guò)CocoaPods引入第三方類庫(kù)。在本篇博客中提到CocoaPods,是因?yàn)槲覀冃枰肅ocoaPods來(lái)引入AFNetWorking,然后在網(wǎng)絡(luò)請(qǐng)求中使用AFNetWorking來(lái)實(shí)現(xiàn)我們圖片的提交。
下面用的API是由新浪微博提供的官方API,鏈接地址:http://open.weibo.com/wiki/微博API, 想使用新浪微博的API首先得注冊(cè)成開發(fā)者獲取一個(gè)和自己新浪微博綁定的access_token,我們可以通過(guò)這個(gè)令牌來(lái)使用新浪微博提供的API.
1.Get方式的請(qǐng)求
(1)下面會(huì)使用公共服務(wù)的國(guó)家,省份,和城市的接口,來(lái)學(xué)習(xí)一下GET請(qǐng)求方式

(2)我們要完成什么要的任務(wù)呢?少說(shuō)點(diǎn)吧,上幾張圖最為直接

(3)上面的數(shù)據(jù)是通過(guò)API獲取的,獲取完后再顯示在我們的tableView中,將會(huì)提供一些關(guān)鍵的實(shí)現(xiàn)代碼,準(zhǔn)備工作是新建三個(gè)TabelViewController然后配置相應(yīng)的cell。下面就以第一個(gè)TableView為例,因?yàn)楹髢蓚€(gè)和第一個(gè)差不多,所以就不做贅述,下面是網(wǎng)路請(qǐng)求的關(guān)鍵代碼:
1 //網(wǎng)絡(luò)請(qǐng)求用的API 2 NSString *urlString = @"https://api.weibo.com/2/common/get_country.json?access_token=你自己的access_token"; 3 4 //把urlString轉(zhuǎn)換成url 5 NSURL *url = [NSURL URLWithString:urlString]; 6 7 //創(chuàng)建URL請(qǐng)求 8 NSURLRequest *request = [NSURLRequest requestWithURL:url]; 9 10 //copy_self在Block中使用,避免強(qiáng)引用循環(huán)11 __weak __block ChinaTableViewController *copy_self = self;12 13 //執(zhí)行請(qǐng)求14 [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {15 16 //連接失敗時(shí)17 if (connectionError) {18 NSLog(@"%@", [connectionError localizedDescription]);19 return ;20 }21 22 23 NSError *error = nil;24 //把json轉(zhuǎn)換成數(shù)組25 copy_self.dataSource = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];26 27 //轉(zhuǎn)換失敗28 if (error) {29 NSLog(@"%@", [error localizedDescription]);30 return;31 }32 33 //tableView的重載34 [copy_self.tableView reloadData];35 36 }];
代碼說(shuō)明:
1.創(chuàng)建要請(qǐng)求的API,根據(jù)你要獲取的數(shù)據(jù)參考API來(lái)拼接你要的URL.
2.根據(jù)拼接的URL來(lái)創(chuàng)建URL請(qǐng)求對(duì)象;
3.發(fā)送請(qǐng)求,上面用的是異步請(qǐng)求方式,同步請(qǐng)求會(huì)阻塞線程。
4.在block回調(diào)中把返回的JSON解析成數(shù)組并加載到我們的表示圖
(4).把數(shù)據(jù)顯示在表視圖上
1 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 2 { 3 return 1; 4 } 5 6 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 7 { 8 return self.dataSource.count; 9 }10 11 12 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath13 {14 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];15 16 NSString *key = [NSString stringWithFormat:@"%03d",indexPath.row+1];17 cell.textLabel.text = self.dataSource[indexPath.row][key];18 19 20 return cell;21 }
(5)因?yàn)樵谙乱粋€(gè)頁(yè)面要請(qǐng)求數(shù)據(jù)的時(shí)候得用到第一個(gè)頁(yè)面的數(shù)據(jù),也就是在請(qǐng)求省份的時(shí)候得知道國(guó)家的編碼,所以要把國(guó)家的編碼傳到第二個(gè)頁(yè)面中,第三個(gè)頁(yè)面和第二個(gè)頁(yè)面也是類似。下面是通過(guò)KVC傳值的代碼
1 // In a storyboard-based application, you will often want to do a little PReparation before navigation 2 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 3 { 4 5 UITableViewCell *cell = sender; 6 7 //獲取點(diǎn)擊Cell的索引 8 NSIndexPath * indexPath = [self.tableView indexPathForCell:cell]; 9 10 //獲取請(qǐng)求的數(shù)據(jù)11 NSDictionary *dic = self.dataSource[indexPath.row];12 13 id vc = [segue destinationViewController];14 [vc setValue:dic forKey:@"country"];15 16 }
后兩個(gè)顯示頁(yè)面和上面的代碼相似,在這就不做贅述,Get數(shù)據(jù)的關(guān)鍵是讀懂API,通過(guò)API獲取你想要的數(shù)據(jù)
2.POST請(qǐng)求方式
我們下面通過(guò)調(diào)用新浪微博發(fā)微博的API來(lái)了解一下通過(guò)POST提交表單中的數(shù)據(jù),在用第三方的類庫(kù)AFNetWorking來(lái)提交圖片,至于發(fā)微博的API如何使用請(qǐng)參照新浪官方的API開發(fā)文檔。
(1)通過(guò)POST提交純表單數(shù)據(jù)
a.用POST方式提交,不需要往URL中拼接參數(shù),首先我們要獲取url(API中提供的發(fā)布微博的URL,下面用的宏定義的URL)
//獲取url NSURL *url = [NSURL URLWithString:SendMessage];
b.通過(guò)URL創(chuàng)建一個(gè)可變的請(qǐng)求:
//創(chuàng)建POST請(qǐng)求 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
c.把請(qǐng)求方式設(shè)置成POST
//設(shè)置POST請(qǐng)求 [request setHTTPMethod:@"POST"];
d.拼接要提交的參數(shù)
//拼接要POST提交的字符串 NSString *string = [NSString stringWithFormat:@"access_token=%@&status=%@", access_token, self.blogTextField.text];
      e.在網(wǎng)絡(luò)傳輸中我們使用的時(shí)二進(jìn)制所以要轉(zhuǎn)換成NSData類型
//把string轉(zhuǎn)變成NSData類型 NSData *bodyData = [string dataUsingEncoding:NSUTF8StringEncoding];
f.把參數(shù)添加到請(qǐng)求中
//把bodyData添加到request中 request.HTTPBody = bodyData;
g.發(fā)送請(qǐng)求
//執(zhí)行request [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSError *error; NSDictionary *dic =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error]; if (error) { NSLog(@"%@", [error localizedDescription]); } NSLog(@"%@", dic); }];
到此微博發(fā)送成功,會(huì)在我們自己的新浪微博的主頁(yè)中顯示我們?cè)谀M器中的文本輸入的東西了,因?yàn)槲姨砑拥膽?yīng)用的access_token沒有申請(qǐng)審核,所以會(huì)顯示“來(lái)自未通過(guò)審核應(yīng)用”,截圖如下:

2.我們?nèi)绾瓮ㄟ^(guò)調(diào)用可以發(fā)圖片的API上傳本地圖片呢?為了簡(jiǎn)化我們APP的圖片的上傳,我們就得用到AFNetWorking中的東西了,如何配置和使用CocoaPods請(qǐng)參考上面的鏈接。
a.用AFHTTPRequestOperationManager來(lái)組織我們的數(shù)據(jù),數(shù)據(jù)是存儲(chǔ)在字典中的
      NSDictionary *dic = @{@"access_token": access_token, @"status":self.blogTextField.text};
b.獲取請(qǐng)求操作,并傳入字典,POST后面跟的時(shí)API中提供的URL。 self.manager是我們之前定義的屬性@property (strong, nonatomic) AFHTTPRequestOperationManager * manager; 并在viewDidLoad中分配內(nèi)存
AFHTTPRequestOperation *op = [self.manager POST:SendImage parameters:dic constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { //把圖片轉(zhuǎn)換成NSData類型的數(shù)據(jù) NSData *imageData = UIImagePNGRepresentation(self.buttonImage.imageView.image);
//把圖片拼接到數(shù)據(jù)中 [formData appendPartWithFileData:imageData name:@"pic" fileName:@"123" mimeType:@"image/png"]; } success:^(AFHTTPRequestOperation *operation, id responSEObject) { NSLog(@"%@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"%@",[error localizedDescription]); }];
c.得啟動(dòng)才可提交
//配置解析過(guò)程 op.responseSerializer = [AFCompoundResponseSerializer serializer]; //啟動(dòng)請(qǐng)求 [op start];
效果如下:


3.如果我們的圍脖到這那不太簡(jiǎn)單了蠻,如果到這就結(jié)束的話,下面又該有小伙伴評(píng)論“這有什么意義呢?”,下面就請(qǐng)求一下我的圍脖的內(nèi)容,點(diǎn)進(jìn)去是本條圍脖的評(píng)論,效果圖如下:

上面的內(nèi)容是用新浪微博提供的API用我自己的token請(qǐng)求的內(nèi)容,和我登陸圍脖賬號(hào)的首頁(yè)是一樣的數(shù)據(jù),點(diǎn)進(jìn)去是該微博的所有評(píng)論,當(dāng)然啦,上面為了省事,我們用Cell是在Storyboard中設(shè)置的。真正實(shí)現(xiàn)起來(lái)需要新建TableViewCell根據(jù)數(shù)據(jù)來(lái)定制我們想要的cell, 之后在TableViewController中進(jìn)行注冊(cè)一下就可以用了。獲取微博內(nèi)容的代碼和上面國(guó)家的代碼類似,在這就不往上貼代碼了。我們往cell中添加網(wǎng)絡(luò)請(qǐng)求的圖片時(shí)用的時(shí)AFNetWorking中的UIKit+AFNetworking.h類目,大大簡(jiǎn)化了我們網(wǎng)絡(luò)請(qǐng)求圖片的操作。設(shè)置圖片的代碼如下:
1 NSURL *url = [NSURL URLWithString:dic[@"user"][@"profile_image_url"]];2 [cell.imageView setImageWithURL:url];
如果你感覺到這這篇博文就結(jié)束啦?不可能的啦!!上面的博文都顯示不出來(lái),還有發(fā)布時(shí)間,圖片等最基本的信息都沒有。在之前的博客中有一篇“IOS開發(fā)之自動(dòng)布局顯示網(wǎng)絡(luò)請(qǐng)求內(nèi)容” ,用的網(wǎng)絡(luò)請(qǐng)求是模擬的微博請(qǐng)求,博文的內(nèi)容也是模擬的,接下來(lái)要用到上一篇博文的知識(shí):根據(jù)請(qǐng)求內(nèi)容來(lái)動(dòng)態(tài)的設(shè)置Cell的高度。下面就讓我們自定義兩種Cell來(lái)把上面的TableView完善一下吧:
1.創(chuàng)建兩種Cell,并給Cell中的各個(gè)控件設(shè)置約束

2.上面的cell是我們自定義的cell,需要關(guān)聯(lián)兩個(gè)UITableViewCell類,然后在Cell對(duì)象中進(jìn)行控件的配置和賦值,其中的一個(gè)自定義Cell的關(guān)鍵代碼如下,在TableView中我們只需要調(diào)用setCellContent方法把存有數(shù)據(jù)的字典傳到cell中中由cell賦值即可:
1 @interface TextTableViewCell() 2 3 @property (strong, nonatomic) IBOutlet UIImageView *image; 4 5 6 @property (strong, nonatomic) IBOutlet UILabel *titleLable; 7 @property (strong, nonatomic) IBOutlet UILabel *dateLabel; 8 @property (strong, nonatomic) IBOutlet UILabel *contentLable; 9 10 @end11 12 @implementation TextTableViewCell13 14 -(void)setCellContent:(NSDictionary *)dic15 {16 17 NSDateFormatter *iosDateFormater=[[NSDateFormatter alloc]init];18 iosDateFormater.dateFormat=@"EEE MMM d HH:mm:ss Z yyyy";19 //必須設(shè)置,否則無(wú)法解析20 iosDateFormater.locale=[[NSLocale alloc]initWithLocaleIdentifier:@"en_US"];21 NSDate *date=[iosDateFormater dateFromString:dic[@"created_at"]];22 23 //目的格式24 NSDateFormatter *resultFormatter=[[NSDateFormatter alloc]init];25 [resultFormatter setDateFormat:@"MM月dd日 HH:mm"];26 27 self.dateLabel.text = [resultFormatter stringFromDate:date];28 29 self.titleLable.text = dic[@"user"][@"name"];30 31 self.contentLable.text = dic[@"text"];32 33 NSURL *imgURL = [NSURL URLWithString:dic[@"user"][@"profile_image_url"]];34 [self.image setImageWithURL:imgURL];35 36 }
3、我們需要在原來(lái)顯示微博的TableView中根據(jù)請(qǐng)求的數(shù)據(jù)來(lái)選擇用哪一個(gè)Cell,選擇代碼如下:
1 //選擇判斷用哪個(gè)cell 2 -(UITableViewCell *)selectCell:(NSDictionary *)dic cellForRowAtIndexPath:(NSIndexPath *)indexPath 3 { 4 UITableViewCell *cell = nil; 5 6 //根據(jù)下面是否有圖片來(lái)判斷選擇哪一個(gè)Cell 7 if (dic[@"thumbnail_pic" ] == nil) 8 { 9 cell = [self.tableView dequeueReusableCellWithIdentifier:@"textCell" forIndexPath:indexPath];10 }11 else12 {13 cell = [self.tableView dequeueReusableCellWithIdentifier:@"imageCell" forIndexPath:indexPath];14 }15 16 return cell;17 }
4.根據(jù)微博內(nèi)容來(lái)動(dòng)態(tài)的調(diào)整cell的高度:
//根據(jù)博文的內(nèi)容調(diào)整cell的高度-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ NSDictionary *dic = self.array[indexPath.row]; NSString *text = dic[@"text"]; //用字典設(shè)置字體的大小 NSDictionary * dic1 = @{NSFontAttributeName: [UIFont systemFontOfSize:14]}; CGRect frame = [text boundingRectWithSize:CGSizeMake(276, 1000) options:NSStringDrawingUsesLineFragmentOrigin attributes:dic1 context:nil]; CGFloat height = frame.size.height; //不同類型的cell高度不同 if (dic[@"thumbnail_pic" ] == nil) { height = height + 59 + 25; } else { height = height + 59 + 25+ 105; } return height;}
5.上面是添加的代碼,下面我們需要把獲取cell的方法進(jìn)行修改,如下:
1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 2 { 3 NSDictionary *dic = self.array[indexPath.row]; 4 5 UITableViewCell *cell = [self selectCell:dic cellForRowAtIndexPath:indexPath]; 6 7 //把值給我們的cell,讓cell設(shè)置其自己的屬性 8 [cell setCellContent:dic]; 9 10 return cell;11 }
上面的時(shí)核心代碼,加入后我們?cè)趤?lái)看一下我們請(qǐng)求的效果吧,是不是看著像那么一回事兒啦,今天的博客的內(nèi)容先到這吧,以后會(huì)繼續(xù)完善我們的圍脖的:

如果有小伙伴感覺上面太簡(jiǎn)單的化,可以來(lái)的復(fù)雜的,如果微博是轉(zhuǎn)發(fā)的把轉(zhuǎn)發(fā)的微博顯示出來(lái),下面我們把轉(zhuǎn)發(fā)的帶圖片的和不帶圖片的博文顯示出來(lái),并在下面加上轉(zhuǎn)發(fā),評(píng)論和贊的按鈕。
需求難點(diǎn):
1.cell的高度根據(jù)本博文和轉(zhuǎn)發(fā)博文的多少而改變,就是在cell中有兩部分內(nèi)容的高度是變化的,需要用代碼來(lái)動(dòng)態(tài)控制其高度。先給自己發(fā)的博文設(shè)置一個(gè)垂直約束,下面轉(zhuǎn)發(fā)的博文只設(shè)置編輯約束,不設(shè)置高度約束。我們根據(jù)博文文字的多少來(lái)用代碼動(dòng)態(tài)的改變垂直約束,至于如何用代碼改變約束的值,請(qǐng)參照以前的博客IOS開發(fā)之絕對(duì)布局和相對(duì)布局(屏幕適配),在這就不做過(guò)多的論述,下面主要講如何給我們的cell添加多個(gè)按鈕,然后在點(diǎn)擊按鈕的時(shí)候我們知道是那個(gè)Cell的那個(gè)button被點(diǎn)擊了。
(1)為了區(qū)分按鈕,我們需要給每個(gè)按鈕設(shè)置tag,然后在TableViewController中獲取Tag的值,我們就知道是那個(gè)按鈕被點(diǎn)擊了。
(2)難點(diǎn)在于我們?nèi)绾闻袛啾稽c(diǎn)擊的按鈕位于那個(gè)cell上。這個(gè)得用block回調(diào)來(lái)解決問(wèn)題啦。
a.在我們Cell的類中需要定義一個(gè)block塊的類型變量,用于在TableViewController中回調(diào)使用,在block回調(diào)時(shí),我們就可以把那個(gè)Cell以及Cell中被點(diǎn)擊的按鈕傳到TableViewController中啦,至于想深入的了解一下block回調(diào),請(qǐng)參考前面的博客Objective-C中的Block回調(diào)模式。下面是在Cell對(duì)應(yīng)的類中,聲明Block塊類型的代碼:
//創(chuàng)建cell的block塊把按鈕的tag傳到ViewController中typedef void (^CellBlock) (ReTextTableViewCell * cell, int buttonTag);
b.在Cell中添加CellBlock類型的變量,用于接收回調(diào)
1 @property (strong, nonatomic) CellBlock block;
c.添加設(shè)置block的setter方法,參數(shù)是要傳入的block塊
1 -(void)setTagButtonBlock:(CellBlock)cellBlock2 {3 self.block = cellBlock;4 }
d.點(diǎn)擊不同的button是給傳入的block設(shè)置不同的值,也就是把Button的tag傳入到block中。添加的三個(gè)按鈕對(duì)應(yīng)著一個(gè)回調(diào)方法,代碼如下:
1 - (IBAction)tapComment:(id)sender {2 UIButton *button = sender;3 4 self.block(self, button.tag);5 }
(3)在我們的TableView中實(shí)現(xiàn)Cell的回調(diào),給據(jù)回調(diào)參數(shù)Button.tag的值的不同,去執(zhí)行相應(yīng)的業(yè)務(wù)邏輯,回調(diào)的代碼如下:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ NSDictionary *dic = self.array[indexPath.row]; UITableViewCell *cell = [self selectCell:dic cellForRowAtIndexPath:indexPath]; //把值給我們的cell,讓cell設(shè)置其自己的屬性 [cell setCellContent:dic]; __weak __block NSDictionary *copy_dic = dic; __weak __block SinaBlogTableViewController *copy_self = self; if ([cell isKindOfClass:[ReTextTableViewCell class]] || [cell isKindOfClass:[ReImageTableViewCell class]]) { ReTextTableViewCell * cellTemp =( ReTextTableViewCell *) cell; [cellTemp setTagButtonBlock:^(ReTextTableViewCell *cell, int buttonTag) { switch (buttonTag) { case 1: { NSLog(@"轉(zhuǎn)發(fā)"); NSString *str = @"https://api.weibo.com/2/statuses/repost.json"; NSDictionary *dic = @{@"access_token":@"你自己的令牌" ,@"id":[NSString stringWithFormat:@"%@",copy_dic[@"id"]]}; //用AFHTTPRequestOperationManager來(lái)組織我們的數(shù)據(jù),數(shù)據(jù)是存儲(chǔ)在字典中的 AFHTTPRequestOperation *op = [self.manager POST:str parameters:dic success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"%@",responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"%@",[error localizedDescription]); }]; //配置解析過(guò)程 op.responseSerializer = [AFJSONResponseSerializer serializer]; //啟動(dòng)請(qǐng)求 [op start]; } break; case 2: { NSLog(@"評(píng)論"); UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; id vc = [storyboard instantiateViewControllerWithIdentifier:@"Comments"]; [vc setValue:copy_dic forKey:@"userInfo"]; [copy_self.navigationController pushViewController:vc animated:YES]; } break; case 3: NSLog(@"贊"); break; default: break; } }]; } return cell;}
經(jīng)過(guò)上面的那些代碼的修飾,我們的新浪微博的效果如下,因?yàn)榱钆剖怯梦易约旱奈⒉┵~號(hào)申請(qǐng)的,所以顯示的東西和我新浪微博的主頁(yè)是一樣的:


新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注