2014-01-18 98 views
6

我在故事板工作,但我現在推測是時候面對代碼...填充的UITableView使用JSON陣列

我有我的輸出MySQL數據庫表的內容作爲我的服務器上的PHP文件陣列JSON格式:

{ 
"id":"2", 
"name":"The King's Arms", 
"city":"London", 
"day":"Tuesday", 
} 

我最終需要的所有數據,但現在我只想輸出城市領域的一個UITableView。我會如何去做這件事?

+0

你想知道如何從JSON對象中提取數據嗎? – Dinesh

+0

是的,然後如何在UITableView中顯示它們。 – Sebastian

+1

@Sebastian現在爲你寫一份指南。和我一起。 – Pavan

回答

18

我相信這是在2012/2013年,Apple在代碼實踐中覆蓋了一段精彩的視頻,突出強調的一個子主題是處理JSON對象併爲其創建數據對象的一種非常聰明的方式。對不起,我忘了實際視頻的名稱,如果有人記得它,請爲我編輯答案。

覆蓋的蘋果是有一個數據對象,存儲每個json對象。然後,我們將創建一個數組來存儲這些對象,並在填充tableView時適當地訪問必需的字段。所以在你的情況下,你會做這樣的事情。

項目中的導航

添加的NSObject類型的文件,並添加以下代碼:

#import <Foundation/Foundation.h> 
@interface PlaceDataObject : NSObject 

-(id)initWithJSONData:(NSDictionary*)data; 

@property (assign) NSInteger placeId; 
@property (strong) NSString *placeName; 
@property (strong) NSString *placeCity; 
@property (strong) NSString *placeDay; 

@end 

,並在您.m文件中,可以添加以下代碼

#import "PlaceDataObject.h" 
@implementation PlaceDataObject 
@synthesize placeId; 
@synthesize placeName; 
@synthesize placeCity; 
@synthesize placeDay; 

-(id)initWithJSONData:(NSDictionary*)data{ 
    self = [super init]; 
    if(self){ 
     //NSLog(@"initWithJSONData method called"); 
     self.placeId = [[data objectForKey:@"id"] integerValue]; 
     self.placeName = [data objectForKey:@"name"]; 
     self.placeCity = [data objectForKey:@"city"]; 
     self.placeDay = [data objectForKey:@"day"]; 
    } 
    return self; 
} 
@end 

你現在有什麼是數據對象類,你可以在任何需要的代碼中隨處使用數據對象類,並獲取相應的細節信息,無論是表city字段表還是city and name表等。通過這樣做, l也避免在項目中的任何地方使用json解碼代碼。當'鑰匙'的名稱改變時會發生什麼?而不是通過您的代碼來檢查您的所有密鑰,只需轉到PlaceDataObject類並更改相應的key,您的應用程序將繼續工作。

蘋果解釋說這口井。

「模型對象代表特別的知識和專長,他們認爲應用程序的數據,並確定處理這些數據的邏輯設計良好的MVC應用程序封裝在其所有的重要數據。模型對象......他們代表與特定問題領域相關的知識和專業知識,他們往往是可重用的。「

填充與從服務器

進來現在到填充此自定義數據對象,你所做的每一個數組JSON項自定義對象的數組。現在遵循MVC方法,最好的辦法是將所有處理數據的方法都放在不同的類(Model類)中。這就是蘋果公司建議將這些方法放在所有處理過程中的單獨模型類中。

但是現在我們只是將以下代碼添加到View Controller中,僅用於演示目的。

在你的視圖控制器的m文件中創建一個方法來處理你的JSON數組。

