我有一个名为“malls”的NSArray,其中包含我上传到Parse.com的大量NSDictionaries(每个都是特定的商城)。我希望我的用户能够访问此信息以创建地图注释。
我试图以两种不同的方式做到这一点:
这是上传:
在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”,但是会出现以下错误:“不兼容的块指针类型”。
我将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);
}];
}
然后我试着把它拿回来:
-(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个对象,但它们都是空的。
答案 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.