2015-07-27 8 views
2

Я пытаюсь выполнить следующий RxSwift пример:Facebook Войти с помощью RxSwift

Вход с использованием Вконтакте в моем приложении -> извлечения информации пользователя -> получить фотография профиля.

У меня есть эти три функции, и они должны быть выполнены в таком порядке: requestAccess() -> fetchUserInformation() -> fetchUserPhoto()

func requestAccess() -> Observable<(ACAccount)> { 
    return create { observer -> Disposable in 
     let accountStore = ACAccountStore() 
     let accountType = accountStore.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierFacebook) 
     let dictionary: [NSObject : AnyObject] = [ACFacebookAppIdKey:"***APPID***", ACFacebookPermissionsKey:["public_profile", "email", "user_friends"]] 

     accountStore.requestAccessToAccountsWithType(accountType, options: dictionary) { granted, error in 
      if granted == false || error != nil { 
       sendError(observer, error ?? UnknownError) 
      } else { 
       let accounts = accountStore.accountsWithAccountType(accountType) 
       let account = accounts.last as! ACAccount 
       sendNext(observer, account) 
       sendCompleted(observer) 
      } 
     } 

     return AnonymousDisposable({}) 
    } 
} 

func fetchUserInformation(account: ACAccount) -> Observable<User> { 
    return create { observer -> Disposable in 
     let url = NSURL(string: "https://graph.facebook.com/me") 
     let request = SLRequest(forServiceType: SLServiceTypeFacebook, requestMethod: .GET, URL: url, parameters: nil) 
     request.account = account 

     request.performRequestWithHandler { (data, response, error) -> Void in 
      if data == nil || response == nil { 
       sendError(observer, error ?? UnknownError) 
      } else { 
       let result: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) 
       let user = User() 
       user.updateInformationWithJSON(result! as! JSONObject) 

       sendNext(observer, user) 
       sendCompleted(observer) 
      } 
     } 

     return AnonymousDisposable({}) 
    } 
} 

func fetchUserPhoto(user: User) -> Observable<AnyObject> { 
    return create { observer -> Disposable in 
     let url = NSURL(string: "https://graph.facebook.com/***myid***/picture") 
     let params = ["redirect":"false", "height":"200", "width":"200"] 

     let request = SLRequest(forServiceType: SLServiceTypeFacebook, requestMethod: .GET, URL: url, parameters: params) 
     request.account = SocialController.account 

     request.performRequestWithHandler { (data, response, error) -> Void in 
      if data == nil || response == nil { 
       sendError(observer, error ?? UnknownError) 
      } else { 
       let result: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil)      
       sendNext(observer, result!) 
       sendCompleted(observer) 
      } 
     } 

     return AnonymousDisposable({}) 
    } 
} 

Я уже пытался реализовать этот поток, но это не делает хорошо чувстовать. Каков наилучший способ решить эту проблему?

 requestAccess() 
     >- subscribeNext { account in 
      fetchUserInformation(account) 
       >- map { user in return UserViewModel(model: user) } 
       >- subscribeNext { viewModel in self.viewModel = viewModel } 
     } 

ответ

4

Вы пытались использовать flatMap? Это эквивалент then в синей птице или мире Q. Разница между map и flatMap заключается в том, что flatMapдолжен вернуть Observable<T>, который затем будет развернут в следующем блоке/закрытии.

requestAccess() 
    >- flatMap{ account in 
     return fetchUserInformation(account) 
    } 
    >- map { user in 
     return UserViewModel(model:user) 
    } 
    >- subscribeNext { viewModel in 
     self.viewModel = viewModel 
    } 

Tidbit # 1: Рассмотрите возможность использования unowned self при обращении self, чтобы избежать сохранения цикла.

Tidbit # 2: Эти два являются почти тем же самым.

flatMap { return just("hello") } 
    >- subscribeNext{ greeting in println(greeting) } 

map { return "hello" } 
    >- subscribeNext{ greeting in println(greeting) } 
+0

Thanks Max Alexander! Ваше решение решает мою проблему :) –

+1

Нет проблем! Я обнаружил, что добавление «rx_» в качестве префикса к вашим методам - ​​хорошая идея, поэтому вы знаете, что этот метод будет обертывать ваше возвращаемое значение как наблюдаемое. Вместо 'fetchInformation', я называю его' rx_fetchInformation'. Это помогает, когда у вас много методов «flatMap». –