Попълване на моя модел от данни във Facebook (‹FBGraphUser›)

Създадох модел, наречен User, който има свойство "име".

Правя заявка към API на facebook (използвайки най-новия SDK за iOS), идеята е да задам свойството ми user.name, когато facebook върне данните.

Facebook връща данните в блока startWithCompletionHandler, но не мога да задам тези данни на моя потребителски обект, имам достъп само до данните на startWithCompletionHandler. Когато се опитам да получа достъп до данните извън блока, моят модел връща NULL.

Как мога да попълня моя модел/обект, когато се върне заявка за facebook?

Текущата ми реализация на метода:

+ (void)requestUserData:(User *)userModel {
    if(FBSession.activeSession.isOpen) {
     [[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
       if(user.name) [self setUserData:user userModel:userModel];
     }];
   }
}

 + (void)setUserData:(NSDictionary<FBGraphUser> *)user userModel:(User *)userModel {
     userModel.name = user.name;
 }

И обаждането:

   __block User *user = [[User alloc] init];
   [GFFacebookHelpers requestUserData:user];
   NSLog(@"user: %@", user.name); //this part prints 2013-06-06 18:03:43.731 FacebookClassTest[74172:c07] user: (null)

Благодаря.


person GodFather    schedule 06.06.2013    source източник
comment
Опитвате ли се да картографирате FBGraphUser данните към вашия модел или просто имате name свойство на вашия модел?   -  person Daniel    schedule 07.06.2013
comment
В момента за тест имам само свойството name, но след като този въпрос бъде решен, ще разширя моя модел, за да съхранявам основните данни на потребителя във Facebook   -  person GodFather    schedule 07.06.2013


Отговори (1)


SDK на Facebook извлича асинхронно, така че манипулаторът за завършване, който сте написали, се изпълнява, след като вашият помощен метод се върне.

Така че, когато вашият метод връща вашия потребителски обект, той логично е само празен потребител (тъй като вече сте го разпределили/инициирали).

Когато се извика блокът за завършване, този потребителски обект се актуализира, но към този момент вече не го обработвате в приложението си (контролер за преглед).

И така, ето моето предложение: или използвайте Facebook SDK по-директно от вашите контролери за изглед, или ако искате да запазите цялата тази логика във вашия помощен клас, тогава го променете, така че вашият метод да не връща данни, но изисква блок, който ще бъде извикан, когато заявката за данни приключи, нещо по-подобно на това:

+ (void)requestUserDataWithCompletionHandler:(void (^)(User *user, NSError *error))handler{
    if(FBSession.activeSession.isOpen) {        
        [[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
            if(!error){
                User *userData = [[User alloc] init];
                userData.name = user.name;

                dispatch_async(dispatch_get_main_queue(), ^{
                    handler(userData, nil);
                });
            }
            else{
                dispatch_async(dispatch_get_main_queue(), ^{
                    handler(nil, error);
                });
            }
        }];
    }
}

Забележка: Увих извикването на блока за манипулиране в dispatch_async() към главната опашка, за да съм сигурен, че сте готови да актуализирате всеки потребителски интерфейс.

Методът на вашия контролер за преглед сега ще изглежда така:

- (void)updateStatusLabels {
    if([GFFacebookHelpers isLogged]){
        [GFFacebookHelpers requestUserDataWithCompletionHandler:^(User *user, NSError *error) {
            if(!error){
                self.fbStatus.text = user.name;
                [_loginButton setTitle:@"Logout" forState:UIControlStateNormal];
            }
        }];
    }else{
        self.fbStatus.text = @"You need to login";

        [_loginButton setTitle:@"Login" forState:UIControlStateNormal];
    }
}
person Daniel    schedule 06.06.2013
comment
Даниел, направих грешка в моя пример за кодов фрагмент. Настройвам userModel.name по този начин: userModel.name = user.name без цикъл. Поправих това в май пост. Вече внедрих вашия код за предложение, но продължавам да получавам NULL, когато се обадя на __block User *user = [[User alloc] init]; [GFFacebookHelpers requestUserData:user]; NSLog(@"user: %@", user.name); - person GodFather; 07.06.2013
comment
Ако имате демо проект, който мога да изтегля, ще се радвам да го разгледам много по-отблизо. - person Daniel; 07.06.2013
comment
Даниел, сложих демонстрацията, където работя тук: git://github.com/godfather/facebookclasstest.git останете свободни да променяте каквото искате. PS.: Направих някои промени след последния пример, който публикувах тук Благодаря - person GodFather; 07.06.2013
comment
Разклоних вашето репо и промених някои неща и създадох заявка за изтегляне, която да разгледате. По принцип вашият блок за завършване на заявка се задейства, след като методът бъде върнат, разбира се, защото Facebook SDK асинхронно извлича данни. Затова добавих блок за обратно извикване към вашия метод. Сега се чувства като обвивка върху обвивка... но поне можете да обработвате грешки в данните в помощния клас и да запазите отговорността на контролерите за изглед за показване/скриване на части от приложението ви според успеха/неуспеха. Моля, разгледайте вашето репо. Тук също ще актуализирам отговора си. - person Daniel; 07.06.2013