Parse.com返回空对象

时间:2015-05-16 19:43:48

标签: ios objective-c parse-platform

我有一个名为“malls”的NSArray,其中包含我上传到Parse.com的大量NSDictionaries(每个都是特定的商城)。我希望我的用户能够访问此信息以创建地图注释。

我试图以两种不同的方式做到这一点:

  1. 我尝试将整个数组上传为单个对象的属性:
  2. 这是上传:

    在dataBank.h文件中:

    @property (strong, nonatomic) NSMutableArray* malls;
    
    <。>文件中的

    PFObject *obj = [PFObject objectWithClassName:@"malls"];
    obj[@"mallsData"] = self.malls;
    [obj saveInBackground];
    

    我尝试从解析中获取数据:

    -(NSMutableArray *)createAnnotationsFromParse
    {
        __block NSMutableArray* data = [[NSMutableArray alloc]init];
        __block NSMutableArray* annots = [[NSMutableArray alloc]init];
    
    PFQuery* query = [PFQuery queryWithClassName:@"malls"];
    [query getObjectInBackgroundWithId:@"Eaib9yfTRe" block:^(PFObject *object, NSError *error) {
        data = [object objectForKey:@"mallsData"];
        annots = [self createAnnotations:data];
    }];
    
    return annots;
    }
    

    问题是getObjectInBackground是异步的,并且始终在从服务器获取数据之前返回。我尝试在代码块中移动“return annots”,但是会出现以下错误:“不兼容的块指针类型”。

    1. 我将5个“mall”对象上传到了“malls2”类。每个对象都有2个属性 - 名称和地址:

      for(int i = 0; i < 5; i++)
      {
          PFObject *mallsObj = [PFObject objectWithClassName:@"malls2"];
          mallsObj[name] = [[self.malls objectAtIndex:i]objectForKey:name];
          mallsObj[address] = [[self.malls objectAtIndex:i]objectForKey:address];
          [mallsObj saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
          if(succeeded)
              NSLog(@"yay");
          else
              NSLog(@"%@", error.description);
      }];
      

      }

    2. 然后我试着把它拿回来:

      -(NSMutableArray *)createAnnotationsFromParse
      {
          __block Annotation* anno = [[Annotation alloc]init];
          __block NSMutableArray* annots = [[NSMutableArray alloc]init];
      
          PFQuery* query = [PFQuery queryWithClassName:@"malls2"];
      
          [query findObjectsInBackgroundWithBlock:^(NSArray *objects,  NSError *error) {
              if(error)
                  NSLog(@"%@", error.description);
              else
              {
                  for(int i = 0; i < [objects count]; i++)
                  {
                          //createAnnotationWithTitle is a func in a different class that creates the annotation
                          anno = [anno createAnnotationWithTitle:[[objects objectAtIndex:i] objectForKey:name] andAddress:[[objects objectAtIndex:i]objectForKey:address]];
                  }
                  [annots addObject:anno];
              }
          }];
      
          return annots;
      }
      

      我得到了5个对象,但它们都是空的。

2 个答案:

答案 0 :(得分:0)

这是对使用块参数的异步方法的基本误解。诀窍是摆脱以后认为稍后在源文件中出现的代码运行的习惯。该假设适用于此函数:

- (void)regularFunction {
    // these NSLogs run top to bottom
    NSLog(@"first");
    NSLog(@"second");
    NSLog(@"third");
}

这将生成日志:第一,第二,第三。从上到下,但不是在这一个:

- (void)functionThatMakesAsynchCall {
    // these NSLogs do not run top to bottom
    NSLog(@"first");
    [someObject doSomeAsynchThing:^{
        NSLog(@"second");
    }];
    NSLog(@"third");
}

该函数将生成日志 - 第一,第三,第二。 “第二”NSLog将在“第三”之后运行良好。

那你该怎么办?在完成之前,不要尝试使用解析调用的结果更新UI,如下所示:

// declared void because we can't return anything useful
- (void)doSomeParseThing {
    // if you change the UI here, change it to say: "we're busy calling parse"
    PFQuery* query = [PFQuery queryWithClassName:@"malls2"];
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects,  NSError *error) {
        if(!error) {
            // change the UI here, say by setting the datasource to a UITableView
            // equal to the objects block parameter
        }
    }];

    // don't bother changing the UI here
    // don't bother returning anything here
    // we just started the request
}

但是,如果doSomeParseThing真的是一个模型函数,其唯一的工作是从解析中获取,而不是对UI有任何了解,该怎么办?这是一个非常合理的想法。要解决这个问题,您需要使用块参数:

来构建模型方法,就像解析构建它们的方法一样
// in MyModel.m
// declared void because we can't return anything useful
+ (void)doSomeParseThing:(void (^)(NSArray *, NSError *))block {
    PFQuery* query = [PFQuery queryWithClassName:@"malls2"];
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects,  NSError *error) {
        block(objects, error);
    }];
}

现在您的视图控制器可以调用,将查询工作留给您的模型,UI工作到vc:

// change UI to 'busy' here
[MyModel doSomeParseThing:^(NSArray *objects, NSError *error) {
    // update UI with objects or error here
}];

答案 1 :(得分:0)

想出来。看起来我得到的是空物#34; (可以在这里看到postimg.org/image/ot7ehn29b)但是一旦我试图从我看到的对象访问数据就没有问题了。基本上我被数组中的PFObjects欺骗了,显示了&#34; 0个对象&#34;并假设这意味着他们从Parse.com回来了。这是我查看的方式,仅供参考:

PFQuery *query = [PFQuery queryWithClassName:@"malls2"];
NSArray *array = [query findObjects];
NSLog(@"%@", [[array objectAtIndex:0] objectForKey:@"name"]; // I have a string property called "name" in my Parse object.