简体   繁体   中英

Passing a JSON string from one view to another

I have a table view where I parse some JSON data and display it in a custom cell. In one view I'm parsing posts from a specific user from Facebook.

I'm displaying a preview in the table view, but I want to pass the data to another view. For example, I read a preview of a post in the table view, but I want to read the whole post.

When I click on that post (cell) I should get directed to a new view controller where the full posts gets displayed (in a label or text view).

How can I do that?

Here's my code for parsing the data to the table view:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.


    strURLToLoad = [[NSMutableString alloc] init];

    [btnFaceBook setTitle:@"link.com/json.php?name=Name" forState:UIControlStateDisabled];
    [btnTwitter setTitle:@"link1.com/json.php?name=Name" forState:UIControlStateDisabled];
    [btnTwitter2 setTitle:@"link2.com/json.php?name=Name" forState:UIControlStateDisabled];

    [btnFaceBook setBackgroundImage:[UIImage imageNamed:@"tab_selected.png"] forState:UIControlStateNormal];
    [btnFaceBook setBackgroundImage:[UIImage imageNamed:@"tab_unselected.png"] forState:UIControlStateSelected];

    [btnTwitter setBackgroundImage:[UIImage imageNamed:@"tab_selected.png"] forState:UIControlStateNormal];
    [btnTwitter setBackgroundImage:[UIImage imageNamed:@"tab_unselected.png"] forState:UIControlStateSelected];

    [btnTwitter2 setBackgroundImage:[UIImage imageNamed:@"tab_selected.png"] forState:UIControlStateNormal];
    [btnTwitter2 setBackgroundImage:[UIImage imageNamed:@"tab_unselected.png"] forState:UIControlStateSelected];



    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"PostsObject" owner:self options:nil];
    PostsObject *cell = [nib objectAtIndex:0];
    fontForCellText = cell.title.font;
    cellTextWidth = cell.title.frame.size.width;
    cellHeightExceptText = cell.frame.size.height - cell.title.frame.size.height;

    [self.navigationController setNavigationBarHidden:YES];

    self.tableView.separatorColor = [UIColor clearColor];

    // Setting Up Activity Indicator View
    self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    self.activityIndicatorView.hidesWhenStopped = YES;
    self.activityIndicatorView.center = self.view.center;
    [self.view addSubview:self.activityIndicatorView];
    [self.activityIndicatorView startAnimating];
    self.tableView.separatorColor = [UIColor clearColor];

    // Initializing Data Source
    movies = [[NSMutableArray alloc] init];

    [self btnFromTabBarClicked:btnFaceBook];
}

- (void)loadJSONFromCurrentURL
{
    [self.activityIndicatorView startAnimating];

    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:strURLToLoad]];

    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        [movies setArray:JSON];
        [self.activityIndicatorView stopAnimating];
        [self.tableView reloadData];

    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
        NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo);
    }];

    [operation start];
}

- (IBAction)btnFromTabBarClicked:(UIButton *)sender
{
    //Unselect all 3 buttons
    btnFaceBook.selected = btnTwitter.selected = btnTwitter2.selected = NO;

    //Select the button that was clicked
    sender.selected = YES;

    //Set the string of an NSMutableString property called strURLToLoad with the URL
    //The URL is pre stored in the text of the UIButton in the Disabled text.
    [strURLToLoad setString:[sender titleForState:UIControlStateDisabled]];

    //Load the URL
    [self loadJSONFromCurrentURL];
}

// Table View Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (movies && movies.count) {
        return movies.count;
    } else {
        return 0;
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *simpleTableIdentifier = @"PostsObject";

    PostsObject *cell = (PostsObject *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
    if (cell == nil)
    {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"PostsObject" owner:self options:nil];
        cell = [nib objectAtIndex:0];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;

    }

    NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
    NSString *strText = [movie objectForKey:[self getTextKey]];

    CGRect rect = cell.title.frame;
    rect.size.height = [self getHeightForText:strText];
    cell.title.frame = rect;
    cell.title.text = strText;
    cell.arrow.center = CGPointMake(cell.arrow.frame.origin.x, rect.origin.y + rect.size.height/2);
    cell.published.text = [movie objectForKey:@"published"];
    cell.twitterName.text = [movie objectForKey:[self getTwitterName]];
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
    NSString *strText = [movie objectForKey:[self getTextKey]];

    CGFloat cellHeight = cellHeightExceptText + [self getHeightForText:strText];

    return cellHeight;
}

- (NSString *)getTextKey
{
    return btnTwitter.selected?@"tweet":@"message";
}

- (NSString *)getTwitterName
{
    return btnTwitter2.selected?@"user":@"user";
}

- (CGFloat)getHeightForText:(NSString *)strText
{
    CGSize constraintSize = CGSizeMake(cellTextWidth, MAXFLOAT);
    CGSize labelSize = [strText sizeWithFont:fontForCellText constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];
    NSLog(@"labelSize.height = %f",labelSize.height);
    return labelSize.height;
}

There are a number of ways to accomplish this.

You can implement tableview:didSelectRowAtIndexPath: and inside it, allocate the next VC and pass your data to its properties and then present that VC.

Or you can implement a segue from the table cell to the new VC and then in prepareForSegue: you pass your data to its properties.

Either way, the presented VC can then load the data into tis views via viewDidLoad .

As far as passing JSON around, it's not particularly optimal. You may think about creating your own objective-c based model objects that the JSON data gets parsed into and use these model objects in your app instead.

You can pass the appropriate data you want to the next view controller using your own init method. To show you this, I created a new view controller called NextViewController, and wrote my own custom init method that takes the dictionary as a parameter. I added this function to the header file so that it can be accessed by your original view controller and also added the dictionary as a property so you can access it throughout that file in the various functions (an instance variable would also work), imported the NextViewController's .h file into my original table view's file, and within the tableView's didSelectRowAtIndexPath function grabbed the selected object based on the indexPath from the data source array, in your case movies, and created a NextViewController instance passing in that dictionary through it's init function. Here is the relevant code:

NextViewController's .h file

@interface NextViewController : UIViewController

- (id)initWithDictionary:(NSDictionary *)dictionary;

@property (nonatomic, retain) NSDictionary *myDictionary;

@end

NextViewController's .m file:

@interface NextViewController ()

@end

@implementation NextViewController

- (id)initWithDictionary:(NSDictionary *)dictionary {
    self = [super initWithNibName:nil bundle:nil];

    self.myDictionary = dictionary;

    return self;
}

@end

Inside the original tableViewController:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // first deselect the cell so it doesn't stay highlighted
    [tableView deselectRowAtIndexPath:indexPath animated:YES];

    // then grab the json you want to pass from your tableView's datasource
    NSDictionary *selectedMovie = self.movies[indexPath.row];

    // create the nextViewController and pass in the appropriate dictionary to it
    NextViewController *nextVC = [[NextViewController alloc] initWithDictionary:selectedMovie];

    // then tell our navigation controller to push this new controller onto the view stack
    [self.navigationController pushViewController:nextVC animated:YES];
}

Let me know if this helps, or if you need further clarification.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM