PFQueryTableView填充表视图时遇到麻烦

时间:2014-04-22 19:07:31

标签: ios parse-platform pfquery

我目前正在研究PFQueryTableView并试图让它填充来自ViewDidLoad的数组中的数据。更新:我已经将该函数移动到NSObject并实现了一个单例,用于跨多个类,以便远离视图控制器。以下是更新后的代码:

  + (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];

}

虽然函数内部的NSLog工作正常,但我的问题现在有点扩展了,我觉得我在这里遗漏了一些非常简单的东西。

当我到达@“TANK NAME ARRAY:%@”时......显然它返回null,因为它在处理查询的部分之外。如果我试图通过另一个类提供数据,这对我没有多大帮助。

过去几天我做了很多尝试,我无法想象我错过了一些非常复杂的东西。我很抱歉重新打开这个,但此时我无法绕过它。

关于如何处理这个问题的任何想法?我一如既往地感谢你的帮助。

2 个答案:

答案 0 :(得分:2)

可能还有其他问题,但确定这一行:

tableData = [NSArray arrayWithObjects:objects, nil];

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

tableData = objects;

关于如何继续的问题,我认为你可以在任何表视图控制器中继续这个类。通过引用tableData来回答表数据源方法(即countnumberOfRowsInSectiontableData[indexPath.row]来配置cellForRowAtIndexPath:等等。

答案 1 :(得分: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中查看解析数据。我建议你先建立一个像这样的东西(就像这样),然后才开始