前言:對伺服器請求之後,返回給用戶端的資料,一般都是JSON格式或者XML格式(檔案下載除外)
本篇隨便先講解JSON解析。
本文:
關於JSON:
JSON是一種輕量級的資料格式,一般用於資料互動JSON的格式很像Objective-C中的字典和數組:{"name":"jack","age":10}
補充:
標準的JSON格式的注意點:key必須用雙引號。(但是在Java中是單引號)
JSON-OC的轉換對照表
其中:null--返回OC裡的NSNull類型
使用:
在JSON解析方案有很多種,但是(蘋果原生的)NSJSONSerialization效能最好
還原序列化(JSON --> OC對象),下面樣本解析成字典對象
序列化(OC對象 --> JSON),注意字典的值不能傳nil,但是可以傳[NSNull null]
並不是所有的類型都是可以轉為JSON的
以下是蘋果官方規定:
我們再來看個執行個體:
#import "MainViewController.h" #import "Video.h" #define kBaseURL @"http://192.168.3.252/~apple" @interface MainViewController () @property (strong, nonatomic) NSArray *dataList; @property (weak, nonatomic) UITableView *tableView; @end @implementation MainViewController class="p1">"412158" snippet_file_name="blog_20140630_1_3481337" name="code" class="objc"> #pragma mark 執行個體化視圖 - (void)loadView { self.view = [[UIView alloc]initWithFrame:[UIScreen mainScreen].applicationFrame]; //1 tableview CGRect frame = self.view.bounds; UITableView *tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height - 44) style:UITableViewStylePlain]; //1)資料來源 [tableView setDataSource:self]; //2)代理 [tableView setDelegate:self]; //)設定表格高度 [tableView setRowHeight:80]; [self.view addSubview:tableView]; self.tableView = tableView; //toolBar UIToolbar *toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, tableView.bounds.size.height, 320, 44)]; [self.view addSubview:toolBar]; //添加toolbar按鈕 UIBarButtonItem *item1 = [[UIBarButtonItem alloc]initWithTitle:@"load json" style:UIBarButtonItemStyleDone target:self action:@selector(loadJson)]; UIBarButtonItem *item2 = [[UIBarButtonItem alloc]initWithTitle:@"load xml" style:UIBarButtonItemStyleDone target:self action:@selector(loadXML)]; UIBarButtonItem *item3 = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; [toolBar setItems:@[item3, item1, item3, item2, item3]]; } #pragma mark -uitableview資料來源方法 對於uitableview下面這兩個方法是必須實現的。 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.dataList.count; } //每填充一行都調用一次這個方法。知道介面上的所有行都填充完畢。, - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //使用可充用標示符查詢可重用儲存格 static NSString *ID = @"MyCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; } //設定儲存格內容 Video *v = self.dataList[indexPath.row]; cell.textLabel.text = v.name; cell.detailTextLabel.text = v.teacher; //載入圖片 //1)同步載入網狀圖片,同步方法以為這這些指令在完成之前,後續指令都無法執行。 //注意:在開發網路應用時,不要使用同步方法載入圖片,否則會嚴重影響使用者體驗 // NSString *imagePath = [NSString stringWithFormat:@"%@%@", kBaseURL, v.imageURL]; // NSURL *imageUrl = [NSURL URLWithString:imagePath]; // NSData *imageData = [NSData dataWithContentsOfURL:imageUrl]; // UIImage *image = [UIImage imageWithData:imageData]; // // //2)非同步載入網狀圖片 // //網路連接本身就有非同步命令 sendAsync // [cell.imageView setImage:image]; //如果緩衝映像不存在 if (v.cacheImage == nil) { //使用預設映像佔位,即能夠保證有映像,又能夠保證有地方。 UIImage *image = [UIImage imageNamed:@"user_default.png"]; [cell.imageView setImage:image]; //使用預設映像佔位 //開啟非同步串連,載入映像,因為載入完成之後,需要重新整理對應的表格航 [self loadImageAsyncWithIndexPath:indexPath]; }else { [cell.imageView setImage:v.cacheImage]; } //[self loadImageAsyncWithUrl:imageUrl imageView:cell.imageView]; return cell; } #pragma mark 非同步載入網狀圖片 //由於uitableview是可重用的,為了避免使用者快速頻繁重新整理表格,造成資料衝突,不能直接將uiimageview傳入非同步方法呼叫 //正確的解決方案是:將表格行的indexpath傳入非同步方法呼叫,載入完成映像以後,直接重新整理指定的行。 - (void)loadImageAsyncWithIndexPath:(NSIndexPath *)indexPath { Video *v = self.dataList[indexPath.row]; //取出當前要填充的行 NSString *imagePath = [NSString stringWithFormat:@"%@%@", kBaseURL, v.imageURL]; NSURL *imageUrl = [NSURL URLWithString:imagePath]; //NSLog(@"%@ %@", url, imageView); //1 request NSURLRequest *request = [NSURLRequest requestWithURL:imageUrl]; //2 connection sendasync非同步請求 [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { //UIImage *image = [UIImage imageWithData:data]; //[imageView setImage:image]; //將網路資料儲存至緩衝映像。 v.cacheImage = [UIImage imageWithData:data]; //重新整理表格 [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft]; }]; } #pragma mark 處理json資料 - (void)handlerJSONData:(NSData *)data { //json檔案中的[]表示一個資料。 //還原序列化json資料 //第二個參數是解析方式,一般用NSJSONReadingAllowFragments NSArray *array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]; NSLog(@"%@", array); //json解析以後是nsarray格式的資料。 //提示:如果開發網路應用,可以將還原序列化出來的對象,儲存至沙箱,以便後續開發使用。 NSArray *docs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *path = [docs[0]stringByAppendingPathComponent:@"json.plist"]; [array writeToFile:path atomically:YES]; //把array裡面的資料寫入沙箱中的jspn.plist中。 //給資料列表賦值 NSMutableArray *arrayM = [NSMutableArray array]; for (NSDictionary *dict in array) { Video *video = [[Video alloc]init]; //給video賦值 [video setValuesForKeysWithDictionary:dict]; [arrayM addObject:video]; } self.dataList = arrayM; //重新整理表格 [self.tableView reloadData]; NSLog(@"%@", arrayM); //這句話將調用video裡面的description和nsarray+log裡面的descriptionWithLocale } #pragma mark 載入json - (void)loadJson { NSLog(@"load json"); //從web伺服器載入資料 NSString *str = @"http://www.baidu.com?format=json"; //這裡是亂寫的 //提示:NSData本身具有同步方法,但是在實際開發中,不要使用次方法 //在使用NSData的同步方法時,無法指定逾時時間,如果伺服器串連不正常,會影響使用者體驗。 //NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:str]]; //簡曆NSURL NSURL *url = [NSURL URLWithString:str]; //建立NSURLRequest NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:2.0f]; //建立NSURLConnect的同步方法載入資料 NSURLResponse *response = nil; NSError *error = nil; //同步載入資料 NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; //錯誤處理 if (data != nil) { //下面這兩句話本身沒有什麼意義,僅用於跟蹤調試。 NSString *result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); //在處理網路資料的時候,不要將NSData轉換成nsstring。 [self handlerJSONData:data]; }else if (data == nil && error == nil){ NSLog(@"空資料"); }else { NSLog(@"%@", error.localizedDescription); } } #pragma mark 載入xml - (void)loadXML { NSLog(@"load xml"); } //- (void)viewDidLoad //{ // [super viewDidLoad]; //} @end