0

I'm currently working on a PFQueryTableView and trying to get it to populate with data from an array that's pulled from ViewDidLoad. UPDATE: I've moved the function to an NSObject and implemented a singleton to be used across multiple classes in an effort to silo the operation away from the view controller. Below is the updated code:

  + (NSArray *)savedTankArray
{
    PFUser *userName = [PFUser currentUser];
    NSString *userNameString = [userName objectForKey:@"username"];


    PFQuery *query = [[PFQuery alloc] initWithClassName:@"SavedTanks"];
    [query whereKey:@"userName" equalTo:userNameString];
    [query setValue:@"SavedTanks" forKeyPath:@"parseClassName"];

    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
     {
         if (!error)
         {
             // The find succeeded.
             NSLog(@"Successfully retrieved %lu Tanks.", objects.count);
             // Do something with the found objects
             for (PFObject *object in objects)
             {
                 NSString *tankNameString = [[NSString alloc] init];
                 NSString *tankCapacityString = [[NSString alloc] init];

                 tankNameString = [object valueForKey:@"tankName"];
                 tankCapacityString = [object valueForKey:@"tankCapacity"];

                 NSLog(@"%@", tankNameString);
                 NSLog(@"%@", tankCapacityString);

                 _savedTankArray = [objects objectAtIndex:0];

             }
         }
         else
         {
             // Log details of the failure
             NSLog(@"Error: %@ %@", error, [error userInfo]);
         }
     }];
NSLog(@"TANK NAME ARRAY: %@", _savedTankArray);
return [_savedTankArray savedTankObjects];

}

While the NSLogs inside of the function work just fine, my problem is a bit expanded now, and I feel as though I'm missing something really simple here.

By the time I get to @"TANK NAME ARRAY: %@"... obviously it's returning null because its outside of the portion that handles the query. This doesn't help me much if I'm trying to bring the data in through another class.

I've tried so much over the past few days and I can't imagine I'm missing something terribly complex. I'm sorry for re-opening this but I can't wrap my head around it at this time.

Any ideas on how I could handle this? I appreciate the help as always.

4

2 回答 2

2

可能还有其他麻烦,但可以肯定的是这一行:

tableData = [NSArray arrayWithObjects:objects, nil];

是一个错误。这将创建一个单元素数组,其第一个元素是结果数组。我认为您可以修复和简化为:

tableData = objects;

对于您关于如何进行的问题,我认为您可以像在任何表格视图控制器中那样继续上课。参照tableData回答表数据源方法(即countfor :,配置一个: numberOfRowsInSection,以此类推)。tableData[indexPath.row]cellForRowAtIndexPath

于 2014-04-22T23:00:24.763 回答
1

编辑后的新问题的新答案:

似乎混淆与调用异步服务有关。我在这里给出两种建议。首先,最简单的包含表的视图控制器,它从异步服务获取数据,其次,包装解析异步服务的小类。首先是VC:

// in a vc with a table view .m
@interface MyViewController ()
@property(weak,nonatomic) IBOutlet UITableView *tableView;
@property(strong,nonatomic) NSArray *array;  // this class keeps the array
@end

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [ClassThatHandlesMyQuery doQuery:^(NSArray *results) {
        self.array = results;
        [self.tableView reloadData];
    }];
}

看看其他类中的查询类方法如何接受块参数?这是必需的,因为查询是异步发生的。

// do the normal table view stuff
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.array.count;
}

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

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    PFObject *pfObject = self.array[indexPath.row];
    cell.textLabel.text = [pfObject valueForKey:@"someStringProperty"];
    return cell;
}

这应该是你在vc中需要的几乎所有东西。现在让我们看看你的查询方法。它犯了三个错误:(a)没有让调用者获得异步结果的块参数,(b)它在查询完成块中错误处理了数组,(c)在方法结束时,它错误地假设了一个变量_savedTankArray被初始化,在块中。该代码出现在块下方,但它实际上在块运行之前运行。\

让我们解决所有三个问题。首先声明一个公共方法:

// ClassThatHandlesMyQuery.h
+ (void) doQuery:(void (^)(NSArray *))completion;

看看它是如何将一个块作为参数的?现在实施:

// ClassThatHandlesMyQuery.m
+ (void) doQuery:(void (^)(NSArray *))completion {

    // your query code.  let's assume this is fine
    PFUser *userName = [PFUser currentUser];
    NSString *userNameString = [userName objectForKey:@"username"];


    PFQuery *query = [[PFQuery alloc] initWithClassName:@"SavedTanks"];
    [query whereKey:@"userName" equalTo:userNameString];
    [query setValue:@"SavedTanks" forKeyPath:@"parseClassName"];

    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error) {
           // the job is MUCH simpler here than your code supposed.
           // log the result for fun
           NSLog(@"did we get objects? %@", objects);

           // hand it back to the caller
           // notice there's no array kept in this class.  it's not needed
           // and it would be awkward to do it at the class (not instance) level
           completion(objects);
        } else {
            NSLog(@"bad news from parse: %@", error);
            completion(nil);
        }
    }
    // this is important
    NSLog(@"hi mom!");
    // watch your log output.  'hi mom' will appear before either message
    // from the block.  why is that?  because that block runs later
    // after the network request completes.  but the hi mom NSLog runs
    // just before the network request starts.  this is why it's wrong to expect
    // any variable set in the block to be initialized here
}

信不信由你,就是这样。您应该能够准确地编写迷你视图控制器类和迷你查询类,如此处所述,并在 UITableView 中查看来自 parse 的数据。我建议你首先构建这样的东西(完全像这样)只是为了开始

于 2014-04-24T07:14:11.730 回答