iOS代表KVO的问题

时间:2012-10-01 23:19:05

标签: ios facebook delegates key-value-observing

我有一个发出请求的方法,并有一个委托响应者。该方法由KVO响应者调用。当我从viewDidLoad调用它时,代码工作正常,但是当我从KVO方法发出请求时,它不会触发委托方法。

这是我的KVO响应者:

//observe app delegates userdata to check for when user data is available or data is changed
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    if ([keyPath isEqualToString:@"userData"] )
    {
        //goto facebook logic
        [self FBFriendSuggester];
    }
}

及其调用的方法:

-(void)FBFriendSuggester
{
    NSDictionary * fb_credentials = nil;
    if([prefs objectForKey:@"facebookCredentials"])
    {
        fb_credentials = [prefs objectForKey:@"facebookCredentials"];
        if ([fb_credentials objectForKey:@"expiry"] && [fb_credentials objectForKey:@"fbtoken"]) {
            NSLog(@"found stored Facebook credentials.");
            ApplicationDelegate.facebook.accessToken = [fb_credentials objectForKey:@"fbtoken"];
            ApplicationDelegate.facebook.expirationDate = [fb_credentials objectForKey:@"expiry"];
        }
    }
    if ([ApplicationDelegate.facebook isSessionValid]) {
        printf("_valid facebook\n");
        [ApplicationDelegate.facebook requestWithGraphPath:@"me/friends" andDelegate:self];
    }else
        printf("_invalid facebook\n");
}

和委托方法:

- (void)request:(FBRequest *)request didLoad:(id)result{
    NSLog(@"result2:%@",result);

    NSDictionary * rawObject = result;
    NSArray * dataArray = [rawObject objectForKey:@"data"];

    for (NSDictionary * f in dataArray) {
        [friends addObject:[[KNSelectorItem alloc] initWithDisplayValue:[f objectForKey:@"name"]
                                                            selectValue:[f objectForKey:@"id"]
                                                               imageUrl:[NSString stringWithFormat:@"http://graph.facebook.com/%@/picture?type=square", [f objectForKey:@"id"]]]];
    }
    [friends sortUsingSelector:@selector(compareByDisplayValue:)];
    [self pickerPopup:self];
}

在这种情况下不会调用委托方法,但是当我直接从控制器调用 - (void)FBFriendSuggester时它确实可以正常工作。我不知道该怎么办,我试着设置一个通知回复,希望它会触发代表,但这也不起作用。

2 个答案:

答案 0 :(得分:1)

我知道这是相当陈旧的,但是为了说明发生这种情况的原因,KVO通知会在发生更改的线程上发送。因此,如果后台线程对AppDelegate上的属性进行了更改,则通知更改也将在后台线程上发生。

因此,在代码的上下文中,您的-(void)FBFriendSuggester最有可能在后台线程中被调用。您可以通过在代码中抛出断点并查看Debug Navigator来确认这一点。

我将继续假设这是真的(它在后台线程中运行)。

此调用[ApplicationDelegate.facebook requestWithGraphPath:@"me/friends" andDelegate:self];很可能需要在主线程上发生。原因可能是潜在的呼叫正在使用NSURLConnection进行呼叫。连接是在后台线程上进行的,但所有委托调用必须在主线程上进行,而不是后台线程。通过调用andDelegate:self,它将对象注册为后台线程上的委托,而不是主线程。

这就是您当前的解决方案解决该问题的原因。

快乐的编码!

答案 1 :(得分:0)

我能够通过发出以下方式解决我的问题:

[self performSelectorOnMainThread:@selector(FBFriendSuggester) withObject:nil waitUntilDone:NO];

很高兴知道为什么这样可以这样工作。