如何使用来自不同 ViewController 的 JSON 响应填充 UITableView?

Posted

技术标签:

【中文标题】如何使用来自不同 ViewController 的 JSON 响应填充 UITableView?【英文标题】:How to populate UITableView with the responce of JSON from a different ViewController? 【发布时间】:2012-01-23 09:01:25 【问题描述】:

我在 ***.com 中搜索和搜索,但无法摆脱这种情况,如何使用 GET 响应填充 TableView。我发送 GET 并在 DetailViewController(我的主控制器)中的一个方法中解析响应,并希望使用响应的一部分初始化 TableViewCell,并使用另一部分初始化该单元格的详细信息。我创建了 messageTableViewmessageDetailViewController ..如果问题不够清楚,我也可以共享代码。谢谢

编辑我知道这不是我们想要的,但我共享了所有代码,因为我无法在 viewControllers 之间绑定变量,我可以在视图之间导航,但我无法在彼此之间共享变量..

这是我的 DetailViewController 的界面文件(在我的应用中,它是主视图控制器)

#import <UIKit/UIKit.h>

@interface BNT_1DetailViewController : UIViewController <UISplitViewControllerDelegate>

    NSMutableArray *buttons;
    NSString *userName, *password, *serverIP;
    NSDictionary *mess;
    IBOutlet UITextField *userNameF;
    IBOutlet UITextField *passwordF;
    IBOutlet UITextField *serverF;
    NSURL *url;
    NSMutableArray *mesag;
    IBOutlet UIButton *acceptButton;
    NSMutableArray *mesID; //saving meesage ID s to NSMutableArray
    NSMutableArray *content; 


@property(retain,nonatomic)NSMutableArray *mesID,*content;
@property(assign,nonatomic)NSMutableArray *mesag ;
@property(retain, nonatomic)NSDictionary *mess;
//@property (retain,nonatomic)  NSMutableArray *buttons;
@property (retain, nonatomic) UITextField *userNameF;
@property (retain, nonatomic) UITextField *passwordF;
@property (retain, nonatomic) UITextField *serverF;
@property (retain, nonatomic) UIButton *acceptButton;
@property (retain, nonatomic) NSString *userName, *password, *serverIP;
@property (strong, nonatomic) id detailItem;
@property(retain,nonatomic)NSURL *url;
@property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;

-(IBAction)acceptAct:(id)sender;
-(IBAction)readMessages:(id)sender;
-(IBAction)secondAct:(id)sender;
@end

这是它的实现文件:

#import "BNT_1DetailViewController.h"
#import "mainMenu.h"
#import "messages.h"
@interface BNT_1DetailViewController ()
@property (strong, nonatomic) UIPopoverController *masterPopoverController;
- (void)configureView;
@end

@implementation BNT_1DetailViewController
@synthesize content,mesID,url;
@synthesize mesag,mess;
@synthesize userNameF, passwordF, serverF, acceptButton;
@synthesize userName, password, serverIP;
@synthesize detailItem = _detailItem;
@synthesize detailDescriptionLabel = _detailDescriptionLabel;
@synthesize masterPopoverController = _masterPopoverController;

-(IBAction)readMessages:(id)sender

    messages *message=[[messages alloc]initWithNibName:@"messages" bundle:nil];
    /*
     message.mesid=mesID;
     message.contents=content;
     */
    [self.navigationController pushViewController:message animated:TRUE];





-(IBAction)acceptAct:(id)sender


    userName=[[NSString alloc] initWithString:userNameF.text ];
    [userNameF setText:userName];
    NSUserDefaults *userNameDef= [NSUserDefaults standardUserDefaults];
    [userNameDef setObject:userName forKey:@"userNameKey"];
    password =[[NSString alloc] initWithString:passwordF.text];
    [passwordF setText:password];
    NSUserDefaults *passDef=[NSUserDefaults standardUserDefaults];
    [passDef setObject:password forKey:@"passwordKey"];
    serverIP=[[NSString alloc] initWithString: serverF.text];
    [serverF setText:serverIP];
    NSUserDefaults *serverDef=[NSUserDefaults standardUserDefaults];
    [serverDef setObject:serverIP forKey:@"serverIPKey"];
    [userNameDef synchronize];
    [serverDef synchronize];
    [passDef synchronize];


    UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"BNTPRO "
                                                      message:@"Your User Informations are going to be sent to server. Do you accept?"
                                                     delegate:self
                                            cancelButtonTitle:@"OK"
                                            otherButtonTitles:@"Cancel",  nil];
    [message show];


- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

    NSString *title = [alertView buttonTitleAtIndex:buttonIndex];

    if([title isEqualToString:@"OK"])
    
        if([userNameF.text isEqualToString:@""]|| [passwordF.text isEqualToString:@""] || [serverF.text length]<6) 
        
            UIAlertView *message1 = [[UIAlertView alloc] initWithTitle:@"BNTPRO "
                                                               message:@"Your User Informations are not defined properly!"
                                                              delegate:nil
                                                     cancelButtonTitle:@"OK"
                                                     otherButtonTitles:  nil];

            [message1 show];
            [userNameF  resignFirstResponder];
            [passwordF resignFirstResponder];
            return;
        
        mainMenu *ma=[[mainMenu alloc]initWithNibName:@"mainMenu" bundle:nil];
        NSString *str1=[@"?username=" stringByAppendingString:userNameF.text];
        NSString *str2=[@"&password=" stringByAppendingString:passwordF.text];
        NSString *str3=[str1 stringByAppendingString:str2];
        NSString *str4 =[@"http://" stringByAppendingString:serverF.text];


       url=[NSURL URLWithString:[str4 stringByAppendingString:[@"/ipad/login.php" stringByAppendingString:str3]]];
        //get the url to jsondata
        NSData *jSonData=[NSData dataWithContentsOfURL:url];

        if (jSonData!=nil) 
            NSError *error=nil;
            id result=[NSJSONSerialization JSONObjectWithData:jSonData options:
                       NSJSONReadingMutableContainers error:&error];
            NSLog(@"%@",result);       

            if (error==nil) 
            mess=[result objectForKey:@"message"];
                NSDictionary *messContent=[mess valueForKeyPath:@"message"];
                NSDictionary *messID=[mess valueForKeyPath:@"ID"];
                NSString*key1=[ result objectForKey:@"key" ];                
                NSString *s1=[@"http://" stringByAppendingString:serverF.text];
                NSString *s2=[s1 stringByAppendingString:@"/ipad/button.php"];
                NSURL *url2=[NSURL URLWithString:[s2 stringByAppendingString:[@"?key=" stringByAppendingString:key1]]];

                NSData *data2=[NSData dataWithContentsOfURL:url2];
                id result2=[NSJSONSerialization JSONObjectWithData:data2 options:NSJSONReadingMutableContainers error:nil];

                mesID = [NSMutableArray array];//saving meesage ID s to NSMutableArray
                content = [NSMutableArray array];    
                for ( mesag in mess) 

                    //i want to populate TableViewCells with the messID and the details of each cell(push in new view controller) will contain 'content' above

                  /*
                     [mesID addObject:[mesag objectForKey:@"ID"]];
                     [content addObject:[mesag objectForKey:@"message"]];    
                     */    
                    [[NSUserDefaults standardUserDefaults] setObject:messID forKey:@"message"];
                    [[NSUserDefaults standardUserDefaults] setObject:messContent forKey:@"messContent"];

                    // NSLog(@"%@", [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]);
                    //   NSLog(@"The Message with ID %@ is: %@\n",messID,messContent);

                

                NSLog(@"MessID: %@",mesID);
                NSLog(@"Context: %@",content);


                buttons = [NSMutableArray array];
                CGFloat yPosition = 60.0f;
                CGFloat xPosition = 40.0f;

                const CGFloat buttonHeight = 75.0f;
                const CGFloat buttonMargin = 50.0f;
                UIButton *bt=[UIButton buttonWithType:UIButtonTypeRoundedRect];

                [bt setTitle:@"Messages" forState:UIControlStateNormal];
                [bt addTarget:self action:@selector(readMessages:) forControlEvents:UIControlEventTouchUpInside];
                bt.titleLabel.font=[UIFont systemFontOfSize:25];
                bt.frame=CGRectMake(300.0f, 700.0f,180.0f , 70.0f);
                [ma.view addSubview:bt];

                for(NSDictionary* buttonData in result2)  
                    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
                    NSString* buttonTitle = [buttonData objectForKey:@"name"];
                    NSString* buttonID=[buttonData objectForKey:@"ID"];
                    [button setTitle:buttonTitle forState:UIControlStateNormal];
                    [button setTag:[buttonID intValue]];
                    button.titleLabel.font=[UIFont systemFontOfSize:28];
                    button.frame = CGRectMake(xPosition, yPosition, 210.0f, buttonHeight);
                    [button addTarget:self action:@selector(secondAct:) forControlEvents:UIControlEventTouchUpInside];
                    [ma.view addSubview:button];
                    //   [v.buttons addObject:button];

                    xPosition = 260.0f;
                    yPosition+= buttonHeight + buttonMargin;

                


            [self.navigationController pushViewController:ma animated:TRUE];



         


