{"id":273998,"date":"2016-02-10T14:05:03","date_gmt":"2016-02-10T11:05:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=273998"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=273998","title":{"rendered":"RxSwift \u0432 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438 \u2014 \u043f\u0438\u0448\u0435\u043c \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435"},"content":{"rendered":"<p>       \u0415\u0441\u043b\u0438 \u0432\u0435\u0440\u0438\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c \u0442\u0435\u043d\u0434\u0435\u043d\u0446\u0438\u044f\u043c, \u0442\u043e FRP \u043d\u0430\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u0431\u043e\u0440\u043e\u0442\u044b \u0438 \u043d\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f. \u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u043d\u044b\u043c FRP \u2014 <a href=\"http:\/\/reactivex.io\/\">ReactiveX<\/a>, \u0438 \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0434\u043b\u044f Swift \u2014 <a href=\"https:\/\/github.com\/ReactiveX\/RxSwift\">RxSwift<\/a>. \u041d\u0430 \u0425\u0430\u0431\u0440\u0435 \u0443\u0436\u0435 \u0431\u044b\u043b\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f <a href=\"https:\/\/habrahabr.ru\/post\/273455\/\">\u0441\u0442\u0430\u0442\u044c\u044f<\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f RxSwift. \u042f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0440\u0430\u0437\u0432\u0438\u0442\u044c \u044d\u0442\u0443 \u0442\u0435\u043c\u0443, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u0432\u0448\u0438\u043c\u0441\u044f \u2014 \u0434\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434 \u043a\u0430\u0442!<\/p>\n<h4>\u041b\u0438\u0445\u0430 \u0431\u0435\u0434\u0430 \u043d\u0430\u0447\u0430\u043b\u043e<\/h4>\n<p>  \u0418 \u044d\u0442\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0442\u0430\u043a. \u0421\u0430\u043c\u043e\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0435, \u0441 \u0447\u0435\u043c \u043c\u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u0442\u044c\u0441\u044f \u2014 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u0434\u0440\u0443\u0433\u043e\u0435 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430. \u0421 \u043c\u043e\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c \u0438\u043c\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u044b\u043b\u043e \u0442\u044f\u0436\u0435\u043b\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043d\u043e\u0432\u044b\u0439 \u043b\u0430\u0434. \u041d\u043e \u0447\u0443\u0442\u044c\u0451 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u043e \u043c\u043d\u0435, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u043c \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f; \u0443 \u043c\u0435\u043d\u044f \u0443\u0448\u043b\u043e 2 \u043d\u0435\u0434\u0435\u043b\u0438 <s>\u043f\u0430\u043d\u0438\u043a\u0438<\/s> \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u0432 \u0441\u0443\u0442\u044c ReactiveX \u0438 \u044f \u043d\u0435 \u0436\u0430\u043b\u0435\u044e \u043e \u043f\u043e\u0442\u0440\u0430\u0447\u0435\u043d\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0440\u0430\u0437\u0443 \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0434\u0438\u0442\u044c \u2014 \u0441\u0442\u0430\u0442\u044c\u044f \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u0432 ReactiveX, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a Observable, Subscriber \u0438 \u0442.\u0434.<\/p>\n<p>  \u0418\u0442\u0430\u043a, \u043d\u0430\u0447\u043d\u0435\u043c. <a name=\"habracut\"><\/a>\u0411\u0443\u0434\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u0443\u044e \u0447\u0438\u0442\u0430\u043b\u043a\u0443 \u0441\u0432\u043e\u0435\u0439 \u0441\u0442\u0435\u043d\u044b \u0441 Facebook. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f <a href=\"https:\/\/github.com\/ReactiveX\/RxSwift\">RxSwift<\/a>, <a href=\"https:\/\/github.com\/Hearst-DD\/ObjectMapper\">ObjectMapper<\/a> \u0434\u043b\u044f \u043c\u0430\u043f\u043f\u0438\u043d\u0433\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, <a href=\"https:\/\/github.com\/facebook\/facebook-ios-sdk\">Facebook iOS SDK<\/a> \u0438 <a href=\"https:\/\/github.com\/jdg\/MBProgressHUD\">MBProgressHUD<\/a> \u0434\u043b\u044f \u0438\u043d\u0434\u0438\u043a\u0430\u0446\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442 \u0432 XCode, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043a \u043d\u0435\u043c\u0443 \u0432\u044b\u0448\u0435\u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 (\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <a href=\"https:\/\/cocoapods.org\/\">CocoaPods<\/a>), \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0441\u0432\u044f\u0437\u043a\u0443 \u0441 Facebook \u043f\u043e <a href=\"https:\/\/developers.facebook.com\/docs\/ios\/getting-started\">\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438<\/a> \u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043a\u043e\u0434\u0438\u043d\u0433\u0443.<\/p>\n<h4>\u042d\u043a\u0440\u0430\u043d \u043b\u043e\u0433\u0438\u043d\u0430<\/h4>\n<p>  \u0418\u0437\u043e\u0431\u0440\u0435\u0442\u0430\u0442\u044c \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434 \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c, \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u043c \u043f\u043e \u0446\u0435\u043d\u0442\u0440\u0443 \u044d\u043a\u0440\u0430\u043d\u0430 \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443 \u043e\u0442 Facebook \u2014 FBSDKLoginButton:<\/p>\n<pre><code class=\"objectivec\">let loginButton = FBSDKLoginButton() loginButton.center = self.view.center loginButton.readPermissions = [&quot;user_posts&quot;] loginButton.delegate = self <\/code><\/pre>\n<p>  \u041d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430 FBSDKLoginButtonDelegate \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043a\u0438 \u043b\u043e\u0433\u0438\u043d\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430:<\/p>\n<pre><code class=\"objectivec\">\/\/ MARK: Facebook Delegate Methods func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {         if ((error) != nil) {             \/\/ Process error             let alert = UIAlertController(title: &quot;\u041e\u0448\u0438\u0431\u043a\u0430&quot;, message: error.localizedDescription, preferredStyle: .Alert)             alert.addAction(UIAlertAction(title: &quot;OK&quot;, style: .Cancel, handler: nil))             self.presentViewController(alert, animated: true, completion: nil)         }         else if result.isCancelled {             let alert = UIAlertController(title: &quot;\u041e\u0448\u0438\u0431\u043a\u0430&quot;, message: &quot;Result is cancelled&quot;, preferredStyle: .Alert)             alert.addAction(UIAlertAction(title: &quot;OK&quot;, style: .Cancel, handler: nil))             self.presentViewController(alert, animated: true, completion: nil)         }         else {             let storyboard = UIStoryboard(name: &quot;Main&quot;, bundle: nil)             let vc = storyboard.instantiateViewControllerWithIdentifier(&quot;navController&quot;) as! UINavigationController             self.presentViewController(vc, animated: true, completion: nil)         }     }          func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {         print(&quot;User Logged Out&quot;)     } <\/code><\/pre>\n<p>  \u0422\u0443\u0442 \u0432\u0441\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u2014 \u0435\u0441\u043b\u0438 \u043e\u0448\u0438\u0431\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u0438\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0436\u0430\u043b \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u041e\u0442\u043c\u0435\u043d\u0430\u00bb \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 Facebook, \u0442\u043e \u0432\u044b\u0432\u043e\u0434\u0438\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u0432 \u0432\u0438\u0434\u0435 alert&#8217;\u0430, \u0430 \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u043e\u043a \u2014 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u044d\u043a\u0440\u0430\u043d \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u043d\u043e\u0432\u043e\u0441\u0442\u0435\u0439. \u0424\u0443\u043d\u043a\u0446\u0438\u044e \u043b\u043e\u0433\u0430\u0443\u0442\u0430 \u044f \u043d\u0435 \u0441\u0442\u0430\u043b \u0442\u0440\u043e\u0433\u0430\u0442\u044c. \u041a\u0430\u043a \u043c\u044b \u0432\u0438\u0434\u0438\u043c, \u043f\u043e\u043a\u0430 \u0432\u0441\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u043e \u0438 \u043d\u0438 \u043e \u043a\u0430\u043a\u043e\u0439 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u0440\u0435\u0447\u0438 \u043d\u0435 \u0438\u0434\u0435\u0442. \u0422\u0443\u0442 \u0442\u043e\u0436\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u043e\u043d\u043a\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u2014 <s>\u043d\u0435 \u0441\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u0432\u043e \u0432\u0441\u0435 \u0449\u0435\u043b\u0438<\/s> \u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043f\u0440\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f <a href=\"https:\/\/ru.wikipedia.org\/wiki\/KISS_(%D0%BF%D1%80%D0%B8%D0%BD%D1%86%D0%B8%D0%BF)\">KISS<\/a>.<\/p>\n<h4>\u042d\u043a\u0440\u0430\u043d \u043d\u043e\u0432\u043e\u0441\u0442\u0435\u0439<\/h4>\n<p>  \u041d\u0430\u043f\u0438\u0448\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u043d\u043e\u0432\u043e\u0441\u0442\u0435\u0439 \u0441\u043e \u0441\u0442\u0435\u043d\u044b Facebook, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0439 \u0442\u0438\u043f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 Observable:<\/p>\n<pre><code class=\"objectivec\">func getFeeds() -&gt; Observable&lt;GetFeedsResponse&gt; {         return Observable.create { observer in             let parameters = [&quot;fields&quot;: &quot;&quot;]             let friendsRequest = FBSDKGraphRequest.init(graphPath: &quot;me\/feed&quot;, parameters: parameters, HTTPMethod: &quot;GET&quot;)             friendsRequest.startWithCompletionHandler { (connection, result, error) -&gt; Void in                 if error != nil {                     observer.on(.Error(error!))                 } else {                     let getFeedsResponse = Mapper&lt;GetFeedsResponse&gt;().map(result)!                     observer.on(.Next(getFeedsResponse))                     observer.on(.Completed)                 }             }                          return AnonymousDisposable {                              }        } } <\/code><\/pre>\n<p>  \u0427\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u044d\u0442\u043e\u043c \u043a\u043e\u0434\u0435? \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 FBSDKGraphRequest \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0441\u0442\u0435\u0439 \u00abme\/feed\u00bb, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043c\u044b \u043e\u0442\u0434\u0430\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u043c \u0441\u0442\u0430\u0442\u0443\u0441 \u0432 \u0431\u043b\u043e\u043a\u0435 completition; \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0435\u0451 \u0432 Observable, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0441\u043f\u0435\u0445\u0430 \u2014 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0432 Observable \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<p>  <b>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/b> \u044f \u043f\u0435\u0440\u0435\u0434\u0430\u044e \u0432 FBSDKGraphRequest \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <\/p>\n<pre><code class=\"objectivec\">let parameters = [&quot;fields&quot;: &quot;&quot;]<\/code><\/pre>\n<p> \u0441 \u043f\u0443\u0441\u0442\u044b\u043c \u043d\u0430\u0431\u043e\u0440\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432. \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b Facebook \u043d\u0435 <s>\u043f\u043b\u0430\u043a\u0430\u043b<\/s> \u0432\u044b\u0432\u043e\u0434\u0438\u043b \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f \u0432 \u043b\u043e\u0433\u0430\u0445 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u043e\u043b\u0435 fields \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u0445 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c. \u0412 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435, \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0431\u0435\u0437 \u044d\u0442\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430, \u043d\u043e \u043c\u043d\u0435 \u0442\u0430\u043a \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u0435\u0439 \u0441\u043f\u0438\u0442\u0441\u044f.<\/p>\n<p>  \u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0442\u043e\u0439\u0434\u0435\u043c \u043e\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e \u043c\u0430\u043f\u043f\u0438\u043d\u0433\u0435 \u0434\u0430\u043d\u043d\u044b\u0445. \u042f \u0440\u0435\u0448\u0430\u044e \u044d\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ObjectMapper, \u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u0438 \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<pre><code class=\"objectivec\">class GetFeedsResponse: Mappable {          var data = [Feed]()     var paging: Paging!          required init?(_ map: Map){              }          \/\/ Mappable     func mapping(map: Map) {         data &lt;- map[&quot;data&quot;]         paging &lt;- map[&quot;paging&quot;]     }      }  class Feed: Mappable {          var createdTime: String!     var id: String!     var story: String?     var message: String?          required init?(_ map: Map){              }          \/\/ Mappable     func mapping(map: Map) {         createdTime &lt;- map[&quot;created_time&quot;]         id &lt;- map[&quot;id&quot;]         story &lt;- map[&quot;story&quot;]         message &lt;- map[&quot;message&quot;]     }      }  class Paging: Mappable {          var next: String!     var previous: String!          required init?(_ map: Map){              }          \/\/ Mappable     func mapping(map: Map) {         next &lt;- map[&quot;next&quot;]         previous &lt;- map[&quot;previous&quot;]     }      } <\/code><\/pre>\n<p>  \u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0441\u0440\u0430\u0437\u0443 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043d\u043e\u0432\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"objectivec\">func getFeedInfo(feedId: String) -&gt; Observable&lt;GetFeedInfoResponse&gt; {         return Observable.create { observer in             let parameters = [&quot;fields&quot; : &quot;id,admin_creator,application,call_to_action,caption,created_time,description,feed_targeting,from,icon,is_hidden,is_published,link,message,message_tags,name,object_id,picture,place,privacy,properties,shares,source,status_type,story,story_tags,targeting,to,type,updated_time,with_tags&quot;]             let friendsRequest = FBSDKGraphRequest.init(graphPath: &quot;&quot; + feedId, parameters: parameters, HTTPMethod: &quot;GET&quot;)             friendsRequest.startWithCompletionHandler { (connection, result, error) -&gt; Void in                 if error != nil {                     observer.on(.Error(error!))                 } else {                     print(result)                     let getFeedInfoResponse = Mapper&lt;GetFeedInfoResponse&gt;().map(result)!                     observer.on(.Next(getFeedInfoResponse))                     observer.on(.Completed)                 }             }                          return AnonymousDisposable {                              }         }     } <\/code><\/pre>\n<p>  \u041a\u0430\u043a \u043c\u044b \u0432\u0438\u0434\u0438\u043c, \u044f \u043f\u0435\u0440\u0435\u0434\u0430\u043b \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 parameters \u043a\u0443\u0447\u0443 \u043f\u043e\u043b\u0435\u0439 \u2014 \u044d\u0442\u043e \u0432\u0441\u0435 \u043f\u043e\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b\u043b\u0438 \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u0420\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c \u0438\u0445 \u0432\u0441\u0435 \u044f \u043d\u0435 \u0431\u0443\u0434\u0443, \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u0442\u044c. \u0412\u043e\u0442 \u043c\u0430\u043f\u043f\u0438\u043d\u0433 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"objectivec\">class GetFeedInfoResponse: Mappable {          var createdTime: String!     var from: IdName!     var id: String!     var isHidden: Bool!     var isPublished: Bool!     var message: String?     var name: String?     var statusType: String?     var story: String?     var to = [IdName]()     var type: String!     var updatedTime: String!          required init?(_ map: Map){              }          \/\/ Mappable     func mapping(map: Map) {         createdTime &lt;- map[&quot;created_time&quot;]         from &lt;- map[&quot;from&quot;]         id &lt;- map[&quot;from&quot;]         isHidden &lt;- map[&quot;is_hidden&quot;]         isPublished &lt;- map[&quot;is_published&quot;]         message &lt;- map[&quot;message&quot;]         name &lt;- map[&quot;name&quot;]         statusType &lt;- map[&quot;status_type&quot;]         story &lt;- map[&quot;story&quot;]                  \/\/ It necessary that Facebook API have a bad structure         \/\/ buffer%varname% is a temporary variable         var bufferTo = NSDictionary()         bufferTo &lt;- map[&quot;to&quot;]         if let bufferData = bufferTo[&quot;data&quot;] as? NSArray {             for bufferDataElement in bufferData {                 let bufferToElement = Mapper&lt;IdName&gt;().map(bufferDataElement)                 to.append(bufferToElement!)             }         }                  type &lt;- map[&quot;type&quot;]         updatedTime &lt;- map[&quot;updated_time&quot;]     }      }  class IdName: Mappable {          var id: String!     var name: String!          required init?(_ map: Map){              }          \/\/ Mappable     func mapping(map: Map) {         id &lt;- map[&quot;id&quot;]         name &lt;- map[&quot;name&quot;]     }      } <\/code><\/pre>\n<p>  \u041a\u0430\u043a \u0432\u0438\u0434\u0438\u043c, \u0431\u0435\u0437 \u043b\u043e\u0436\u043a\u0438 \u0434\u0435\u0433\u0442\u044f \u0442\u0443\u0442 \u0442\u043e\u0436\u0435 \u043d\u0435 \u043e\u0431\u043e\u0448\u043b\u043e\u0441\u044c. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438 \u0440\u0430\u0437\u0431\u043e\u0440\u0435 json-\u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u00abto\u00bb, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043e\u0434\u043d\u043e \u043f\u043e\u043b\u0435 \u00abdata\u00bb, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f json-\u043c\u0430\u0441\u0441\u0438\u0432\u043e\u043c, \u043c\u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0438\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"objectivec\">var bufferTo = NSDictionary()         bufferTo &lt;- map[&quot;to&quot;]         if let bufferData = bufferTo[&quot;data&quot;] as? NSArray {             for bufferDataElement in bufferData {                 let bufferToElement = Mapper&lt;IdName&gt;().map(bufferDataElement)                 to.append(bufferToElement!)             }         } <\/code><\/pre>\n<p>  \u0412 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435, \u044f \u043c\u043e\u0433 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0430\u0439\u043b \u0441 \u043e\u0434\u043d\u0438\u043c \u043f\u043e\u043b\u0435\u043c \u00abdata\u00bb \u0438 \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e \u0440\u0430\u0437\u043c\u0430\u043f\u043f\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u0442\u0430\u043c, \u043d\u043e \u043c\u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u0433\u043b\u0443\u043f\u043e\u0439 \u0441\u0430\u043c\u0430 \u0438\u0434\u0435\u044f \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b \u0440\u0430\u0434\u0438 \u043c\u0430\u043f\u043f\u0438\u043d\u0433\u0430 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044f. \u0415\u0441\u043b\u0438 \u0443 \u043a\u043e\u0433\u043e-\u0442\u043e \u0438\u0437 \u0412\u0430\u0441 \u0435\u0441\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u044d\u043b\u0435\u0433\u0430\u043d\u0442\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u2014 \u044f <s>\u043d\u0430\u043f\u044c\u044e\u0441\u044c \u043d\u0430 \u0440\u0430\u0434\u043e\u0441\u0442\u044f\u0445<\/s> \u0431\u0443\u0434\u0443 \u0440\u0430\u0434 \u0443\u0437\u043d\u0430\u0442\u044c \u043e \u043d\u0435\u043c.<\/p>\n<p>  \u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a \u043d\u0430\u0448\u0438\u043c \u0431\u0430\u0440\u0430\u043d\u0430\u043c. \u0421 Facebook&#8217;\u043e\u043c \u043c\u044b \u0441\u0432\u044f\u0437\u0430\u043b\u0438\u0441\u044c, \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u043e\u0432\u043e\u0441\u0442\u0435\u0439 \u0432 \u0432\u0438\u0434\u0435 Observable, \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435. \u0414\u043b\u044f \u044d\u0442\u043e\u0439 \u0446\u0435\u043b\u0438 \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d <a href=\"https:\/\/ru.wikipedia.org\/wiki\/Model-View-ViewModel\">MVVM<\/a>. \u041c\u043e\u044f \u0432\u043e\u043b\u044c\u043d\u0430\u044f \u0442\u0440\u0430\u043a\u0442\u043e\u0432\u043a\u0430 \u044d\u0442\u043e\u0433\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f ReactiveX \u0437\u0432\u0443\u0447\u0438\u0442 \u0442\u0430\u043a: \u0432\u043e ViewModel \u0435\u0441\u0442\u044c Observable, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u0430 View \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u044d\u0442\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0438\u0445. \u0422\u043e \u0435\u0441\u0442\u044c, ViewModel \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0442\u043e\u0433\u043e, \u043a\u0442\u043e \u043d\u0430 \u043d\u0435\u0433\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d \u2014 \u0435\u0441\u043b\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u0438 \u0435\u0441\u0442\u044c, \u0442\u043e Observable \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435, \u0435\u0441\u043b\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u043e\u0432 \u043d\u0435\u0442, \u0442\u043e Observable \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 (\u044d\u0442\u043e \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0432\u0435\u0440\u043d\u043e \u0434\u043b\u044f \u00ab\u0445\u043e\u043b\u043e\u0434\u043d\u044b\u0445\u00bb Observable, \u0442.\u043a. \u00ab\u0433\u043e\u0440\u044f\u0447\u0438\u0435\u00bb Observable \u0432\u0441\u0435\u0433\u0434\u0430 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0442 \u0434\u0430\u043d\u043d\u044b\u0435). \u041d\u0430\u043f\u0438\u0448\u0435\u043c ViewModel \u0434\u043b\u044f \u044d\u043a\u0440\u0430\u043d\u0430 \u043d\u043e\u0432\u043e\u0441\u0442\u0435\u0439:<\/p>\n<pre><code class=\"objectivec\">class FeedsViewModel {          let feedsObservable: Observable&lt;[Feed]&gt;     let clickObservable: Observable&lt;GetFeedInfoResponse&gt;          \/\/ If some process in progress     let indicator: Observable&lt;Bool&gt;          init(input: (         UITableView         ),         dependency: (         API: APIManager,         wireframe: Wireframe         )         ) {             let API = dependency.API             let wireframe = dependency.wireframe                          let indicator = ViewIndicator()             self.indicator = indicator.asObservable()                          feedsObservable = API.getFeeds()                 .trackView(indicator)                 .map { getFeedResponse in                     return getFeedResponse.data                 }                 .catchError { error in                     return wireframe.promptFor(String(error), cancelAction: &quot;OK&quot;, actions: [])                         .map { _ in                             return error                         }                         .flatMap { error in                             return Observable.error(error)                     }                 }                 .shareReplay(1)                          clickObservable = input                 .rx_modelSelected(Feed)                 .flatMap { feed  in                     return API.getFeedInfo(feed.id).trackView(indicator)                 }                 .catchError { error in                     return wireframe.promptFor(String(error), cancelAction: &quot;OK&quot;, actions: [])                         .map { _ in                             return error                         }                         .flatMap { error in                             return Observable.error(error)                     }                 }                 \/\/ If error when click uitableview - set retry() if you want to click cell again                 .retry()                 .shareReplay(1)     } } <\/code><\/pre>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043a\u043e\u0434. \u0412 \u043f\u043e\u043b\u0435 input \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0438\u0437 View, \u0432 \u043f\u043e\u043b\u0435 dependency \u2014 \u043a\u043b\u0430\u0441\u0441 API \u0438 Wireframe. \u0412 \u043a\u043b\u0430\u0441\u0441\u0435 \u0435\u0441\u0442\u044c 3 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435: feedsObservable \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 Observable \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u043d\u043e\u0432\u043e\u0441\u0442\u0435\u0439, clickObservable \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u044f\u0447\u0435\u0439\u043a\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0430 indicator \u044d\u0442\u043e \u0431\u0443\u043b\u0435\u0432\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0430\u044f \u043d\u0443\u0436\u043d\u043e \u043b\u0438 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u0412 \u043a\u043e\u0434\u0435 \u0435\u0441\u0442\u044c \u0441\u0440\u0430\u0437\u0443 2 \u043b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u0430 \u2014 Wireframe \u0438 ViewIndicator, \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c\u0441\u044f \u043d\u0430 \u043d\u0438\u0445 \u043f\u043e\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0439. Wireframe \u044d\u0442\u043e \u043d\u0435 \u0447\u0442\u043e \u0438\u043d\u043e\u0435, \u043a\u0430\u043a \u00ab\u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u0430\u044f\u00bb \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f alert&#8217;\u043e\u0432. \u042f \u0432\u0437\u044f\u043b \u044d\u0442\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 RxSwift. ViewIndicator \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0442\u0440\u0435\u043a\u0438\u043d\u0433, \u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f trackView \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 trackView \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u042f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043a\u043e\u0434 \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u2014 \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0439\u0442\u0438 \u0435\u0433\u043e \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u043d\u0438\u0437\u0443 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p>  \u041a\u043e\u0441\u043d\u0435\u043c\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0448\u0438\u0445 Observable. \u041f\u0435\u0440\u0432\u044b\u0439 \u2014 feedsObservable \u2014 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442 \u0441 Facebook, \u043f\u043e\u0442\u043e\u043c \u0432 \u0431\u043b\u043e\u043a\u0435 map \u0438\u0437 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u044e\u0442\u0441\u044f \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u043e\u0432\u043e\u0441\u0442\u0435\u0439, \u043f\u043e\u0442\u043e\u043c \u0441\u0442\u043e\u0438\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a, \u043d\u0443 \u0438 trackView \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u0412\u0442\u043e\u0440\u043e\u0439 \u2014 clickObservable \u2014 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442 \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u043d\u0430 \u044f\u0447\u0435\u0439\u043a\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043d\u043e\u0432\u043e\u0441\u0442\u0438. \u0421\u0443\u043f\u0435\u0440, \u0441 \u043c\u043e\u0434\u0435\u043b\u044c\u044e \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438, \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043a View.<\/p>\n<p>  \u042f \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u043a\u043e\u0434 View, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043c\u044b \u0441 \u0412\u0430\u043c\u0438 \u0435\u0433\u043e \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c:<\/p>\n<pre><code class=\"objectivec\">class FeedsViewController: UIViewController, UITableViewDelegate {      @IBOutlet weak var feedsTableView: UITableView!          var disposeBag = DisposeBag()          override func viewDidLoad() {         super.viewDidLoad()                  let viewModel = FeedsViewModel(             input:feedsTableView,             dependency: (                 API: APIManager.sharedAPI,                 wireframe: DefaultWireframe.sharedInstance             )         )                  let progress = MBProgressHUD()         progress.mode = MBProgressHUDMode.Indeterminate         progress.labelText = &quot;\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445...&quot;         progress.dimBackground = true                  viewModel.indicator             .bindTo(progress.rx_mbprogresshud_animating)             .addDisposableTo(self.disposeBag)                  feedsTableView.rx_setDelegate(self)                  viewModel.feedsObservable             .bindTo(feedsTableView.rx_itemsWithCellFactory) { tableView, row, feed in                                  let cell = tableView.dequeueReusableCellWithIdentifier(&quot;feedTableViewCell&quot;) as! FeedTableViewCell                                  cell.feedCreatedTime.text = NSDate().convertFacebookTime(feed.createdTime)                                  if let story = feed.story {                     cell.feedInfo.text = story                 } else if let message = feed.message {                     cell.feedInfo.text = message                 }                                  cell.layoutMargins = UIEdgeInsetsZero                              return cell             }             .addDisposableTo(disposeBag)                  viewModel.clickObservable             .subscribeNext { feed in                 let storyboard = UIStoryboard(name: &quot;Main&quot;, bundle: nil)                 let feedInfoViewController = storyboard.instantiateViewControllerWithIdentifier(&quot;feedInfoViewController&quot;) as! FeedInfoViewController                 feedInfoViewController.feedInfo = feed                 self.navigationController?.pushViewController(feedInfoViewController, animated: true)             }             .addDisposableTo(disposeBag)     }      override func didReceiveMemoryWarning() {         super.didReceiveMemoryWarning()     }      \/\/ Deselect tableView row after click     func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {         tableView.deselectRowAtIndexPath(indexPath, animated: true)     }      } <\/code><\/pre>\n<p>  \u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c, \u0441\u043e\u0437\u0434\u0430\u0435\u043c viewModel. \u0414\u0430\u043b\u0435\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u043a\u0430\u043a-\u0442\u043e \u0435\u0433\u043e \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u0441 ViewIndicator. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c Extension \u0434\u043b\u044f MBProgressHUD:<\/p>\n<pre><code class=\"objectivec\">extension MBProgressHUD {          \/**      Bindable sink for MBProgressHUD show\/hide methods.      *\/     public var rx_mbprogresshud_animating: AnyObserver&lt;Bool&gt; {         return AnyObserver {event in             MainScheduler.ensureExecutingOnScheduler()                          switch (event) {             case .Next(let value):                 if value {                     let loadingNotification = MBProgressHUD.showHUDAddedTo(UIApplication.sharedApplication().keyWindow?.subviews.last, animated: true)                     loadingNotification.mode = self.mode                     loadingNotification.labelText = self.labelText                     loadingNotification.dimBackground = self.dimBackground                 } else {                     MBProgressHUD.hideHUDForView(UIApplication.sharedApplication().keyWindow?.subviews.last, animated: true)                 }             case .Error(let error):                 let error = &quot;Binding error to UI: \\(error)&quot;                 #if DEBUG                     rxFatalError(error)                 #else                     print(error)                 #endif             case .Completed:                 break             }         }     } } <\/code><\/pre>\n<p>  \u0415\u0441\u043b\u0438 \u0432 MBProgressHUD \u043f\u043e\u0434\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0442\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440. \u0415\u0441\u043b\u0438 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043d\u0435 \u043f\u043e\u0434\u0430\u0435\u0442\u0441\u044f \u2014 \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0435\u0433\u043e. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0431\u0438\u043d\u0434\u0438\u043d\u0433 \u043c\u0435\u0436\u0434\u0443 \u043d\u0430\u0448\u0438\u043c MBProgressHUD \u0438 ViewIndicator. \u0414\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u0432\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"objectivec\">viewModel.indicator             .bindTo(progress.rx_mbprogresshud_animating)             .addDisposableTo(self.disposeBag) <\/code><\/pre>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0431\u0438\u043d\u0434\u0438\u043d\u0433 \u043c\u0435\u0436\u0434\u0443 UITableView \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043c\u0435\u0436\u0434\u0443 \u043d\u0430\u0436\u0430\u0442\u0438\u0435\u043c \u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 UITableView \u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u043c \u043d\u0430 \u043d\u043e\u0432\u044b\u0439 \u044d\u043a\u0440\u0430\u043d. \u042d\u043a\u0440\u0430\u043d \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u0441\u0442\u0435 \u044f \u0442\u0430\u043a\u0436\u0435 \u0441\u0434\u0435\u043b\u0430\u043b \u0431\u0435\u0437 \u00ab\u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438\u00bb:<\/p>\n<pre><code class=\"objectivec\">override func viewDidLoad() {         super.viewDidLoad()                  var feedDetail = &quot;From: &quot; + feedInfo.from.name                  if feedInfo.to.count &gt; 0 {             feedDetail += &quot;\\nTo: &quot;             for to in feedInfo.to {                 feedDetail += to.name + &quot;\\n&quot;             }         }                  if let date = feedInfo.createdTime {             feedDetail += &quot;\\nDate: &quot; + NSDate().convertFacebookTime(date)         }                  if let story = feedInfo.story {             feedDetail += &quot;\\nStory: &quot; + story         }                  if let message = feedInfo.message {             feedDetail += &quot;\\nMessage: &quot; + message         }                  if let name = feedInfo.name {             feedDetail += &quot;\\nName: &quot; + name         }                  if let type = feedInfo.type {             feedDetail += &quot;\\nType: &quot; + type         }                  if let updatedTime = feedInfo.updatedTime {             feedDetail += &quot;\\nupdatedTime: &quot; + NSDate().convertFacebookTime(updatedTime)         }                  feedTextView.text = feedDetail                  self.navigationController?.navigationBar.tintColor = UIColor.whiteColor()     } <\/code><\/pre>\n<p>  \u041d\u0430 \u044d\u0442\u043e\u043c \u0443 \u043c\u0435\u043d\u044f \u0432\u0441\u0435. \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430 Github \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u043f\u043e \u044d\u0442\u043e\u0439 <a href=\"https:\/\/github.com\/svyatoslav-reshetnikov\/ReactiveApp\">\u0441\u0441\u044b\u043b\u043a\u0435<\/a>. \u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u043b\u0430\u0441\u044c \u043c\u043e\u044f \u0441\u0442\u0430\u0442\u044c\u044f, \u0442\u043e \u044f <s>\u043b\u043e\u043f\u043d\u0443 \u043e\u0442 \u0441\u0447\u0430\u0441\u0442\u044c\u044f<\/s> \u0441 \u0443\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0438\u0435\u043c \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0443 \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e RxSwift \u0438 \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u044c \u0435\u0433\u043e \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b \u0432 \u0431\u043e\u043b\u0435\u0435 \u043d\u0435\u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447\u0430\u0445.       <\/p>\n<div class=\"clear\"><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habrahabr.ru\/post\/276971\/\"> https:\/\/habrahabr.ru\/post\/276971\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>       \u0415\u0441\u043b\u0438 \u0432\u0435\u0440\u0438\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c \u0442\u0435\u043d\u0434\u0435\u043d\u0446\u0438\u044f\u043c, \u0442\u043e FRP \u043d\u0430\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u0431\u043e\u0440\u043e\u0442\u044b \u0438 \u043d\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f. \u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u043d\u044b\u043c FRP \u2014 <a href=\"http:\/\/reactivex.io\/\">ReactiveX<\/a>, \u0438 \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0434\u043b\u044f Swift \u2014 <a href=\"https:\/\/github.com\/ReactiveX\/RxSwift\">RxSwift<\/a>. \u041d\u0430 \u0425\u0430\u0431\u0440\u0435 \u0443\u0436\u0435 \u0431\u044b\u043b\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f <a href=\"https:\/\/habrahabr.ru\/post\/273455\/\">\u0441\u0442\u0430\u0442\u044c\u044f<\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f RxSwift. \u042f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0440\u0430\u0437\u0432\u0438\u0442\u044c \u044d\u0442\u0443 \u0442\u0435\u043c\u0443, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u0432\u0448\u0438\u043c\u0441\u044f \u2014 \u0434\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434 \u043a\u0430\u0442!<\/p>\n<h4>\u041b\u0438\u0445\u0430 \u0431\u0435\u0434\u0430 \u043d\u0430\u0447\u0430\u043b\u043e<\/h4>\n<p>  \u0418 \u044d\u0442\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0442\u0430\u043a. \u0421\u0430\u043c\u043e\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0435, \u0441 \u0447\u0435\u043c \u043c\u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u0442\u044c\u0441\u044f \u2014 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u0434\u0440\u0443\u0433\u043e\u0435 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430. \u0421 \u043c\u043e\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c \u0438\u043c\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u044b\u043b\u043e \u0442\u044f\u0436\u0435\u043b\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043d\u043e\u0432\u044b\u0439 \u043b\u0430\u0434. \u041d\u043e \u0447\u0443\u0442\u044c\u0451 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u043e \u043c\u043d\u0435, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u043c \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f; \u0443 \u043c\u0435\u043d\u044f \u0443\u0448\u043b\u043e 2 \u043d\u0435\u0434\u0435\u043b\u0438 <s>\u043f\u0430\u043d\u0438\u043a\u0438<\/s> \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u0432 \u0441\u0443\u0442\u044c ReactiveX \u0438 \u044f \u043d\u0435 \u0436\u0430\u043b\u0435\u044e \u043e \u043f\u043e\u0442\u0440\u0430\u0447\u0435\u043d\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0440\u0430\u0437\u0443 \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0434\u0438\u0442\u044c \u2014 \u0441\u0442\u0430\u0442\u044c\u044f \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u0432 ReactiveX, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a Observable, Subscriber \u0438 \u0442.\u0434.<\/p>\n<p>  \u0418\u0442\u0430\u043a, \u043d\u0430\u0447\u043d\u0435\u043c. <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-273998","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/273998","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=273998"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/273998\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=273998"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=273998"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=273998"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}