摘要:[iOS] Objective-c 對的Json操作(六) UITableView 操作 WebApi資料
前面討論了許多Json檔案序列化回強型別的物件集合後,這一篇我們要把這個應用帶進UITableView裡面。這是在開發上常常會碰到的應用。你的公司Server Backend提供了一個WebApi,而App可以經由這個WebApi的服務來取得資料。當然,資料傳遞的方式目前主流上是Json的格式。這一篇要開始把前面討論過的東西帶進UITableView。
在Xcode裡面新建一個UITableView專案,在這個專案中,我們要執行以下的步驟。
1. 新增一個對應到http://benluwebapi.azurewebsites.net/api/values 的類別物件。
2. 新增Jastor Library專案裡面。(對此物件還不熟悉的話,請參考前面的章節)
3. 在iPhoneStoreboard的畫面上拖拉出UITableView以及客製化UITableCell
4. 新增一個myCell類別,繼承UITableViewCell。
5. 在Layout畫面對應到ViewController實作UITabelviewdelegate與UITablesource
6. 在ViewController實作存取WebApi資料的程式。
1. 新增一個對應到http://benluwebapi.azurewebsites.net/api/values 的類別物件。
把這個網址貼到Json to C# 網站(http://json2csharp.com ),可以取得C#的類別檔,自己需要辛苦一點在把它轉換成Objective-c的類別檔。
在專案中建立一個Cocoa Touch Class,我就命名為object.h檔。
object.h 檔案內容
@interface RootObject : Jastor
@property (nonatomic) NSString* title;
@property (nonatomic) NSString* detail;
@property (nonatomic) NSString* image;
@end
object.m 檔案內容
#import
#import "object.h"
@implementation RootObject
@synthesize title,detail,image;
@end
2. 新增Jastor Library專案裡面。
新增libJson.oc.a 與Jastor.h檔還有JastorRuntimeHelper.h檔案到專案之中。
3. 在iPhoneStoreboard的畫面上拖拉出UITableView以及客製化UITableCell
4. 新增一個myCell類別,繼承UITableViewCell。
把StoryBoard畫面上的UI控制項與myCell.h檔案產生IBoutlet關聯。
myCell.h檔案內容
@interface myCell : UITableViewCell
@property (weak, atomic) IBOutlet UIImageView *myImage;
@property (weak, nonatomic) IBOutlet UILabel *myLabel;
@property (weak, nonatomic) IBOutlet UILabel *myLabelDetail;
@end
5. 在Layout畫面對應到ViewController實作UITabelviewdelegate與UITablesource
ViewController.h檔案
#import
#import "object.h"
@interface ViewController : UIViewController
//用來序列化Json的型別
@property (nonatomic)RootObject* info;
//動態陣列用來存放Json物件集合
@property (nonatomic) NSMutableArray *Listobj;
//UITableView的IBoutlet
@property (nonatomic) IBOutlet UITableView* myTable;
@end
ViewController.m檔案
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.myTable.delegate = self;
self.myTable.dataSource = self;
NSURL *url = [NSURL URLWithString:@"http://benluwebapi.azurewebsites.net/api/values"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
//取得Json資訊
NSArray* jsonobj = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:nil];
//初始化Listobj物件
Listobj = [[NSMutableArray alloc]init];
//迭代出NSArray裡面的所有值,轉成物件後,存放到NSMutableArray裡面
[jsonobj enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
NSDictionary* array1 = [jsonobj objectAtIndex:idx];
RootObject *product = [[RootObject alloc] initWithDictionary:array1];
[Listobj addObject:product];
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return Listobj.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
myCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
cell = [[myCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//取得NSMutableArray裡面的物件
//接著就可以用物件屬性的方式來操作物件
RootObject *rootobject = [Listobj objectAtIndex:[indexPath row]];
//接著就可以用物件屬性的方式來操作物件
cell.myLabel.text = rootobject.title;
cell.myLabelDetail.text = rootobject.detail;
//同步下載方式
NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: rootobject.image]];
cell.myImage.image = [UIImage imageWithData:imageData];
return cell;
}
範例做到這邊時,編譯這個App,同步下載圖片的時候,在滑動的時候整個就卡卡的。所以這時候要改用非同步的方式來下載圖片。
//非同步下載方式
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSData *imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: rootobject.image]];
if ( imageData == nil )
return;
dispatch_async(dispatch_get_main_queue(), ^{
// WARNING: is the cell still using the same data by this point??
cell.myImage.image = [UIImage imageWithData:imageData];
});
});
編譯這個程式之後,可以看到TableView在下載圖片不會在卡卡的,不過解決掉卡卡的問題後,又出現了圖片會錯位的問題。這跟iOS的記憶體運作方式有關係,我們在下一篇再來解釋與解決這個問題。
範例程式下載:https://github.com/twbenlu/JsonToUITableViewWithWebApi
參考文獻:
Getting Image from URL Objective C
http://stackoverflow.com/questions/933099/getting-image-from-url-objective-c
iOS 开发UITableView 加载图片的内存管理