2013-05-19 41 views
-1

我使用parse.com作为我的应用程序的后端。 我需要从我的后端获取信息并使用此信息初始化一个实例。 我用这个代码为了做到这一点:未从块内初始化的iOS实例变量

- (id) initWithTeamId:(NSString *)teamId 
{ 
__block NSString *str; 
__block FrFTeam *blockSelf = self; 
PFQuery *query = [PFQuery queryWithClassName:@"teams"]; 
[query getObjectInBackgroundWithId:teamId block:^(PFObject *object, NSError *error) { 
    str = [object objectForKey:@"teamName"]; 
    (void)[blockSelf initWithName:str players:nil thumb:nil]; 
}]; 

return self; 
} 

当这个代码做self.name设置为null, 我究竟做错了什么? 谢谢!

回答

0

试试这个代码:

// call init on the object, then setup the team id 
- (id)initWithTeamId:(NSString *)teamId 
{ 
    self = [super init]; 
    if (self) { 
     [self setupWithTeamId:teamId]; 
    } 

    return self; 
} 

- (void) setupWithTeamId:(NSString *)teamId 
{ 
    __weak FrFTeam *blockSelf = self; 

    PFQuery *query = [PFQuery queryWithClassName:@"teams"]; 
    [query getObjectInBackgroundWithId:teamId block:^(PFObject *object, NSError *error) { 
     NSString *name = [object objectForKey:@"teamName"]; 
     NSLog(@"Received name: %@ from object: %@", name, object); 
     [blockSelf setName:name]; 
    }]; 
} 

然后,将方法的名称从initWithName:...更改,因为这不是一个真正的init方法,因为在调用setupWithTeamId:之前已经完成init。

如果您需要解析位init方法返回之前完成,你应该:

  1. 呼叫解析对象
  2. 在初始化调用使用getObjectWithId:之前获得的细节---不推荐因为这会阻塞init中的线程,坏主意
+0

谢谢,在启动之后,这仍然不起作用:FrFTeam * tmpTeam = [[FrFTeam alloc] init];并使用你的方法:[tmpTeam setupWithTeamId:team.objectId];该名称仍然为空 –

+0

在调用该方法后立即它是无(应该是),因为完成处理程序最多安排在当前runloop的END处,所以没有办法让名称字段立即填充而没有阻塞请求。我的建议KVO,你可以听名字的变化(如果设置正确),并根据变化采取行动。 –

0

相当肯定的原因是您所呼叫-getObjectInBackgroundWithId:block:方法名(它指定InBackground,这表明该块被称为在以后的某个阶段,并立即不)

这表明,你最终。自==为零(你不是在调用该方法的任何其他初始化器

对象的初始化必须是同步

+0

有没有办法让数据异步,并且init同步? –

+0

只有在后台线程中处理init时,init本身必须是同步的。我注意到你将很多nils传递给你的初始化程序,甚至是需要初始化该对象的名称字符串?也许你可以初始化它,然后启动加载(异步),填充名称字段?这是其他答案在给出的代码中所做的。 –

+0

“这会建议你最终得到self == nil”否。如果你看看OP的代码,从'initWithTeamId:'方法返回的是'self',即它被调用的对象。不''无'。 – newacct