Iphone iOS实例变量未从块内初始化

Iphone iOS实例变量未从块内初始化,iphone,ios,objective-c,objective-c-blocks,parse-platform,Iphone,Ios,Objective C,Objective C Blocks,Parse Platform,我正在使用parse.com作为我的应用程序的后端。 我需要从后端获取信息,并使用此信息初始化实例。 我使用此代码来执行此操作: - (id) initWithTeamId:(NSString *)teamId { __block NSString *str; __block FrFTeam *blockSelf = self; PFQuery *query = [PFQuery queryWithClassName:@"teams"]; [query getObjectInBackgr

我正在使用parse.com作为我的应用程序的后端。 我需要从后端获取信息,并使用此信息初始化实例。 我使用此代码来执行此操作:

    - (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, 我做错了什么?
谢谢大家!

很确定原因在于您调用的方法名
-getObjectInBackgroundHithid:block:
(它指定InBackground,这表明该块是在稍后的某个阶段调用的,而不是立即调用的)


这将建议您以self==nil结束(因为您没有在方法中调用任何其他初始化器)

对象的初始化必须是同步的。

请尝试以下代码:

// 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方法返回之前完成解析位,则应:

  • 在对对象调用init之前,调用parse以获取详细信息
  • 不建议使用
    getObjectWithId:
    ——因为这会阻止init中的线程,这是个坏主意

  • 有没有一种方法可以使数据异步,并使init同步?只有在后台线程中处理init,但init本身必须是同步的。我注意到,您正在向初始值设定器传递大量的nil,初始化对象是否需要名称字符串?也许您可以先初始化它,然后启动loading(异步),它填充name字段?这是另一个答案在给定代码中所做的。“这表明您最终的self==nil”否。如果您查看OP的代码,则从
    initWithTeamId:
    方法返回的是
    self
    ,即调用它的对象。而不是
    nil
    。好的,是的,您有这个权利,self将返回。但是,blockSelf是在块中进行初始化的对象,并且从未使用该初始化的返回值,所以我认为最终目标仍然没有实现,在这种情况下self也可以==nil(除了为对象分配了内存)。我想我想说的是self!=一个完全初始化的self,它只是一个shell,根据NSObjects文档,还没有准备好使用。谢谢,在初始化:frftam*tmpTeam=[[frftam alloc]init];并使用您的方法:[tmpTeam setupWithTeamId:team.objectId]之后,这仍然不起作用;在调用该方法后,名称仍然为null。它是nil(并且应该是),因为完成处理程序最多安排在当前runloop的末尾,因此无法在不阻塞请求的情况下立即填充名称字段。我的建议是KVO,您可以听名称的更改(如果设置正确)并根据变化采取行动。