-(IBAction)secondAct:(id)sender

    NSLog(@"ABC: %d",[sender tag]);



- (void)dealloc

    [_detailItem release];
    [_detailDescriptionLabel release];
    [_masterPopoverController release];
    [super dealloc];


#pragma mark - Managing the detail item

- (void)setDetailItem:(id)newDetailItem

    if (_detailItem != newDetailItem) 
        [_detailItem release]; 
        _detailItem = [newDetailItem retain]; 

        // Update the view.
        [self configureView];
    

    if (self.masterPopoverController != nil) 
        [self.masterPopoverController dismissPopoverAnimated:YES];
            


- (void)configureView

    // Update the user interface for the detail item.

    if (self.detailItem) 
        self.detailDescriptionLabel.text = [self.detailItem description];
    


- (void)didReceiveMemoryWarning

    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.


#pragma mark - View lifecycle

- (void)viewDidLoad

    [super viewDidLoad];
    [passwordF setSecureTextEntry:YES];
    userNameF.font=[UIFont systemFontOfSize:24];

    userNameF.frame = CGRectMake(320.0f,60.0f,360.0f,50.0f);
    passwordF.frame = CGRectMake(320.0f,145.0f,360.0f,50.0f);
    serverF.frame= CGRectMake(320.0f,235.0f,360.0f,50.0f);
    userNameF.font=[UIFont boldSystemFontOfSize:24];
    [userNameF becomeFirstResponder];
    serverF.font=[UIFont boldSystemFontOfSize:24];
    passwordF.font=[UIFont systemFontOfSize:24];


    acceptButton.titleLabel.font=[UIFont boldSystemFontOfSize:26];
    // Do any additional setup after loading the view, typically from a nib.
    [self configureView];


- (void)viewDidUnload

    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;


- (void)viewWillAppear:(BOOL)animated

    [super viewWillAppear:animated];


- (void)viewDidAppear:(BOOL)animated

    [super viewDidAppear:animated];


- (void)viewWillDisappear:(BOOL)animated

    [super viewWillDisappear:animated];


- (void)viewDidDisappear:(BOOL)animated

    [super viewDidDisappear:animated];


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

    // Return YES for supported orientations
    return YES;


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) 
        self.title = NSLocalizedString(@"Detail", @"Detail");
    
    return self;


#pragma mark - Split view

- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController

    barButtonItem.title = NSLocalizedString(@"Master", @"Master");
    [self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
    self.masterPopoverController = popoverController;


- (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem

    // Called when the view is shown again in the split view, invalidating the button and popover controller.
    [self.navigationItem setLeftBarButtonItem:nil animated:YES];
    self.masterPopoverController = nil;


@end

我想用 messID 填充 TableViewCells,每个单元格的详细信息(推入新视图控制器)将包含上面的“内容”

这是我的TableViewController 文件,名为messages: (.h 文件)

#import <UIKit/UIKit.h>

@interface messages : UITableViewController

    NSMutableArray *mesid,*contents; 



@property(retain,nonatomic)NSMutableArray *mesid,*contents;


@end

和.m文件:

#import "messages.h"
#import "messageDetail.h"
@implementation messages
@synthesize mesid;
- (id)initWithStyle:(UITableViewStyle)style

    self = [super initWithStyle:style];
    if (self) 
        // Custom initialization
    
    return self;


- (void)didReceiveMemoryWarning

    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.


#pragma mark - View lifecycle

- (void)viewDidLoad

    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations.
     self.clearsSelectionOnViewWillAppear = NO;

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
     self.navigationItem.rightBarButtonItem = self.editButtonItem;


- (void)viewDidUnload

    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;


- (void)viewWillAppear:(BOOL)animated

    

- (void)viewDidAppear:(BOOL)animated

    [super viewDidAppear:animated];


- (void)viewWillDisappear:(BOOL)animated

    [super viewWillDisappear:animated];


- (void)viewDidDisappear:(BOOL)animated

    [super viewDidDisappear:animated];


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

    // Return YES for supported orientations
    return YES;


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

#warning Potentially incomplete method implementation.
    // Return the number of sections.
    return 1;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

#warning Incomplete method implementation.
    // Return the number of rows in the section.

   return [mesid count];


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    
    cell.textLabel.text=[mesid objectAtIndex:indexPath.row];
    [tableView reloadData]; 
    // Configure the cell...

    return cell;



// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath

    // Return NO if you do not want the specified item to be editable.
    return YES;




// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath

    if (editingStyle == UITableViewCellEditingStyleDelete) 
        // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
       
    else if (editingStyle == UITableViewCellEditingStyleInsert) 
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
       



/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath


*/

/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath

    // Return NO if you do not want the item to be re-orderable.
    return YES;

*/

#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    // Navigation logic may go here. Create and push another view controller.

     messageDetail *detailViewController = [[messageDetail alloc] initWithNibName:@"messageDetail" bundle:nil];
     // ...
     // Pass the selected object to the new view controller.
     [self.navigationController pushViewController:detailViewController animated:YES];
     detailViewController.title=@"Message Detail";
     [detailViewController release];



@end

我的最后一个控制器是 messageDetails。它的接口文件是:

#import <UIKit/UIKit.h>

@interface messageDetail : UIViewController

@end

最后一个,messageDetail的实现文件:

#import "messageDetail.h"

@implementation messageDetail

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) 
        // Custom initialization
    
    return self;


- (void)didReceiveMemoryWarning

    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.


#pragma mark - View lifecycle

- (void)viewDidLoad

    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.


- (void)viewDidUnload

    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

    // Return YES for supported orientations
    return YES;


@end

【问题讨论】:

我编辑了问题,希望这种风格不会太无聊:) 【参考方案1】:

我快速浏览一下就发现了几个问题: 1. 你有一个 UITableViewController 的实例。 UITableViewController 的正确初始化是initWithStyle: 改用它。否则你需要做一些额外的工作,而且真的不需要。 2. 您正在检查UIAlertView 实例中按钮的字符串。我的建议是不要这样做。字符串在某种程度上是易变的。可以将多语言作为一项功能插入,之后您可能会遇到问题。而是检查索引。这是一个简单的 int,而不是令人头疼的警报! 3. 您已将NSMutableArray 设置为messages 类中的属性。你为什么不填充它。这就是信息没有出现在您的表格中的原因:因为您没有将其提供给特定的班级。 从控制器初始化控制器(包含表视图的类),提供原始控制器的内容。

建议: 4. 为了标准化,用大写字母命名你的类,用小字母命名你的变量。常量应以“k”字母开头。

【讨论】:

谢谢大家,我是一个新手,我遇到了一些麻烦。你能帮我写代码吗?:) 特别是你第三个(3.)是我不知道的暂时弄清楚..你能把它写成代码吗。 例如,我不知道如何在 messageDetail 视图中显示消息(内容)的详细信息.. 请假设我刚刚问过这个问题:您好,在我的应用程序中,我向我的服务器发送了一个 GET 并收到了一些响应。我的主视图控制器类期望有 TavleView 和 TableViewController 类。我在我的主 ViewController 中进行解析,我想用我从第一个 ViewController 收到的结果填充 TableViewCells。而且我还想在一个名为 DetailViewController 的新 ViewController 中显示任何单元格的详细信息。现在,视图之间的任何导航都可以按照我的意愿工作

以上是关于如何使用来自不同 ViewController 的 JSON 响应填充 UITableView?的主要内容,如果未能解决你的问题,请参考以下文章