简体   繁体   中英

How to Use Relational Queries Parse iOS to populate a UITableView?

I'm developing a social app and have some problems with populating objects from parse created in a selected cell.

The Home screen is a UITableViewController, populates an array of objects stored in Parse, when a user taps a cell, a new scene DetailViewController will be pushed, which shows the object from the selected cell in a view.

Next, I created in DetailViewController a UIButton to add objects to a new class called "replies" and also have added into the DetailViewController scene, a TableView which is populated using a new array from those objects at the "replies" class.

I want to retrieve just the objects created on the selected cell :( At the moment everything works fine except on the DetailViewController scene the TableView will show all the objects created in the "replies" class no matter on which cell I tap.

I wonder how would I store an array from the selected cell so I can populate the objects that have been created at that selected cell... I believe that I could solve this issue with relational queries from parse at the retrieve from parse method.

Would Appreciate Very Much Any Help.

.h file

#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#import <ParseUI/ParseUI.h>
#import "GroundTableViewCell.h"
#import "TimelineTableViewController.h"

@interface DetailViewController : UIViewController<
UITableViewDataSource,
UITableViewDelegate,
NSObject>
{
}

@property (strong, nonatomic) IBOutlet UITableView *detailTableView;
@property (strong, nonatomic) IBOutlet UITextView *TextField;
@property (nonatomic, strong) PFObject *groUnds;
@property (strong, nonatomic) IBOutlet UITextView *replyTextView;
- (IBAction)sendReply:(id)sender;

@end

.m file

#import "DetailViewController.h"
#import <Parse/Parse.h>
#import "GroundTableViewCell.h"
#import "TimelineTableViewController.h"

@interface DetailViewController ()
@property(strong)NSMutableArray* repliesMutableArray;

@end

@implementation DetailViewController

@synthesize groUnds;
@synthesize TextField;
@synthesize detailTableView;
@synthesize repliesMutableArray;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    PFUser *currentUser = [PFUser currentUser];
    if (currentUser) {
        // do stuff with the user
    } else {
        // show the signup or login screen
    }

    // Do any additional setup after loading the view.
//      [self performSelector:@selector(retrieveFromParse)];
//    repliesArray = [[NSArray alloc] initWithObjects:@"comment", nil];

       [self performSelector:@selector(retrieveFromParse)];

    // Set the Label text with the selected detail.
    self.TextField.text = [self.groUnds objectForKey:@"comment"];
}

- (void) retrieveFromParse {
    PFQuery *retrieveReplies = [PFQuery queryWithClassName:@"Replies"];

  // This is the part where im not really sure how to query...
 // if uncommented won't show any objects at all now shows all the objects from the "Replies class" -->
  //  [retrieveReplies whereKey:@"comment" equalTo:groUnds];
    [retrieveReplies orderByDescending:@"createdAt"];

    [retrieveReplies findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error) {
            repliesMutableArray = [[NSMutableArray alloc] initWithArray:objects];
        }
        [detailTableView reloadData];
    }];
}

//*********************Setup table of folder names ************************
//get number of sections in tableview
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 1;
}

//get number of rows by counting number of folders
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return [repliesMutableArray count ];
}

//setup cells in tableView
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"replyCell";
    GroundTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    PFObject *tempObject = [repliesMutableArray objectAtIndex:indexPath.row];
    cell.cellTitle.text = [tempObject objectForKey:@"commentReplies"];

    return cell;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

 //reply button
- (IBAction)sendReply:(id)sender {
    //1
    //Add the image to the object, and add the comment and the user
    PFObject *Reply = [PFObject objectWithClassName:@"Replies"];
    [Reply setObject:[PFUser currentUser].username forKey:@"user"];
    [Reply setObject:self.replyTextView.text forKey:@"commentReplies"];
    //2
    [Reply saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
        //3
        if (succeeded){
            //Go back to the wall
            [self.navigationController popViewControllerAnimated:YES];
        }
        else{
            NSString *errorString = [[error userInfo] objectForKey:@"error"];
            UIAlertView *errorAlertView = [[UIAlertView alloc] initWithTitle:@"Error" message:errorString delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
            [errorAlertView show];
        }
    }];
}

@end

Overview

The basic structure of passing information between view controllers is that you need to set the data you want to display in the Detail View Controller (DVC) while you are in the main view controller (MVC). So on the delegate method in the MVC which is called when you select a cell (didSelectRowAtIndexPath) you can get the data specific to the selected cell and place it into a variable. Inside of the prepareForSegue... method you can set that data to be a variable on the dvc that represents your tableview data.

Passing Data Between View Controllers

To see how to properly pass data between view controllers look at the answers to this highly rated question on SO.

You can think of this as a push instead of pull. Data should be added to a property on the DVC before the view is presented. There are a number of ways to limit the data using NSPredicates, SubQueries, Related Queries or Queries on Array Values:

Queries on Array Values

For keys with an array type, you can find objects where the key's array value contains 2 by:

// Find objects where the array in arrayKey contains 2.
// Using PFQuery
[query whereKey:@"arrayKey" equalTo:@2];

// Or using NSPredicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"2 IN arrayKey"];
PFQuery *query = [PFQuery queryWithClassName:@"MyClass" predicate:predicate];

( more Parse Queries )

Keep in mind that you can also handle this problem of refining the data by using Apple API solutions to refine the data you add onto the DVC property. You mentioned that you are new so please make sure you have read and completed the tutorial on the getting started link below. It's important because it shows Apple's paradigm for handling data movement in iOS.

Getting Started

Please review the getting started guide if the explanation doesn't make sense. There are critical concepts that cannot be glossed over or easily explained in the context of this answer.

Proposed Resolution

Pass in the indexPath.row of the selected cell to detail view controller so that you can limit the results of the array to that cell. If the indexPath row is not useful for this purpose then just pass a value that will limit the results to something unique within the selected cell. Use the delegate method didSelectRowAtIndexPath on your tableview delegate to set a relevant data value that you pass to the object managing the underlying tableview on the detail scene. You will want to identify a "where-clause" that is appropriate to the data you want to show in the DVC and then use either a new query or an nspredicate to limit the results from your array of data. Search SO for examples of each of these concepts.

Hopefully these tips will help you to find the ultimate answer. Searching SO will give you examples that you then need to apply to your specific situation. However, I really recommend that you step back for a moment to make sure you understand how to pass data between view controllers correctly.

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