//make sure you have a global NSMutableArray *placesArray in your view controllers.h file. 
-(void)setupPlacesFromJSONArray:(NSData*)dataFromServerArray{ 
    NSError *error; 
    NSMutableArray *placesArray = [[NSMutableArray alloc] init]; 
    NSArray *arrayFromServer = [NSJSONSerialization JSONObjectWithData:dataFromServerArray options:0 error:error]; 

    if(error){ 
     NSLog(@"error parsing the json data from server with error description - %@", [error localizedDescription]); 
    } 
    else { 
     placesArray = [[NSMutableArray alloc] init]; 
     for(NSDictionary *eachPlace in arrayFromServer) 
     { 
      PlaceDataObject *place = [PlaceDataObject alloc] initWithJSONData:eachPlace]; 
      [placesArray addObject:place]; 
     } 

     //Now you have your placesArray filled up with all your data objects 
    } 
} 

而且你會打電話像這樣的上述方法:

//This is not what your retrievedConnection method name looks like ;) 
// but you call the setupPlacesFromJSONArray method inside your connection success method 
-(void)connectionWasASuccess:(NSData *)data{ 
    [self setupPlacesFromJSONArray:data]; 
} 

與您的自定義數據填充您的tableView對象

至於你TableView中填入你的數據,你這樣做的像這個:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 
    //We check against table to make sure we are displaying the right number of cells 
    // for the appropriate table. This is so that things will work even if one day you 
    //decide that you want to have two tables instead of one. 
    if(tableView == myCitysTable){ 
      return([placesArray count]); 
    } 
    return 0; 
} 


-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; 
    if(cell) 
    { 
      //set your configuration of your cell 
    } 
    //The beauty of this is that you have all your data in one object and grab WHATEVER you like 
    //This way in the future you can add another field without doing much. 

    if([placesArray count] == 0){ 
     cell.textLabel.text = @"no places to show"; 
    } 
    else{ 
     PlacesDataObject *currentPlace = [placesArray objectAtIndex:indexPath.row]; 
     cell.textLabel.text = [currentPlace placeCity]; 
     // in the future you can grab whatever data you need like this 
     //[currentPlace placeName], or [currentPlace placeDay]; 
    }  
    return(cell); 
} 

簡短的免責聲明:上面的代碼沒有經過測試,但請告訴我,如果一切正常,或者我忽略了任何字符。

+1

非常感謝,這看起來不錯。我會坐下來實施它,並接受我的時間。 – Sebastian

+0

現在檢查代碼,刷新頁面,因爲我添加了更多的更改,例如數組驗證等。 – Pavan

+0

一個問題 - 我在Storyboard中開發了我的界面,所以我沒有viewcontroller.m - 是否有某個地方否則我把該代碼或有沒有辦法找到該文件? – Sebastian

1

如果來自服務器的原始數據到達NSData對象,則可以使用NSJSONSerialization類爲您解析它。

即:

NSError *error; 
NSMutableArray *cityArray = [[NSMutableArray alloc] init]; 
NSArray *arrayFromServer = [NSJSONSerialization JSONObjectWithData:dataFromServer options:0 error:error]; 
if(arrayFromServer) 
{ 
    NSLog(@"error parsing data - %@", [error localizedDescription]); 
} else { 
    for(NSDictionary *eachEntry in arrayFromServer) 
    { 
     NSString *city = [eachEntry objectForKey:@"city"]; 

     [cityArray addObject: city]; 
    } 
} 

一旦你完成填充你的城市的陣列,這是你可以在表視圖的數據源方法返回的內容:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    return 1; // your table only has one section, right? 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    if(section == 0) 
    { 
      return([cityArray count]); 
    } 
    NSLog(@"if we're at this place in the code, your numberOfSectionsInTableView is returning something other than 1"); 
    return 0; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // are you using standard (default) cells or custom cells in your storyboard? 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; 
    if(cell) 
    { 
      cell.text = [cityArray objectAtIndex:indexPath.row]; 
    } 
    return(cell); 
} 
+0

我不認爲這是填充陣列的最佳方式。 – Pavan

+0

也許你是對的,@Pavan。你可以做一個更好的方法,我會upvote它的答案。 –

+0

@michaeldatuermann是的,我們說話時就這麼做了。 – Pavan

0

什麼是myCitysTable,Paven?那是否應該是TableView的名字?如果是這樣,我正在努力弄清楚如何命名它...