{"id":279763,"date":"2016-05-08T07:45:02","date_gmt":"2016-05-08T03:45:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=279763"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=279763","title":{"rendered":"RxSwift: \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 GUI"},"content":{"rendered":"<p>       <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/49a\/a66\/dfc\/49aa66dfc7e34d5ca6292d7dc9c5e387.png\"\/><\/p>\n<p>  \u041c\u043e\u044f <a href=\"https:\/\/habrahabr.ru\/post\/281292\/\">\u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e RxSwift<\/a> \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u043b\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0441\u0435 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b, \u0431\u0435\u0437 \u0437\u043d\u0430\u043d\u0438\u0439 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043d\u0435 \u0438\u043c\u0435\u043b\u043e \u043e\u0441\u043e\u0431\u043e\u0433\u043e \u0441\u043c\u044b\u0441\u043b\u0430. \u041d\u043e \u044d\u0442\u043e \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u0430\u043b\u0444\u0430\u0432\u0438\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043d\u044f\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 GUI.<\/p>\n<p>  \u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0434\u043b\u044f \u043f\u0440\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0437 RxExample, \u043d\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432 \u0431\u044b\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0430 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 UIExplanation \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0432 RxExample<br \/>  \u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0437\u0434\u0435\u0441\u044c <a href=\"https:\/\/github.com\/sparklone\/RxSwift\/\">github.com\/sparklone\/RxSwift<\/a><\/p>\n<p>  \u041f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 UI \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0432 Rx \u0435\u0441\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0438:<br \/>  1) <a href=\"#Driver\">\u043f\u043e\u043d\u044f\u0442\u044c \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u0430\u043c\u043d\u0438 \u043d\u0430\u0441 \u043e\u0436\u0438\u0434\u0430\u044e\u0442 \u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435 \u0438 \u0437\u0430\u0447\u0435\u043c \u043d\u0443\u0436\u0435\u043d Driver<\/a><br \/>  2) <a href=\"#UIBindingObserver\">\u043d\u0430\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 UI \u043a Observable, \u0447\u0442\u043e\u0431\u044b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b Observable \u043c\u0435\u043d\u044f\u043b\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\/\u0441\u0432\u043e\u0439\u0441\u0442\u0432 UI \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430. \u042d\u0442\u043e \u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e UIBindingObserver<\/a><br \/>  3) <a href=\"#ControlEvent\">\u043d\u0430\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u0430\u0442\u0442\u0435\u0440\u043d target-action \u043d\u0430 \u0440\u0435\u043b\u044c\u0441\u044b Rx. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ControlEvent<\/a><br \/>  4) <a href=\"#ControlProperty\">\u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0432\u0443\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u044e\u044e \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c UI \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ControlProperty<\/a><br \/>  5) <a href=\"#DelegateProxy\">\u0442.\u043a. \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u0443 UI \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 delegate\/dataSource \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0442\u0441\u044f \u0432 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u0447\u0438\u0441\u043b\u0435, \u2014 \u0432\u0432\u0435\u043b\u0438 \u043a\u043b\u0430\u0441\u0441 DelegateProxy, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0434\u0435\u043b\u0435\u0433\u0430\u0442, \u0442\u0430\u043a \u0438 Rx \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/a><\/p>\n<p>  \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u0436\u0434\u0443\u044e \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e<br \/>  <a name=\"habracut\"><\/a><\/p>\n<p>  <a name=\"Driver\"><\/a>  <\/p>\n<h2>Driver<\/h2>\n<p>  1) \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 Observable. \u0427\u0442\u043e\u0431\u044b \u0438\u0445 \u043f\u043e\u043d\u044f\u0442\u044c, \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 <a href=\"https:\/\/github.com\/sparklone\/RxSwift\/blob\/master\/UIExplanation.playground\/Pages\/Without%20ShareRelay.xcplaygroundpage\/Contents.swift\">\u043f\u0440\u0438\u043c\u0435\u0440<\/a> \u0432 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0435<\/p>\n<pre><code>import Cocoa import RxSwift import RxCocoa import XCPlayground  XCPlaygroundPage.currentPage.needsIndefiniteExecution = true  example(&quot;without shareReplay duplicate call problem&quot;) {     let source = NSTextField()     let status = NSTextField()          let URL = NSURL(string: &quot;https:\/\/github.com\/&quot;)!     let request = NSURLRequest(URL: URL)     let observable =  NSURLSession.sharedSession().rx_response(request).debug(&quot;http&quot;)          let sourceObservable = observable.map { (maybeData, response) in         return String(data: maybeData, encoding: NSUTF8StringEncoding)!         }.observeOn(MainScheduler.instance)     let statusObservable = observable.map { (maybeData, response) in         return response.statusCode.description         }.observeOn(MainScheduler.instance)          sourceObservable.subscribe(source.rx_text)     statusObservable.subscribe(status.rx_text) } <\/code><\/pre>\n<p>  \u0430) \u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c Observable \u0438 \u043a \u043d\u0435\u043c\u0443 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e Observer&#8217;\u043e\u0432 \u2014 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e Observer&#8217;\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 Observable. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 Observable \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u0441\u0435\u0442\u044c \u0438 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u043a\u043e\u0434 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0438 \u0441\u0442\u0430\u0442\u0443\u0441 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u0432 \u0440\u0430\u0437\u043d\u044b\u0435 textView.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0442\u043e \u0443\u0432\u0438\u0434\u0438\u043c 2 subscribed, 2 disposed:  <\/p>\n<pre><code>--- without shareReplay duplicate call problem example --- 2016-05-01 04:17:17.225: http -&gt; subscribed 2016-05-01 04:17:17.229: http -&gt; subscribed curl -X GET  &quot;https:\/\/github.com\/&quot; -i -v Success (1098ms): Status 200 2016-05-01 04:17:18.326: http -&gt; Event Next((&lt;OS_dispatch_d...; mode=block&quot;; } })) 2016-05-01 04:17:18.339: http -&gt; Event Completed 2016-05-01 04:17:18.339: http -&gt; disposed curl -X GET  &quot;https:\/\/github.com\/&quot; -i -v Success (1326ms): Status 200 2016-05-01 04:17:18.556: http -&gt; Event Next((&lt;OS_dispatch_d...; mode=block&quot;; } })) 2016-05-01 04:17:18.557: http -&gt; Event Completed 2016-05-01 04:17:18.557: http -&gt; disposed<\/code><\/pre>\n<p>  \u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e\u0433\u043e \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c, \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c shareReplayLatestWhileConnected \u0434\u043b\u044f \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e observable  <\/p>\n<pre><code>let observable =  NSURLSession.sharedSession().rx_response(request).debug(&quot;http&quot;).shareReplayLatestWhileConnected()<\/code><\/pre>\n<p>  \u0412 \u0438\u0442\u043e\u0433\u0435 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0438\u0434\u0435\u0442 \u043b\u0438\u0448\u044c \u043e\u0434\u043d\u043e \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435  <\/p>\n<pre><code>--- with shareReplay no duplicate call problem example --- 2016-05-01 04:18:27.845: http -&gt; subscribed curl -X GET  &quot;https:\/\/github.com\/&quot; -i -v Success (960ms): Status 200 2016-05-01 04:18:28.807: http -&gt; Event Next((&lt;OS_dispatch_d...; mode=block&quot;; } })) 2016-05-01 04:18:28.820: http -&gt; Event Completed 2016-05-01 04:18:28.821: http -&gt; disposed<\/code><\/pre>\n<p>  \u0417\u0430\u043c\u0435\u0447\u0443 \u0435\u0449\u0435, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f shareReplayLatestWhileConnected, \u0430 \u043d\u0435 shareReplay(1), \u0442.\u043a. \u043e\u043d \u043e\u0447\u0438\u0449\u0430\u0435\u0442 \u0431\u0443\u0444\u0435\u0440 \u043f\u0440\u0438 \u043e\u0442\u043f\u0438\u0441\u043a\u0435 \u0432\u0441\u0435\u0445 Observer&#8217;\u043e\u0432 \u0438 \u043f\u0440\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0438\u043b\u0438 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439. \u041a\u043e\u0433\u0434\u0430 \u044f \u043f\u0438\u0441\u0430\u043b \u043f\u0435\u0440\u0432\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e \u043f\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430\u043c RxSwift, \u0442\u043e \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b \u044d\u0442\u043e \u0441\u0442\u0440\u0430\u043d\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 shareReplay (\u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u043e\u0447\u0438\u0441\u0442\u043a\u0438 \u0434\u0430\u0436\u0435 \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0431\u044b\u043b\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430) \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0432 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0435 \u0438 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u044f \u0447\u0442\u043e \u0442\u043e \u0434\u0435\u043b\u0430\u044e \u043d\u0435 \u0442\u0430\u043a, \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u2014 by design.<\/p>\n<p>  \u0431) \u0432\u0441\u0435 \u0447\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 GUI \u043c\u044b \u043e\u0431\u044f\u0437\u0430\u043d\u044b \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430 MainScheduler. \u0415\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u043e\u0441\u0432\u0435\u0436\u0438\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u043f\u043e \u043f\u043e\u0432\u043e\u0434\u0443 \u0440\u0430\u0437\u043d\u044b\u0445 Scheduler&#8217;\u043e\u0432. \u041c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 <a href=\"https:\/\/github.com\/sparklone\/RxSwift\/blob\/master\/Documentation\/Schedulers.md\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a> \u0438 \u043f\u0440\u043e\u0439\u0442\u0438 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0430\u043c, \u0433\u0434\u0435 \u044f \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u043b <a href=\"https:\/\/habrahabr.ru\/post\/281292\/#subscribeOn\">subscribeOn<\/a> \u0438 <a href=\"https:\/\/habrahabr.ru\/post\/281292\/#observeOn\">observeOn<\/a> \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<br \/>  \u0415\u0441\u043b\u0438 \u0443\u0431\u0440\u0430\u0442\u044c .observeOn(MainScheduler.instance) \u0438\u0437 \u043a\u043e\u0434\u0430, \u2014 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c   <\/p>\n<pre><code>fatalError &quot;fatal error: Executing on backgound thread. Please use `MainScheduler.instance.schedule` to schedule work on main thread.&quot;<\/code><\/pre>\n<p>  \u041c\u0435\u043d\u044f \u043a\u0441\u0442\u0430\u0442\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0437\u0430\u0434\u0430\u0447\u0438\u043b\u0430 \u044d\u0442\u0430 \u043e\u0448\u0438\u0431\u043a\u0430, \u044f \u0432\u0435\u0434\u044c \u0437\u043d\u0430\u043b, \u0447\u0442\u043e \u0432 \u043a\u0430\u043a\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 \u0442\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u0448\u044c Observable, \u0432 \u0442\u0430\u043a\u043e\u043c \u0438 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043a\u043e\u0434 \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0435\u0433\u043e. \u041d\u043e \u044f \u043e\u0448\u0438\u0431\u043e\u0447\u043d\u043e \u043f\u043e\u043b\u0430\u0433\u0430\u043b, \u0447\u0442\u043e \u0432 \u043a\u0430\u043a\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 \u0438\u0434\u0435\u0442 \u0432\u044b\u0437\u043e\u0432 subscribe, \u0432 \u0442\u0430\u043a\u043e\u043c \u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 observer&#8217;\u0430. <\/p>\n<p>  \u041f\u043e \u043f\u0435\u0440\u0432\u043e\u043c\u0443 \u043c\u043e\u043c\u0435\u043d\u0442\u0443, \u043a\u043e\u0434 Observable \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c \u0436\u0435 \u043f\u043e\u0442\u043e\u043a\u0435, \u0433\u0434\u0435 \u043e\u043d \u0438 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d. \u041d\u043e, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 rx_response \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f Observable, \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0438\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a \u043c\u0435\u0442\u043e\u0434\u0443 dataTaskWithRequest \u043e\u0442 NSURLSession, \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0438\u0434\u0435\u0442 \u0438\u0437 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430, \u0430 \u044d\u0442\u043e \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0435 \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u0434\u0440\u0443\u0433\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u043e \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u0438\u0437 NSURLSession.sharedSession().rx_response(request) \u043d\u0430\u0441 \u0436\u0434\u0435\u0442 \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u043e\u0442\u043e\u043a.<\/p>\n<p>  \u0410 \u043f\u043e \u0432\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u2014 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u044f \u043e\u0448\u0438\u0431\u043e\u0447\u043d\u043e \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u043b, \u0447\u0442\u043e \u0438\u0437 \u043a\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0448\u044c subscribe \u2014 \u0432 \u044d\u0442\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 \u0438 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0442\u0435\u043b\u043e Observer&#8217;\u0430&quot;, \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0435 \u0442\u0430\u043a. \u041f\u043e\u0442\u043e\u043a \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0442\u043e\u0442 \u2014 \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0439 \u043a\u043e\u0434 Observable.<br \/>  \u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0435\u0449\u0435 \u0434\u0432\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0430<\/p>\n<pre><code>example(&quot;from main thread&quot;) {     print(&quot;init thread: \\(NSThread.currentThread())&quot;)     let source = NSTextField()     let status = NSTextField()          let URL = NSURL(string: &quot;https:\/\/github.com\/&quot;)!     let request = NSURLRequest(URL: URL)     let observable =  NSURLSession.sharedSession().rx_response(request).shareReplayLatestWhileConnected()          let sourceObservable = observable.map { (maybeData, response) in         return String(data: maybeData, encoding: NSUTF8StringEncoding)!     }          sourceObservable.subscribe() { e in         print(&quot;observer thread: \\(NSThread.currentThread())&quot;)     } }  example(&quot;from another queue&quot;) {     print(&quot;init thread: \\(NSThread.currentThread())&quot;)     let source = NSTextField()     let status = NSTextField()          let URL = NSURL(string: &quot;https:\/\/github.com\/&quot;)!     let request = NSURLRequest(URL: URL)     let observable =  NSURLSession.sharedSession().rx_response(request).shareReplayLatestWhileConnected()          let sourceObservable = observable.map { (maybeData, response) in         return String(data: maybeData, encoding: NSUTF8StringEncoding)!     }          let queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)     dispatch_async(queue1,{         print(&quot;queue1 thread: \\(NSThread.currentThread())&quot;)         sourceObservable.subscribe() { e in             print(&quot;observer thread: \\(NSThread.currentThread())&quot;)         }     }) }<\/code><\/pre>\n<p>  \u0412\u044b\u0432\u043e\u0434 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438:<\/p>\n<pre><code>--- from main thread example --- init thread: &lt;NSThread: 0x7fc298d12ec0&gt;{number = 1, name = main} curl -X GET  &quot;https:\/\/github.com\/&quot; -i -v Success (944ms): Status 200 observer thread: &lt;NSThread: 0x7fc298fbf1a0&gt;{number = 3, name = (null)} observer thread: &lt;NSThread: 0x7fc298fbf1a0&gt;{number = 3, name = (null)}  --- from another queue example --- init thread: &lt;NSThread: 0x7ff182d12ef0&gt;{number = 1, name = main} queue1 thread: &lt;NSThread: 0x7ff182d5c3e0&gt;{number = 3, name = (null)} curl -X GET  &quot;https:\/\/github.com\/&quot; -i -v Success (956ms): Status 200 observer thread: &lt;NSThread: 0x7ff185025950&gt;{number = 4, name = (null)} observer thread: &lt;NSThread: 0x7ff185025950&gt;{number = 4, name = (null)}<\/code><\/pre>\n<p>  \u0412 \u043e\u0431\u043e\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u044f \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e observeOn. \u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0432 \u043e\u0431\u043e\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u043a\u043e\u0434 \u0432\u043d\u0443\u0442\u0440\u0438 observer&#8217;\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0435 \u0432 \u043f\u043e\u0442\u043e\u043a\u0435 \u0442\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0434\u0435\u043b\u0430\u043b subscribe, \u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u0435\u0440\u043d\u0443\u043b\u0441\u044f \u0438\u0437 rx_response (\u0432 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u0438\u0432 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0432\u043d\u0443\u0442\u0440\u0438 \u0444\u0430\u0439\u043b\u0430 NSURLSession+Rx \u0438\u0437 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Rx)<\/p>\n<pre><code>public func rx_response(request: NSURLRequest) -&gt; Observable&lt;(NSData, NSHTTPURLResponse)&gt; { \treturn Observable.create { observer in \t\tprint(&quot;RXRESPONSE thread: \\(NSThread.currentThread())&quot;)  ......\t\t\t              let task = self.dataTaskWithRequest(request) { (data, response, error) in print(&quot;TASK thread: \\(NSThread.currentThread())&quot;)<\/code><\/pre>\n<p>  \u0432) \u0435\u0441\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043a\u043e\u0434\u0430 Observable, \u0442\u043e \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 Debug \u043c\u044b \u043b\u043e\u0432\u0438\u043c fatalError, \u0430 \u0432 Release \u2014 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0443\u0445\u043e\u0434\u0438\u0442 \u043e\u0448\u0438\u0431\u043a\u0430 \u00abBinding error to UI: Argument out of range.\u00bb \u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043e\u0442\u0432\u044f\u0437\u043a\u0430 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u0447\u0430\u0441\u0442\u043d\u043e\u0433\u043e \u0432 UI \u043a \u044d\u0442\u043e\u043c\u0443 Observable.<\/p>\n<p>  \u0427\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043a\u0430\u043a \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u2014 \u044f \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043b \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 IntroductionExampleViewController. \u042f \u0437\u0430\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043b \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u043a disposeButton.rx_tap, \u0432\u043c\u0435\u0441\u0442\u043e \u043d\u0435\u0435 \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u0441\u0432\u043e\u044e (\u043d\u0430 \u0433\u0438\u0442\u0445\u0430\u0431\u0435 \u044f \u0437\u0430\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043b \u0441\u0432\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043c\u0435\u043d\u044f\u0442\u044c \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u043d\u0430 \u043b\u0435\u0442\u0443)<\/p>\n<pre><code>disposeButton.rx_tap.debug(&quot;rx_tap&quot;)     .flatMap{ value in     return Observable&lt;String&gt;.create{ observer in         observer.on(.Next(&quot;1&quot;))         observer.onError(RxError.ArgumentOutOfRange)         return NopDisposable.instance     } } .bindTo(a.rx_text) .addDisposableTo(disposeBag)<\/code><\/pre>\n<p>  \u0412 Release \u0440\u0435\u0436\u0438\u043c\u0435 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f  <\/p>\n<pre><code>2016-04-30 02:02:41.486: rx_tap -&gt; subscribed<\/code><\/pre>\n<p>  \u0410 \u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443<\/p>\n<pre><code>2016-04-30 02:02:48.248: rx_tap -&gt; Event Next(()) Binding error to UI: Argument out of range. 2016-04-30 02:02:48.248: rx_tap -&gt; disposed<\/code><\/pre>\n<p>  \u0414\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u0443\u0436\u0435 \u043d\u0438 \u043a \u0447\u0435\u043c\u0443 \u043d\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442, \u0442.\u043a. rx_tap \u0441\u0442\u0430\u043b disposed<\/p>\n<p>  \u0412 \u0438\u0442\u043e\u0433\u0435 \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u044d\u0442\u0438\u043c\u0438 \u043c\u043e\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0438 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d Driver, \u043e\u043d \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u043a\u0430\u043a \u0440\u0430\u0437 \u0442\u0440\u0438 \u0432\u0435\u0449\u0438<br \/>  \u0430) \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0448\u0430\u0440\u0438\u0442\u044c\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e shareReplayLatestWhileConnected<br \/>  \u0431) \u043f\u043e\u0442\u043e\u043a \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430 MainScheduler (\u0433\u0440\u0443\u0431\u043e \u0433\u043e\u0432\u043e\u0440\u044f UI \u043f\u043e\u0442\u043e\u043a)<br \/>  \u0432) \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043e\u0448\u0438\u0431\u043e\u043a (\u043c\u044b \u0441\u0430\u043c\u0438 \u0440\u0435\u0448\u0430\u0435\u043c \u043a\u0430\u043a\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0448\u0438\u0431\u043a\u0438)<\/p>\n<p>  \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/p>\n<pre><code>let safeSequence = xs   .observeOn(MainScheduler.instance) \/\/ observe events on main scheduler   .catchErrorJustReturn(onErrorJustReturn) \/\/ can't error out   .shareReplayLatestWhileConnected         \/\/ side effects sharing return Driver(raw: safeSequence)           \/\/ wrap it up<\/code><\/pre>\n<p>  \u0415\u0441\u043b\u0438 \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u0433\u0434\u0435 \u0442\u043e drive() \u0432\u043c\u0435\u0441\u0442\u043e subscribe() \u043c\u044b \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u043c \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u043c \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 ui.<\/p>\n<p>  \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438\u043c\u0435\u0440 GitHubSignup, \u0442\u0430\u043c \u043a\u0430\u043a \u0440\u0430\u0437 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044e\u0442 \u0432 \u043b\u043e\u0431 \u043a\u043e\u0434 \u0441 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u043c Driver \u0438 \u0431\u0435\u0437 \u043e\u043d\u043e\u0433\u043e.<br \/>  \u041d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Driver \u043a\u043e\u0434 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f viewModel \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c:<\/p>\n<pre><code>let viewModel = GithubSignupViewModel1(     input: (         username: usernameOutlet.rx_text.asObservable(),         password: passwordOutlet.rx_text.asObservable(),         repeatedPassword: repeatedPasswordOutlet.rx_text.asObservable(),         loginTaps: signupOutlet.rx_tap.asObservable()     )     ...<\/code><\/pre>\n<p>  \u0442.\u043a. rx_text \u2014 ControlProperty, \u0442\u043e asObservable \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 Observable \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445 \u043b\u0438\u0431\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0439<\/p>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0441 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u043c Driver&#8217;\u0430<\/p>\n<pre><code>let viewModel = GithubSignupViewModel2(     input: (         username: usernameOutlet.rx_text.asDriver(),         password: passwordOutlet.rx_text.asDriver(),         repeatedPassword: repeatedPasswordOutlet.rx_text.asDriver(),         loginTaps: signupOutlet.rx_tap.asDriver()     ),     ...<\/code><\/pre>\n<p>  \u0420\u0430\u0437\u043d\u0438\u0446\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f, \u0432\u043c\u0435\u0441\u0442\u043e asObservable \u2014 asDriver, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e \u0432\u044b\u0448\u0435\u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0445 3\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u0439.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u0431\u0440\u0430\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435, \u0442\u043e \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u0442\u043e\u0436\u0435 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0430, \u0431\u0435\u0437 Driver \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f subscribe\/bind \u0438 \u0438\u0445 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438<\/p>\n<pre><code>viewModel.signupEnabled     .subscribeNext { [weak self] valid  in         self?.signupOutlet.enabled = valid         self?.signupOutlet.alpha = valid ? 1.0 : 0.5     }     .addDisposableTo(disposeBag)  viewModel.validatedUsername     .bindTo(usernameValidationOutlet.ex_validationResult)     .addDisposableTo(disposeBag)<\/code><\/pre>\n<p>  \u0421 Driver \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c drive \u0438 \u0435\u0433\u043e \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438<\/p>\n<pre><code>viewModel.signupEnabled     .driveNext { [weak self] valid  in         self?.signupOutlet.enabled = valid         self?.signupOutlet.alpha = valid ? 1.0 : 0.5     }     .addDisposableTo(disposeBag)  viewModel.validatedUsername     .drive(usernameValidationOutlet.ex_validationResult)     .addDisposableTo(disposeBag) <\/code><\/pre>\n<p>  \u0427\u0443\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u0437\u0433\u043b\u044f\u043d\u0443\u0442\u044c \u0432 GithubSignupViewModel1\/GithubSignupViewModel2 \u0433\u0434\u0435 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f Driver&#8217;\u0430<\/p>\n<p>  \u041c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u044b\u0439 \u043a\u043e\u0434 \u0432 GithubSignupViewModel1<\/p>\n<pre><code>validatedUsername = input.username \t.flatMapLatest { username in \t    return validationService.validateUsername(username) \t        .observeOn(MainScheduler.instance) \t        .catchErrorJustReturn(.Failed(message: &quot;Error contacting server&quot;)) \t} \t.shareReplay(1)  <\/code><\/pre>\n<p>  \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442\u0441\u044f \u0434\u043e <\/p>\n<pre><code>validatedUsername = input.username \t.flatMapLatest { username in \t    return validationService.validateUsername(username) \t        .asDriver(onErrorJustReturn: .Failed(message: &quot;Error contacting server&quot;)) \t}<\/code><\/pre>\n<p>  \u0417\u0434\u0440\u0430\u0432\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u0437\u043d\u0430\u043d\u0438\u0439 \u0443\u0436\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0443\u0431\u0435\u0440\u0435\u0447\u044c \u043e\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 UI. \u041d\u043e \u0432\u0441\u0435 \u0436\u0435 \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c \u043a\u0430\u043a \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u044e\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 UI \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Rx, \u0447\u0442\u043e\u0431\u044b \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f. <\/p>\n<p>  <a name=\"UIBindingObserver\"><\/a><\/p>\n<h2>UIBindingObserver<\/h2>\n<p>  2) \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 GeolocationViewController.swift \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u043a\u0430\u043a \u0432\u0435\u0448\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 Observer&#8217;\u044b \u043d\u0430 UI \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b<\/p>\n<pre><code>private extension UILabel {     var rx_driveCoordinates: AnyObserver&lt;CLLocationCoordinate2D&gt; {         return UIBindingObserver(UIElement: self) { label, location in             label.text = &quot;Lat: \\(location.latitude)\\nLon: \\(location.longitude)&quot;         }.asObserver()     } }<\/code><\/pre>\n<p>  \u0418\u0442\u0430\u043a, UIBindingObserver \u2014 generic \u043a\u043b\u0430\u0441\u0441 \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0432 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 location) \u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\/\u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e text). UIBindingObserver \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430 (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 UILabel, \u0442.\u043a. extension UILabel), \u0432 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0435 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u0441\u0430\u043c \u043e\u0431\u044a\u0435\u043a\u0442 (label) \u0442\u0430\u043a \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043c\u0435\u043d\u044f\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 (location)<br \/>  \u0422\u0438\u043f \u0434\u043b\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 location \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u043e\u043c, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f AnyObserver&lt;CLLocationCoordinate2D&gt;<br \/>  \u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 \u043d\u0435 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442<\/p>\n<pre><code>var rx_driveCoordinates: AnyObserver&lt;CLLocationCoordinate2D&gt; {     let observer = UIBindingObserver(UIElement: self) { label, location in         label.text = &quot;Lat: \\(location.latitude)\\nLon: \\(location.longitude)&quot;     }     return observer.asObserver() }<\/code><\/pre>\n<p>  \u0412\u0435\u0434\u044c \u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f observer, \u2014 UIBindingObserver \u043f\u043e\u043d\u044f\u0442\u0438\u044f \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043a\u0430\u043a\u043e\u0439 \u0442\u0438\u043f \u0431\u0443\u0434\u0435\u0442 \u0443 location, \u0432\u0435\u0434\u044c \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0438 \u043e\u0442 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u0430 \u043d\u0435 \u0438\u0434\u0435\u0442 \u0441\u0440\u0430\u0437\u0443 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u0438\u0437 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u044f. \u00ab\u041c\u0430\u0433\u0438\u044f\u00bb \u0430\u0432\u0442\u043e\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<br \/>  \u0410 \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0439 \u0443\u0436\u0435 \u043f\u043e\u0439\u0434\u0435\u0442, \u0442.\u043a. \u043c\u044b \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 UIBindingObserver \u0442\u0438\u043f \u0432\u0441\u0435\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432<\/p>\n<pre><code>var rx_driveCoordinates: AnyObserver&lt;CLLocationCoordinate2D&gt; {     let uiBindingObserver: UIBindingObserver&lt;UILabel, CLLocationCoordinate2D&gt; = UIBindingObserver(UIElement: self) { label, location in         label.text = &quot;Lat: \\(location.latitude)\\nLon: \\(location.longitude)&quot;     }     return uiBindingObserver.asObserver() }<\/code><\/pre>\n<p>  \u041f\u043e\u0434\u044b\u0442\u043e\u0436\u0438\u043c. \u0421 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u044d\u0442\u0430 \u0440\u0435\u043c\u0430\u0440\u043a\u0430 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u043a RxSwift, \u044d\u0442\u043e \u0441\u043a\u043e\u0440\u0435\u0435 \u043e\u0442\u0441\u044b\u043b\u043a\u0430 \u043a \u0442\u043e\u043c\u0443 \u043a\u0430\u043a Swift \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0442\u0438\u043f\u0430\u043c\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0438 \u0438\u0445 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c\u0443 \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u0438\u044e, \u0447\u0442\u043e \u0438\u0437\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0441 \u043e\u0442 \u0440\u0443\u0442\u0438\u043d\u043d\u043e\u0433\u043e \u044f\u0432\u043d\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432. \u0421 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u043c\u0430\u0433\u0438\u0438 \u0432 \u0431\u0438\u043d\u0434\u0438\u043d\u0433\u0430\u0445 RXSwift \u043d\u0435\u0442. \u0421\u043e \u0437\u043d\u0430\u043d\u0438\u0435\u043c \u0447\u0442\u043e \u043e\u0442\u043a\u0443\u0434\u0430 \u0431\u0435\u0440\u0435\u0442\u0441\u044f \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f, \u043c\u043e\u0436\u043d\u043e \u0434\u043b\u044f \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u043a\u0443, \u2014 \u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 \u043c\u044b \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u0446\u0432\u0435\u0442 \u0442\u0435\u043a\u0441\u0442\u0430 UILabel&#8217;\u0430 \u043c\u0435\u043d\u044f\u043b \u0446\u0432\u0435\u0442 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0432 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0442\u0438\u043f\u0430 Bool. \u0415\u0441\u043b\u0438 \u043e\u043d \u0440\u0430\u0432\u0435\u043d true \u043f\u0443\u0441\u0442\u044c \u0446\u0432\u0435\u0442 \u0442\u0435\u043a\u0441\u0442\u0430 \u0441\u0442\u0430\u043d\u0435\u0442 \u043a\u0440\u0430\u0441\u043d\u044b\u043c, \u0438 \u0447\u0435\u0440\u043d\u044b\u043c \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 false<br \/>  \u0412\u0441\u0435 \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u2014 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0439 \u043f\u0440\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438 Observer \u0442\u0438\u043f\u043e\u043c Bool, \u043d\u0443 \u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u044d\u0442\u0438\u043c \u0437\u043d\u0430\u043d\u0438\u0435\u043c \u0432\u043d\u0443\u0442\u0440\u0438 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u044f<\/p>\n<pre><code>var rx_wasError: AnyObserver&lt;Bool&gt; {     return UIBindingObserver(UIElement: self) { label, error in         label.textColor = error ? UIColor.redColor() : UIColor.blackColor()         }.asObserver() }<\/code><\/pre>\n<p>  \u0425\u043e\u0440\u043e\u0448\u043e, \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442, \u043f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u043d\u0430\u043c \u043d\u0435 \u0432\u0435\u0440\u043d\u0443\u0442\u044c UIBindingObserver, \u0437\u0430\u0447\u0435\u043c \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043a AnyObserver? \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0438\u043d\u0430\u0447\u0435 \u043d\u0430\u043c \u0431\u044b \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0442\u0438\u043f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0449\u0435 \u0438 \u0442\u0438\u043f\u043e\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430 (UILabel), \u0447\u0442\u043e \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u043d\u0435 \u0432\u0430\u0436\u043d\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0437\u0430\u0434\u0430\u0447\u0438. <\/p>\n<pre><code>var rx_driveCoordinatesUIB: UIBindingObserver&lt;UILabel, CLLocationCoordinate2D&gt; {     return UIBindingObserver(UIElement: self) { label, location in         label.text = &quot;Lat: \\(location.latitude)\\nLon: \\(location.longitude)&quot;         } }<\/code><\/pre>\n<p>  \u041f\u0440\u0430\u0432\u044b \u043b\u0438 \u043c\u044b? \u0421\u043c\u043e\u0442\u0440\u0438\u043c \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 AnyObserver<\/p>\n<p>  \/**<br \/>  A type-erased `ObserverType`.<\/p>\n<p>  Forwards operations to an arbitrary underlying observer with the same `Element` type, hiding the specifics of the underlying observer type.<br \/>  *\/<br \/>  \u0422\u0430\u043a \u0438 \u0435\u0441\u0442\u044c, AnyObserver \u2014 \u044d\u0442\u043e \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0442\u0438\u043f \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0438\u043f \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0432 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430.<\/p>\n<p>  \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c \u0437\u043d\u0430\u043d\u0438\u044f\u043c \u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043b\u0435\u0433\u043a\u043e \u0438 \u043f\u0440\u043e\u0441\u0442\u043e. \u0412 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0432 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0442\u0438\u043f\u0430 Bool \u043c\u044b \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u043c UIView, \u0438\u043b\u0438 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442 \u0434\u0435\u043b\u0430\u0435\u043c \u0432\u0438\u0434\u0438\u043c\u044b\u043c.<\/p>\n<pre><code>private extension UIView {     var rx_driveAuthorization: AnyObserver&lt;Bool&gt; {         return UIBindingObserver(UIElement: self) { view, authorized in             if authorized {                 view.hidden = true                 view.superview?.sendSubviewToBack(view)             }             else {                 view.hidden = false                 view.superview?.bringSubviewToFront(view)             }         }.asObserver()     } }<\/code><\/pre>\n<p>  <a name=\"ControlEvent\"><\/a>  <\/p>\n<h2>ControlEvent<\/h2>\n<p>  3) \u0427\u0442\u043e\u0431\u044b \u0432 Rx \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c target-event \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u0432\u0432\u0435\u043b\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 ControlEvent&lt;&gt;<br \/>  \u041e\u043d\u0430 \u043e\u0431\u043b\u0430\u0434\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438:<br \/>   \u2014 \u0435\u0435 \u043a\u043e\u0434 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0443\u043f\u0430\u0434\u0435\u0442<br \/>   \u2014 \u043f\u0440\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f<br \/>   \u2014 \u043f\u0440\u0438 \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0435\u043d\u0438\u0438 \u043f\u0430\u043c\u044f\u0442\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e .Completed<br \/>   \u2014 \u043d\u0430\u0440\u0443\u0436\u0443 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0432\u044b\u0439\u0434\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043e\u0448\u0438\u0431\u043e\u043a<br \/>   \u2014 \u0432\u0441\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043d\u0430 MainScheduler<\/p>\n<p>  \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443. \u0414\u043b\u044f UIButton \u0441\u043e\u0437\u0434\u0430\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435, \u0433\u0434\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e rx_tap  <\/p>\n<pre><code>extension UIButton {     \/**     Reactive wrapper for `TouchUpInside` control event.     *\/     public var rx_tap: ControlEvent&lt;Void&gt; { \t\treturn rx_controlEvent(.TouchUpInside)     }  }<\/code><\/pre>\n<p>  \u0414\u043b\u044f UIControl&#8217;\u0430 \u0436\u0435 \u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u043c\u0435\u0442\u043e\u0434<\/p>\n<pre><code>public func rx_controlEvent(controlEvents: UIControlEvents) -&gt; ControlEvent&lt;Void&gt; {     let source: Observable&lt;Void&gt; = Observable.create { [weak self] observer in         MainScheduler.ensureExecutingOnScheduler() \/\/ \u0443\u0431\u0435\u0436\u0434\u0430\u0435\u043c\u0441\u044f \u0447\u0442\u043e \u043c\u044b \u0432 Main \u043f\u043e\u0442\u043e\u043a\u0435          guard let control = self else { \/\/ \u0435\u0441\u043b\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b \u0443\u0436\u0435 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 - \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c .Competed              observer.on(.Completed)             return NopDisposable.instance         }          \/\/ \u0441\u0430\u043c\u043e\u0435 \u0432\u0430\u0436\u043d\u043e\u0435, \u0441\u043e\u0437\u0434\u0430\u0435\u043c ControlTarget \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0430, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 callback \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f         let controlTarget = ControlTarget(control: control, controlEvents: controlEvents) {             control in             observer.on(.Next())         }                  return AnonymousDisposable {             controlTarget.dispose()         }     }.takeUntil(rx_deallocated) \/\/ \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u043c \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043f\u0440\u0438 \u0434\u0435\u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0430          return ControlEvent(events: source) }<\/code><\/pre>\n<p>  \u0412\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 ControlTarget \u0443\u0436\u0435 \u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f<br \/>  control.addTarget(self, action: selector, forControlEvents: controlEvents)<\/p>\n<p>  \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0436\u0435 \u0442\u0430\u043a\u0438\u043c\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438 \u0442\u0430\u043a \u0436\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0430\u043a \u0438 \u043e\u0431\u044b\u0447\u043d\u044b\u043c\u0438 Observable<br \/>  \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440 GeolocationExample, \u0430 \u0442\u043e\u0447\u043d\u0435\u0435 \u043a\u043b\u0430\u0441\u0441 GeolocationViewController<\/p>\n<pre><code>class GeolocationViewController: ViewController {     @IBOutlet weak private var button: UIButton! ...     override func viewDidLoad() { ...         button.rx_tap             .bindNext { [weak self] in                 self?.openAppPreferences()             }             .addDisposableTo(disposeBag) ...     } ... }<\/code><\/pre>\n<p>  \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u043c bindNext \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u043f\u043e \u043a\u043d\u043e\u043f\u043a\u0435, \u0438 \u0432 \u043a\u043e\u0434\u0435 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u044f \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043f\u0430\u043d\u0435\u043b\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a.<br \/>  bindNext \u043a\u0441\u0442\u0430\u0442\u0438 \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 subscribe \u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043c\u044b \u0432 \u0433\u043b\u0430\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435<\/p>\n<pre><code>public func bindNext(onNext: E -&gt; Void) -&gt; Disposable {     return subscribe(onNext: onNext, onError: { error in         let error = &quot;Binding error: \\(error)&quot;         #if DEBUG             rxFatalError(error)         #else             print(error)         #endif     }) }<\/code><\/pre>\n<p>  \u0422\u0430\u043a \u0436\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0437 ControlEvent \u2014 Observable \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e .asObservable() \u0438\u043b\u0438 Driver \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e .asDriver()<\/p>\n<p>  <a name=\"ControlProperty\"><\/a>  <\/p>\n<h2>ControlProperty<\/h2>\n<p>  4) \u0427\u0442\u043e\u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0432\u0443\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u044e\u044e \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c UI \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 ControlProperty&lt;&gt; \u043e\u0431\u043b\u0430\u0434\u0430\u044e\u0449\u0430\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438<\/p>\n<p>   \u2014 \u0435\u0451 \u043a\u043e\u0434 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0443\u043f\u0430\u0434\u0435\u0442<br \/>   \u2014 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d shareReplay(1)<br \/>   \u2014 \u043f\u0440\u0438 \u043e\u0441\u043e\u0432\u043e\u0431\u043e\u0436\u0434\u0435\u043d\u0438\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043e\u043c \u043f\u0430\u043c\u044f\u0442\u0438 \u0431\u0443\u0434\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e .Completed<br \/>   \u2014 \u043d\u0430\u0440\u0443\u0436\u0443 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0432\u044b\u0439\u0434\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043e\u0448\u0438\u0431\u043e\u043a<br \/>   \u2014 \u0432\u0441\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043d\u0430 MainScheduler<\/p>\n<p>  \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435 \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e text \u043e\u0442 UITextField<\/p>\n<pre><code>extension UITextField {     \/**     Reactive wrapper for `text` property.     *\/     public var rx_text: ControlProperty&lt;String&gt; {         return UIControl.rx_value(             self,             getter: { textField in                 textField.text ?? &quot;&quot;             }, setter: { textField, value in                 textField.text = value             }         )     } }<\/code><\/pre>\n<p>  \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0442\u043e \u0438\u0437 \u0441\u0435\u0431\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0435\u0442\u043e\u0434 rx_value<\/p>\n<pre><code>static func rx_value&lt;C: AnyObject, T: Equatable&gt;(control: C, getter: (C) -&gt; T, setter: (C, T) -&gt; Void) -&gt; ControlProperty&lt;T&gt; {         let source: Observable&lt;T&gt; = Observable.create { [weak weakControl = control] observer in                 guard let control = weakControl else { \/\/ \u0435\u0441\u043b\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b \u0443\u0436\u0435 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 - \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c .Competed                      observer.on(.Completed)                     return NopDisposable.instance                 }                  observer.on(.Next(getter(control))) \/\/ \u0441\u0440\u0430\u0437\u0443 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0430 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u0433\u043e getter'\u0430  \t\t\t\t\/\/ \u0441\u044e\u0440\u043f\u0440\u0438\u0437, \u0438 \u0441\u043d\u043e\u0432\u0430 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u044b\u0439 \u0440\u0430\u043d\u0435\u0435 ControlTarget                 let controlTarget = ControlTarget(control: control as! UIControl, controlEvents: [.AllEditingEvents, .ValueChanged]) { _ in                     if let control = weakControl {                         observer.on(.Next(getter(control)))                     }                 }                                  return AnonymousDisposable {                     controlTarget.dispose()                 }             }             .distinctUntilChanged() \/\/ \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u043b\u043e\u0441\u044c             .takeUntil((control as! NSObject).rx_deallocated) \/\/ \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u043c \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043f\u0440\u0438 \u0434\u0435\u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0430          \/\/ \u0438 \u0441\u043d\u043e\u0432\u0430 \u0441\u044e\u0440\u043f\u0440\u0438\u0437, \u0441\u0442\u0430\u0440\u044b\u0439 \u0434\u043e\u0431\u0440\u044b\u0439 UIBindingObserver \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 Observable \u043a \u043f\u043e\u043b\u044e \u0447\u0435\u0440\u0435\u0437 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0439 setter         let bindingObserver = UIBindingObserver(UIElement: control, binding: setter)           return ControlProperty&lt;T&gt;(values: source, valueSink: bindingObserver)     } }<\/code><\/pre>\n<p>  \u041a\u0430\u043a \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u0434\u0432\u0443\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u044f\u044f \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 \u2014 \u044d\u0442\u043e \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f \u0443\u0436\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u044b\u0445 ControlTarget \u0438 UIBindingObserver<br \/>  \u0415\u0441\u043b\u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 ControlProperty, \u0442\u043e \u0432\u0438\u0434\u043d\u043e \u0447\u0442\u043e \u043e\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b ControlPropertyType, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043e\u0442 ObservableType, \u0442\u0430\u043a \u0438 \u043e\u0442 ObserverType. <br \/>  \u0415\u0449\u0435 \u0440\u0430\u0437 \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u043a\u043e\u0434 IntroductionExampleViewController <\/p>\n<pre><code>@IBOutlet var a: NSTextField! @IBOutlet var b: NSTextField! @IBOutlet var c: NSTextField! ...  override func viewDidLoad() { ... \t\/\/\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c ControlProperty \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a\u0430\u043a \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 Observable     let sum = Observable.combineLatest(a.rx_text, b.rx_text) { (a: String, b: String) -&gt; (Int, Int) in         return (Int(a) ?? 0, Int(b) ?? 0)     } ...     sum         .map { (a, b) in             return &quot;\\(a + b)&quot;         }         .bindTo(c.rx_text) \/\/\u0442\u0430\u043a \u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 Observer'\u0430         .addDisposableTo(disposeBag) }<\/code><\/pre>\n<p>  \u0415\u0441\u043b\u0438 \u0436\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043e\u0431\u0430 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f, \u0442.\u0435. \u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0432\u0443\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u044e\u044e \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u2014 \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0432 \u043a\u043e\u0434\u0435 Rx<\/p>\n<pre><code>infix operator &lt;-&gt; { }  func &lt;-&gt; &lt;T&gt;(property: ControlProperty&lt;T&gt;, variable: Variable&lt;T&gt;) -&gt; Disposable {     let bindToUIDisposable = variable.asObservable()         .bindTo(property)     let bindToVariable = property         .subscribe(onNext: { n in             variable.value = n         }, onCompleted:  {             bindToUIDisposable.dispose()         })      return StableCompositeDisposable.create(bindToUIDisposable, bindToVariable) }<\/code><\/pre>\n<p>  \u041e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u043f\u0440\u043e\u0441\u0442\u043e \u0438 \u044f\u0441\u043d\u043e<\/p>\n<pre><code>let textViewValue = Variable(&quot;&quot;) textView.rx_text &lt;-&gt; textViewValue<\/code><\/pre>\n<p>  <a name=\"DelegateProxy\"><\/a>  <\/p>\n<h2>DelegateProxy<\/h2>\n<p>  5) \u043a\u0440\u0430\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u044b\u0439 \u043a\u0430\u043c\u0435\u043d\u044c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b Cocoa \u2014 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u044b. \u041d\u043e \u043e\u0431\u044b\u0447\u043d\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u2014 \u043e\u0434\u0438\u043d \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u043d\u0430 \u043e\u0434\u0438\u043d \u043e\u0431\u044a\u0435\u043a\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 Rx \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043a\u043b\u0430\u0441\u0441 DelegateProxy, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0434\u0435\u043b\u0435\u0433\u0430\u0442, \u0442\u0430\u043a \u0438 Rx \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>  \u0421 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e API \u043d\u0438\u0447\u0435\u0433\u043e \u0432\u0440\u043e\u0434\u0435 \u043e\u0441\u043e\u0431\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e \u0438 \u043d\u0435\u0442.<br \/>  \u0412\u043e\u0437\u044c\u043c\u0435\u043c \u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 UISearchBar, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043a\u0430\u043a \u0442\u043e \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u043a\u043d\u043e\u043f\u043a\u0438 Cancel. \u0414\u043b\u044f \u043d\u0430\u0441 \u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0438 \u0434\u043b\u044f \u043a\u043b\u0430\u0441\u0441\u0430 UISearchBar \u0441\u043e\u0437\u0434\u0430\u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f <\/p>\n<pre><code>public var rx_cancelButtonClicked: ControlEvent&lt;Void&gt; {         let source: Observable&lt;Void&gt; = rx_delegate.observe(#selector(UISearchBarDelegate.searchBarCancelButtonClicked(_:)))             .map { _ in                 return ()             }         return ControlEvent(events: source)     }<\/code><\/pre>\n<p>  \u0420\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0435\u0439 \u043b\u0435\u0433\u043a\u043e \u0438 \u043f\u0440\u043e\u0441\u0442\u043e:  <\/p>\n<pre><code>searchBar.rx_cancelButtonClicked.subscribeNext { _ in             \/\/ \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f         }<\/code><\/pre>\n<p>  \u0410 \u0432\u043e\u0442 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 tableView \u043c\u0435\u043d\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0441\u0441\u0442\u0440\u043e\u0438\u043b\u0430.<br \/>  \u0415\u0441\u043b\u0438 \u0432\u0437\u044f\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440 (SimpleTableViewExample), \u0442\u043e \u0432\u0441\u0435 \u043f\u0440\u043e\u0441\u0442\u043e<\/p>\n<pre><code>class SimpleTableViewExampleViewController : ViewController {     @IBOutlet weak var tableView: UITableView!      override func viewDidLoad() {         super.viewDidLoad()          \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c Observable  \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432         let items = Observable.just([             &quot;First Item&quot;,             &quot;Second Item&quot;,             &quot;Third Item&quot;         ])  \t\t\/\/ \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u043c \u044d\u0442\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0441 tableView (\u0432\u043d\u0443\u0442\u0440\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u043a\u0441\u0438 dataSource), \u0442\u0430\u043a \u0436\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044f \u0444\u0430\u0431\u0440\u0438\u043a\u0443 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u044f\u0447\u0435\u0435\u043a         items             .bindTo(tableView.rx_itemsWithCellIdentifier(&quot;Cell&quot;, cellType: UITableViewCell.self)) { (row, element, cell) in                 cell.textLabel?.text = &quot;\\(element) @ row \\(row)&quot;             }             .addDisposableTo(disposeBag)  \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0440\u0435\u0430\u043a\u0446\u0438\u044e \u043d\u0430 \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u043f\u043e \u0441\u0442\u0440\u043e\u043a\u0435, rx_modelSelected - \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 tableView:didSelectRowAtIndexPath:         tableView             .rx_modelSelected(String)             .subscribeNext { value in                 DefaultWireframe.presentAlert(&quot;Tapped `\\(value)`&quot;)             }             .addDisposableTo(disposeBag)  \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0440\u0435\u0430\u043a\u0446\u0438\u044e \u043d\u0430 \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u043f\u043e \u043a\u043d\u043e\u043f\u043a\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 - \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 tableView(_:accessoryButtonTappedForRowWithIndexPath:)         tableView             .rx_itemAccessoryButtonTapped             .subscribeNext { indexPath in                 DefaultWireframe.presentAlert(&quot;Tapped Detail @ \\(indexPath.section),\\(indexPath.row)&quot;)             }             .addDisposableTo(disposeBag)      } }<\/code><\/pre>\n<p>  \u041a\u043b\u0430\u0441\u0441\u043d\u043e, rx_itemsWithCellIdentifier \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u0432 \u0441\u0430\u043c\u043e\u043c Rx, \u0442\u0430\u043a \u0447\u0442\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432\u0441\u0435\u043c. \u041e\u043a. \u0410 \u043a\u0430\u043a \u0434\u0435\u043b\u0430 \u043e\u0431\u0441\u0442\u043e\u044f\u0442 \u0441 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\u0439 \u0441 \u0441\u0435\u043a\u0446\u0438\u044f\u043c\u0438? \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440 SimpleTableViewExampleSectioned<\/p>\n<pre><code>class SimpleTableViewExampleSectionedViewController     : ViewController     , UITableViewDelegate {     @IBOutlet weak var tableView: UITableView!      let dataSource = RxTableViewSectionedReloadDataSource&lt;SectionModel&lt;String, Double&gt;&gt;()      override func viewDidLoad() {         super.viewDidLoad()          let dataSource = self.dataSource          let items = Observable.just([             SectionModel(model: &quot;First section&quot;, items: [                     1.0,                     2.0,                     3.0                 ]),             SectionModel(model: &quot;Second section&quot;, items: [                     1.0,                     2.0,                     3.0                 ]),             SectionModel(model: &quot;Second section&quot;, items: [                     1.0,                     2.0,                     3.0                 ])             ])          dataSource.configureCell = { (_, tv, indexPath, element) in             let cell = tv.dequeueReusableCellWithIdentifier(&quot;Cell&quot;)!             cell.textLabel?.text = &quot;\\(element) @ row \\(indexPath.row)&quot;             return cell         }          items             .bindTo(tableView.rx_itemsWithDataSource(dataSource))             .addDisposableTo(disposeBag)          tableView             .rx_itemSelected             .map { indexPath in                 return (indexPath, dataSource.itemAtIndexPath(indexPath))             }             .subscribeNext { indexPath, model in                 DefaultWireframe.presentAlert(&quot;Tapped `\\(model)` @ \\(indexPath)&quot;)             }             .addDisposableTo(disposeBag)          tableView             .rx_setDelegate(self)             .addDisposableTo(disposeBag)     }      func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -&gt; UIView? {         let label = UILabel(frame: CGRect.zero)         label.text = dataSource.sectionAtIndex(section).model ?? &quot;&quot;         return label     } }<\/code><\/pre>\n<p>  \u041e\u0431\u0440\u0430\u0449\u0430\u0435\u043c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 RxTableViewSectionedReloadDataSource, \u0430 \u0433\u0434\u0435 \u043e\u043d \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d? \u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 RxExample, \u0442.\u0435. \u043a\u0430\u043a \u044f \u043f\u043e\u043d\u0438\u043c\u0430\u044e \u044d\u0442\u043e \u043d\u0435 \u043e\u0431\u043a\u0430\u0442\u0430\u043d\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0432\u0441\u0435\u043c, \u0430 \u0442\u0430\u043a, \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430. \u0415\u0441\u043b\u0438 \u0437\u0430\u0433\u043b\u044f\u043d\u0443\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u044c, \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0448\u044c \u043f\u043e\u0447\u0435\u043c\u0443, \u0442\u0430\u043c \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0447\u0438\u0445 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0442 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0432\u0441\u0435\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u044b<\/p>\n<pre><code>public func tableView(tableView: UITableView, observedEvent: Event&lt;Element&gt;) {     UIBindingObserver(UIElement: self) { dataSource, element in         dataSource.setSections(element)         tableView.reloadData()     }.on(observedEvent) } <\/code><\/pre>\n<p>  \u041c\u044f\u0433\u043a\u043e \u0433\u043e\u0432\u043e\u0440\u044f \u043d\u0435 \u0441\u0430\u043c\u043e\u0435 \u043b\u0443\u0447\u0448\u0435\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u041a\u0430\u043a\u0438\u0435 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u044b? \u041e\u043f\u044f\u0442\u044c \u0442\u0430\u043a\u0438 \u0432 RxExample \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u043a\u043b\u0430\u0441\u0441 RxTableViewSectionedAnimatedDataSource. \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u044d\u0442\u0438\u043c dataSource \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043f\u0440\u0438\u043c\u0435\u0440 TableViewPartialUpdates. \u041e\u043d \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0432 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438 \u043a\u0430\u043a \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445 \u0441 \u0441\u0435\u043a\u0446\u0438\u044f\u043c\u0438 \u043a\u0430\u043a \u0441 \u043f\u043e\u043b\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 (RxTableViewSectionedReloadDataSource), \u0442\u0430\u043a \u0438 \u0441 \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e\u0439 (RxTableViewSectionedAnimatedDataSource). \u0417\u0434\u0435\u0441\u044c \u0436\u0435 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 CollectionView. \u041d\u043e \u0432\u0441\u0435 \u044d\u0442\u043e \u0431\u0435\u0437 \u0443\u0447\u0435\u0442\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<br \/>  \u0427\u0442\u043e \u0436\u0435, \u043c\u043d\u0435 \u0438 \u043a\u0430\u0440\u0442\u044b \u0432 \u0440\u0443\u043a\u0438, \u0441\u043e\u0437\u0434\u0430\u043c \u043a\u0430 \u044f \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\u0439 \u0441 \u0441\u0435\u043a\u0446\u0438\u044f\u043c\u0438 \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041f\u0440\u0438\u043c\u0435\u0440 TableViewEditPartialUpdate \u044f \u043f\u043e\u043b\u043e\u0436\u0438\u043b \u043a \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c \u0432 RxExample.<\/p>\n<p>  \u0423\u0447\u0438\u0442\u044b\u0432\u0430\u044f \u0447\u0442\u043e \u044d\u0442\u043e \u0431\u044b\u043b \u043c\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043e\u043f\u044b\u0442 \u00ab\u0431\u043e\u0435\u0432\u043e\u0433\u043e\u00bb \u043a\u043e\u0434\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 GUI \u0432 RxSwift \u044f \u0442\u0443\u0442 \u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0441\u0432\u043e\u044e \u043f\u043e\u0440\u0446\u0438\u044e \u0433\u0440\u0430\u0431\u043b\u0435\u0439.<\/p>\n<pre><code>class TablViewControllerEditPartialUpdate : ViewController {     @IBOutlet weak var tableView: UITableView!     var sections = Variable([NumberSection]())          override func viewDidLoad() {         super.viewDidLoad()          \/\/ NumberSection - \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 typealias AnimatableSectionModel&lt;String, Int&gt;         let items = [             NumberSection(model: &quot;Section 1&quot;, items: [1, 3, 5]),             NumberSection(model: &quot;Section 2&quot;, items: [2, 4, 6, 8]),             NumberSection(model: &quot;Section 3&quot;, items: [7, 11, 10])         ]         self.sections.value = items         let editableDataSource = RxTableViewSectionedAnimatedDataSource&lt;NumberSection&gt;()                  configDataSource(editableDataSource)          \/\/ \u0437\u0430\u043c\u0435\u0447\u0443 \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f rx_itemsAnimatedWithDataSource, \u0430 \u043d\u0435 rx_itemsWithDataSource         self.sections.asObservable()             .bindTo(tableView.rx_itemsAnimatedWithDataSource(editableDataSource))             .addDisposableTo(disposeBag)                  \/\/ \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438\u0437 \u043c\u043e\u0434\u0435\u043b\u0438         tableView.rx_itemDeleted.subscribeNext{[weak self] item in             if let controller = self {                 controller.sections.value[item.section].items.removeAtIndex(item.row)             }             }.addDisposableTo(disposeBag)                  \/\/ \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u044b         tableView             .rx_modelSelected(IdentifiableValue&lt;Int&gt;)             .subscribeNext { i in                 DefaultWireframe.presentAlert(&quot;Tapped `\\(i)`&quot;)             }             .addDisposableTo(disposeBag)                  \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c NSIndexPath \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0447\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043c\u043e\u0433\u043b\u043e \u043f\u0440\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u0442\u0438\u043f\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u0430         tableView             .rx_itemSelected             .subscribeNext { [weak self]  i in                 if let controller = self {                     print(&quot;Tapped `\\(i)` - \\(controller.sections.value[i.section].items[i.row].dynamicType)&quot;)                 }             }             .addDisposableTo(disposeBag)     }          func configDataSource(dataSource: RxTableViewSectionedDataSource&lt;NumberSection&gt;) {         dataSource.configureCell = { (_, tv, ip, i) in             let cell = tv.dequeueReusableCellWithIdentifier(&quot;Cell&quot;)                 ?? UITableViewCell(style:.Default, reuseIdentifier: &quot;Cell&quot;)             cell.textLabel!.text = &quot;\\(i)&quot;             return cell         }                  dataSource.titleForHeaderInSection = { (ds, section: Int) -&gt; String in             return dataSource.sectionAtIndex(section).model         }                  dataSource.canEditRowAtIndexPath = { (ds, ip) in             return true         }     } }<\/code><\/pre>\n<p>  1) \u042f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u044d\u0442\u043e\u0442 \u043a\u043e\u0434, \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u043b \u0441\u0432\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f TableViewController \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0432 storyboard \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c. \u041e\u0448\u0438\u0431\u043a\u0430.   <\/p>\n<pre><code>fatal error: Failure converting from &lt;RxExample_iOS.TableViewControllerEditPartialUpdate: 0x7f895a643dd0&gt; to UITableViewDataSource: file \/Users\/SparkLone\/projects\/repos\/RxSwift\/RxCocoa\/Common\/RxCocoa.swift, line 340<\/code><\/pre>\n<p>  \u041d\u0430\u0434\u043e \u0436\u0435. \u0414\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0441\u0440\u0430\u0437\u0443 \u044f \u043f\u043e\u043d\u044f\u043b \u0432 \u0447\u0435\u043c \u0434\u0435\u043b\u043e. \u041c\u043d\u043e\u0433\u043e Rx \u043a\u043e\u0434\u0430 \u043f\u043e\u043a\u043e\u0432\u044b\u0440\u044f\u043b \u0432 \u0442\u0449\u0435\u0442\u043d\u043e\u0439 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u043f\u0440\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0434\u0435\u0431\u0440\u0438. \u0410 \u0434\u0435\u043b\u043e \u0431\u044b\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 ViewTableController&#8217;\u0430 \u0432 \u0434\u0438\u0437\u0430\u0439\u043d\u0435\u0440\u0435 \u043e\u043d \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430\u0448 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 dataSource. \u0410 \u043a\u043e\u0433\u0434\u0430 Rx \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043f\u0440\u043e\u043a\u0441\u0438 \u2014 \u043e\u043d \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u043a\u0443\u0449\u0438\u0439 dataSource \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0430\u043a forwardToDelegate. \u0410 \u043c\u043e\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 DataSource \u0432 \u043a\u0430\u043d\u043e\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0432\u0438\u0434\u0435. \u0412\u0438\u043d\u0438\u0442\u044c \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u043d\u0435\u043a\u043e\u0433\u043e, \u043d\u043e \u0432\u0438\u0434\u0438\u043c\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 \u0442\u0430\u043a\u043e\u0433\u043e \u0440\u043e\u0434\u0430, \u043f\u043e\u0434\u0441\u043e\u0437\u043d\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u0448\u044c \u043a\u0430\u043a\u0438\u0445 \u0442\u043e \u0445\u0438\u0442\u0440\u044b\u0445 \u0431\u0430\u0433\u043e\u0432.<\/p>\n<p>  2) \u041e\u043a\u0435\u0439, \u0445\u043e\u0442\u0435\u043b\u0438 \u0445\u0438\u0442\u0440\u044b\u0445 \u0431\u0430\u0433\u043e\u0432, \u2014 \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430.<br \/>  \u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0432\u043c\u0435\u0441\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0438<\/p>\n<pre><code>rx_modelSelected(IdentifiableValue&lt;Int&gt;)<\/code><\/pre>\n<p>  \u0431\u044b\u043b\u0430 <\/p>\n<pre><code>rx_modelSelected(Int)<\/code><\/pre>\n<p>  \u0438 \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u044f \u0441\u043b\u043e\u0432\u0438\u043b \u0434\u0440\u0443\u0433\u0443\u044e \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443.<\/p>\n<pre><code>fatal error: Failure converting from 4 to Int: file \/Users\/SparkLone\/projects\/repos\/RxSwift\/RxCocoa\/Common\/RxCocoa.swift, line 340<\/code><\/pre>\n<p>  \u041d\u0443 \u0434\u0430, \u043a\u0430\u043a \u0436\u0435 4 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a Int \u0442\u043e. \u041f\u043e\u0441\u043b\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0433\u043e \u0431\u0435\u0437\u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u044f\u0441\u043d\u0438\u0442\u044c \u043a\u0430\u043a\u043e\u0439 \u0436\u0435 \u0442\u0438\u043f \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0432\u043c\u0435\u0441\u0442\u043e Int, \u044f \u0434\u043e\u0433\u0430\u0434\u0430\u043b\u0441\u044f \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0435\u0433\u043e \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c<\/p>\n<pre><code>tableView     .rx_itemSelected     .subscribeNext { [weak self]  i in         if let controller = self {             print(&quot;Tapped `\\(i)` - \\(controller.sections.value[i.section].items[i.row].dynamicType)&quot;)         }     }     .addDisposableTo(disposeBag)<\/code><\/pre>\n<p>  \u042d\u0442\u0443 \u043e\u0448\u0438\u0431\u043a\u0443 \u044f \u043c\u043e\u0433\u0443 \u043f\u0440\u0438\u043d\u044f\u0442\u044c \u043d\u0430 \u0441\u0432\u043e\u0439 \u0441\u0447\u0435\u0442 \u0443\u0436\u0435 \u0441 \u043d\u0430\u0442\u044f\u0436\u043a\u043e\u0439, \u043d\u0438\u0433\u0434\u0435 \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u044f \u043d\u0438 \u043f\u0440\u043e \u043a\u0430\u043a\u043e\u0439 IdentifiableValue \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u043d\u0435 \u0431\u044b\u043b\u043e.<\/p>\n<p>  3) \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u044f \u0443\u043a\u0430\u0437\u0430\u043b \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0435\u043a\u0446\u0438\u0438 \u043d\u0435 [1, 3, 5] \u0430 [1, 3, 3]<br \/>  \u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0430\u043b\u043e, \u043d\u043e \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0435\u043a\u0446\u0438\u0438 \u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0443\u0436\u0435 \u0442\u0430\u043a\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443<\/p>\n<pre><code>precondition failed: Item 3 has already been indexed at (0, 1): file \/Users\/SparkLone\/projects\/repos\/RxSwift\/RxExample\/RxDataSources\/DataSources\/Differentiator.swift, line 130<\/code><\/pre>\n<p>  \u041a\u0430\u043a \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u0437\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u0432 \u0441\u0442\u0440\u043e\u043a\u0430\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0441\u0442\u0440\u043e\u043a \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b. \u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0433\u0430\u0434\u0430\u0442\u044c\u0441\u044f, \u0432\u044b\u044f\u0441\u043d\u0438\u043b \u044d\u0442\u043e \u044f \u0442\u043e\u0436\u0435 \u043d\u0435 \u0441\u0440\u0430\u0437\u0443. <\/p>\n<p>  \u041f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0432\u0441\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432\u0440\u043e\u0434\u0435 \u0431\u044b \u043a\u0430\u043a\u0438\u0435 \u0442\u043e \u043d\u0435\u0441\u0435\u0440\u044c\u0435\u0437\u043d\u044b\u0435, \u0438 \u0432\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u0437 \u043d\u0430 \u0442\u0435 \u0436\u0435 \u0433\u0440\u0430\u0431\u043b\u0438 \u0443\u0436\u0435 \u043d\u0435 \u043d\u0430\u0441\u0442\u0443\u043f\u0438\u0448\u044c. \u041d\u043e \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u044f \u043f\u043e\u0442\u0440\u0430\u0442\u0438\u0442\u044c \u043f\u043e\u043b\u0447\u0430\u0441\u0430, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0431\u0440\u043e\u0441\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\u0439, \u2014 \u043a\u0440\u0430\u0439\u043d\u0435 \u043d\u0435\u043f\u0440\u0438\u044f\u0442\u043d\u043e \u043d\u044b\u0440\u044f\u0442\u044c \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c \u043f\u043e\u0447\u0435\u043c\u0443 \u0432\u0441\u0435 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0440\u0430\u0437. \u0410 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044f \u043d\u0435\u043b\u0438\u043d\u0435\u0439\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u0436\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0442\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u043e (\u0431\u044b\u0441\u0442\u0440\u043e) \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u043d\u044f\u0442\u044c \u0432 \u0447\u0435\u043c \u0434\u0435\u043b\u043e. \u041e\u0447\u0435\u043d\u044c \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u0447\u0442\u043e \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0441\u0435\u0445 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439, \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0430\u044f \u0438 \u0432\u043d\u044f\u0442\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f. \u0414\u043b\u044f \u043c\u0435\u043d\u044f \u0436\u0435 \u043f\u0435\u0440\u0432\u044b\u0439 \u0431\u043b\u0438\u043d \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043a\u043e\u043c\u043e\u043c.<\/p>\n<p>  \u0425\u043e\u0440\u043e\u0448\u043e, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a \u0432\u0441\u0435 \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/90e\/52a\/15c\/90e52a15cf29484b82bb3d0ad502ea06.png\"\/><\/p>\n<p>  \u041c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043d\u0430\u0434 UIView subclass, \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0435\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e rx_delegate, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043f\u0440\u043e\u043a\u0441\u0438 \u0434\u043b\u044f \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430. \u0414\u0430\u043b\u0435\u0435 \u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0438 \u043f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u043d\u0430\u0434 \u0442\u0435\u043c\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c. \u041a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u044d\u0442\u0438 \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u043d\u0430\u0434 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438, \u0438 \u043f\u0440\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u0440\u043e\u043a\u0441\u0438 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 Observable \u044d\u043b\u0435\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443, \u0437\u0430\u0442\u0435\u043c \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u2014 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 (\u0434\u0435\u043b\u0430\u0435\u0442 forward, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e API \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430) \u0435\u0433\u043e \u043e\u0431\u044b\u0447\u043d\u043e\u043c\u0443 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0443, \u0435\u0441\u043b\u0438 \u043e\u043d \u0431\u044b\u043b \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f Rx \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430. <\/p>\n<p>  \u0412 \u043e\u0441\u043d\u043e\u0432\u0435 \u043b\u0435\u0436\u0438\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b <\/p>\n<pre><code>protocol DelegateProxyType { \t\/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0430\u044f \u0437\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u043a\u0441\u0438 \tstatic func createProxyForObject(object: AnyObject) -&gt; AnyObject  \t\/\/ \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u0435\u043c \u043f\u0440\u043e\u043a\u0441\u0438 \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0443 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c objc_setAssociatedObject  \tstatic func assignProxy(proxy: AnyObject, toObject object: AnyObject) \t\/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u043a\u0441\u0438 \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0443 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c objc_getAssociatedObject     static func assignedProxyFor(object: AnyObject) -&gt; AnyObject?               \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0435 \u0437\u0430 \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u0435 \/ \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043e\u0431\u044b\u0447\u043d\u043e\u043c\u0443(\u043d\u0435 Rx) \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0443     func setForwardToDelegate(forwardToDelegate: AnyObject?, retainDelegate: Bool)     func forwardToDelegate() -&gt; AnyObject?           \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0435 \u0437\u0430 \u043f\u0440\u0438\u0441\u0432\u043e\u0435\u043d\u0438\u0435 \/ \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0443-\u043f\u0440\u043e\u043a\u0441\u0438, \u0441 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435\u043c \u0442\u0438\u043f\u043e\u0432     static func currentDelegateFor(object: AnyObject) -&gt; AnyObject?     static func setCurrentDelegate(delegate: AnyObject?, toObject object: AnyObject) }<\/code><\/pre>\n<p>  \u0422\u0430\u043a \u0436\u0435 \u0435\u0441\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 DelegateProxy \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u0435\u0440\u0432\u044b\u0435 5 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430. \u041e\u0441\u0442\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u0434\u0432\u0430 \u043e\u0431\u044b\u0447\u043d\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u0442.\u043a. \u0438\u043c\u0435\u043d\u043d\u043e \u043e\u043d\u0438 \u0437\u043d\u0430\u044e\u0442 \u043a\u0430\u043a\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c UI \u043e\u0431\u044a\u0435\u043a\u0442 \u0438 \u043a\u0430\u043a\u043e\u0435 \u0438\u043c\u044f \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0435 \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u0432 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c UIControl<\/p>\n<pre><code>class DelegateProxy { \tpublic class func createProxyForObject(object: AnyObject) -&gt; AnyObject {} \tpublic class func assignedProxyFor(object: AnyObject) -&gt; AnyObject? {} \tpublic class func assignProxy(proxy: AnyObject, toObject object: AnyObject) {} \tpublic func setForwardToDelegate(delegate: AnyObject?, retainDelegate: Bool) {} \tpublic func forwardToDelegate() -&gt; AnyObject? {} }<\/code><\/pre>\n<p>  \u0427\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0447\u0443\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0439 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 UISearchController.<br \/>  \u0414\u043b\u044f \u043d\u0435\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435<\/p>\n<pre><code>extension UISearchController { \t\/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u043d\u0430\u0434 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u043e\u043c, \u0441\u043e\u0437\u0434\u0430\u044e\u0449\u0443\u044e \u043d\u0430\u0448 \u043f\u0440\u043e\u043a\u0441\u0438 RxSearchControllerDelegateProxy     public var rx_delegate: DelegateProxy {         return proxyForObject(RxSearchControllerDelegateProxy.self, self)     }      \/\/ Rx \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u043c UISearchControllerDelegate.didDismissSearchController(_:)     public var rx_didDismiss: Observable&lt;Void&gt; {         return rx_delegate             .observe(#selector(UISearchControllerDelegate.didDismissSearchController(_:)))             .map {_ in}     }     ... } <\/code><\/pre>\n<p>  \u041f\u0440\u043e\u043a\u0441\u0438 \u0434\u043b\u044f UISearchController \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f RxSearchControllerDelegateProxy<\/p>\n<pre><code>public class RxSearchControllerDelegateProxy     : DelegateProxy     , DelegateProxyType     , UISearchControllerDelegate {          \/\/ \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430 (\u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u043a\u0441\u0438) \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0437\u043d\u0430\u0442\u044c \u0442\u0438\u043f \u043a\u043b\u0430\u0441\u0441\u0430 (UISearchController) \u0438 \u0438\u043c\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430 (delegate)     public class func setCurrentDelegate(delegate: AnyObject?, toObject object: AnyObject) {         let searchController: UISearchController = castOrFatalError(object)         searchController.delegate = castOptionalOrFatalError(delegate)     }          \/\/ \u0442\u0435 \u0436\u0435 \u0437\u043d\u0430\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u0438 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0440\u043e\u043a\u0441\u0438 \u043f\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0443     public class func currentDelegateFor(object: AnyObject) -&gt; AnyObject? {         let searchController: UISearchController = castOrFatalError(object)         return searchController.delegate     } }<\/code><\/pre>\n<p>  \u041a\u043e\u043f\u043d\u0435\u043c \u0447\u0443\u0442\u044c \u0433\u043b\u0443\u0431\u0436\u0435.<\/p>\n<p>  \u041f\u0440\u043e\u043a\u0441\u0438 \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e   <\/p>\n<pre><code>proxyForObject(RxSearchControllerDelegateProxy.self, self)<\/code><\/pre>\n<p>  proxyForObject \u2014 \u044d\u0442\u043e \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u044f\u0434\u0440\u043e \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0440\u043e\u043a\u0441\u0438 \u0434\u043b\u044f \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u043e\u0432. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0435\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0442\u0438\u043f \u043f\u0440\u043e\u043a\u0441\u0438 (RxSearchControllerDelegateProxy.self) \u0438 \u043e\u0431\u044a\u0435\u043a\u0442 \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u0442\u044c \u043f\u0440\u043e\u043a\u0441\u0438.<\/p>\n<p>  \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 type \u0431\u0443\u0434\u0435\u0442 RxSearchControllerDelegateProxy, object \u2014 \u0442\u0435\u043a\u0443\u0449\u0438\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u0442\u0438\u043f\u0430 UISearchController<\/p>\n<pre><code>public func proxyForObject&lt;P: DelegateProxyType&gt;(type: P.Type, _ object: AnyObject) -&gt; P {     MainScheduler.ensureExecutingOnScheduler() \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0447\u0442\u043e \u043a\u043e\u0434 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0433\u043b\u0430\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435          let maybeProxy = P.assignedProxyFor(object) as? P \/\/ assignedProxyFor \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430 \u0432 DelegateProxy \u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u0433\u0434\u0435 \u043d\u0435 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f          let proxy: P     if maybeProxy == nil {         proxy = P.createProxyForObject(object) as! P \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u043e\u043a\u0441\u0438 (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0442\u0438\u043f\u0430 RxSearchControllerDelegateProxy). \u041c\u0435\u0442\u043e\u0434 createProxyForObject \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u0432 DelegateProxy \u0438 \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u043a\u0441\u0438, \u043d\u043e \u0435\u0433\u043e \u043c\u043e\u0433\u0443\u0442 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043a\u043b\u0430\u0441\u0441\u044b \u0441 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435\u043c, \u0434\u043b\u044f \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043d\u0443\u0436\u0435\u043d \u0441\u0432\u043e\u0439 \u0434\u0435\u043b\u0435\u0433\u0430\u0442         P.assignProxy(proxy, toObject: object) \/\/ \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u043a\u0441\u0438 \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0443. assignProxy \u0442\u0430\u043a \u0436\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u0432 DelegateProxy, \u0438 \u0435\u0433\u043e \u043d\u0435 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442, \u043a\u0430\u043a \u0438 assignedProxyFor         assert(P.assignedProxyFor(object) === proxy)     }     else {         proxy = maybeProxy! \/\/ \u0435\u0441\u043b\u0438 \u043f\u0440\u043e\u043a\u0441\u0438 \u0443\u0436\u0435 \u0431\u044b\u043b \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u0435\u043d \u0440\u0430\u043d\u0435\u0435 - \u0431\u0435\u0440\u0435\u043c \u0435\u0433\u043e     }          let currentDelegate: AnyObject? = P.currentDelegateFor(object) \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439\u0441\u044f \u0432 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0435 UI \u043e\u0431\u044a\u0435\u043a\u0442\u0430 (\u043e\u0431\u044b\u0447\u043d\u043e delegate\/dataSource). \u0412\u0441\u0435 \u043a\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b DelegateProxy \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434, \u0442.\u043a. \u0442\u0430\u043c \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 as! \u043a \u0442\u0438\u043f\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u044b \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u0435\u043c \u043f\u0440\u043e\u043a\u0441\u0438          if currentDelegate !== proxy { \/\/ \u0435\u0441\u043b\u0438 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u043d\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u0435\u043d \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043f\u0440\u043e\u043a\u0441\u0438         proxy.setForwardToDelegate(currentDelegate, retainDelegate: false) \/\/ \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0442\u0430\u0440\u044b\u0439 \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430 \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0441\u044b\u043b\u0430\u0442\u044c\u0441\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0443 UI \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0438 \u043f\u0440\u043e\u043a\u0441\u0438 \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u0438 \u043e\u0431\u044b\u0447\u043d\u044b\u0439. \u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043b\u0435\u0436\u0438\u0442 \u0432 Objective-C \u0447\u0430\u0441\u0442\u0438 Rx, \u0430 \u0442\u043e\u0447\u043d\u0435\u0435 \u0432 _RXDelegateProxy.         P.setCurrentDelegate(proxy, toObject: object) \/\/ \u0432\u0441\u0435 \u043a\u0442\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 DelegateProxy \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434, \u0442.\u043a. \u0442\u0430\u043c \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 as! \u043a \u0442\u0438\u043f\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u044b \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u0435\u043c \u043f\u0440\u043e\u043a\u0441\u0438         assert(P.currentDelegateFor(object) === proxy)         assert(proxy.forwardToDelegate() === currentDelegate)     }              return proxy }<\/code><\/pre>\n<p>  \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043f\u0440\u043e\u043a\u0441\u0438 \u0435\u0441\u043b\u0438 \u043d\u0435 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u0440\u0430\u043d\u0435\u0435, \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u0451 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430, \u0438 \u0435\u0441\u043b\u0438 \u0431\u044b\u043b \u2014 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0434\u0435\u043b\u0435\u0433\u0430\u0442.<\/p>\n<p>  \u0421\u043e\u0432\u0441\u0435\u043c \u0433\u043b\u0443\u0431\u043e\u043a\u043e \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043b\u0435\u0437\u0442\u044c \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0447\u0435\u0442\u0441\u044f, \u0441\u043a\u0430\u0436\u0443 \u043b\u0438\u0448\u044c, \u0447\u0442\u043e \u043f\u043e\u0434\u043c\u0435\u043d\u0430 \u043c\u0435\u0442\u043e\u0434\u0430 \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u043e\u0432 \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c swizzling&#8217;\u043e\u043c \u0438\u0437 Objective-C \u043a\u043e\u0434\u0430.<\/p>\n<p>  \u042f \u0441\u043e\u0437\u0434\u0430\u043b UML \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u0441 \u043d\u0435\u0439 \u0441\u0442\u0430\u043d\u0435\u0442 \u0447\u0443\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0439 \u043a\u0430\u043a \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u043a\u0441\u0438 (\u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430 \u043a\u043b\u0438\u043a\u0430\u0431\u0435\u043b\u044c\u043d\u0430).<\/p>\n<p>  <a href=\"https:\/\/habrastorage.org\/files\/2f1\/7ba\/309\/2f17ba30992448a7be33a9ef268e0d11.png\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/2f1\/7ba\/309\/2f17ba30992448a7be33a9ef268e0d11.png\"\/><\/a><\/p>\n<p>  \u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u044b\u0440\u043d\u0435\u043c \u0435\u0449\u0435 \u0447\u0443\u0442\u044c \u0433\u043b\u0443\u0431\u0436\u0435, \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0440\u0430\u0437, \u043e\u0431\u0435\u0449\u0430\u044e.<br \/>  \u0427\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0441\u043b\u0438 \u043d\u0430\u0448 UI \u043a\u043b\u0430\u0441\u0441 \u0438\u043c\u0435\u0435\u0442 \u0434\u0435\u043b\u0435\u0433\u0430\u0442, \u043d\u043e \u043e\u043d \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u043e\u043c \u043e\u0442 \u0434\u0440\u0443\u0433\u043e\u0433\u043e UI \u043a\u043b\u0430\u0441\u0441\u0430 \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u044e\u0449\u0435\u0433\u043e \u0434\u0435\u043b\u0435\u0433\u0430\u0442? \u0424\u0430\u0431\u0440\u0438\u0447\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442.<\/p>\n<p>  \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 UITableView. \u041e\u043d \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u043e\u043c UIScrollView, \u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0442\u043e\u0436\u0435 \u0435\u0441\u0442\u044c \u0434\u0435\u043b\u0435\u0433\u0430\u0442. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 rx_delegate \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 (UIScrollView), \u0430 \u043d\u0435 \u0432 UITableView.<br \/>  \u041f\u0440\u043e\u043a\u0441\u0438 \u0434\u043b\u044f RxTableViewDelegateProxy \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u043e\u043c RxScrollViewDelegateProxy<\/p>\n<pre><code>extension UIScrollView {          \/**     Factory method that enables subclasses to implement their own `rx_delegate`.          - returns: Instance of delegate proxy that wraps `delegate`.     *\/     public func rx_createDelegateProxy() -&gt; RxScrollViewDelegateProxy {         return RxScrollViewDelegateProxy(parentObject: self)     }          \/**     Reactive wrapper for `delegate`.          For more information take a look at `DelegateProxyType` protocol documentation.     *\/     public var rx_delegate: DelegateProxy {         return proxyForObject(RxScrollViewDelegateProxy.self, self)     } ... }<\/code><\/pre>\n<p>  \u0412 \u0435\u0433\u043e \u043f\u0440\u043e\u043a\u0441\u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d \u043c\u0435\u0442\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430 createProxyForObject, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u043a\u0441\u0438 \u043c\u0435\u0442\u043e\u0434\u0443 rx_createDelegateProxy<\/p>\n<pre><code>public class RxScrollViewDelegateProxy     : DelegateProxy     , UIScrollViewDelegate     , DelegateProxyType {      public override class func createProxyForObject(object: AnyObject) -&gt; AnyObject {         let scrollView = (object as! UIScrollView)                  return castOrFatalError(scrollView.rx_createDelegateProxy())     }     ... }<\/code><\/pre>\n<p>  \u0412 UItableView \u0436\u0435 \u043c\u0435\u0442\u043e\u0434 rx_createDelegateProxy \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d<\/p>\n<pre><code>extension UITableView {       \/**     Factory method that enables subclasses to implement their own `rx_delegate`.          - returns: Instance of delegate proxy that wraps `delegate`.     *\/     public override func rx_createDelegateProxy() -&gt; RxScrollViewDelegateProxy {         return RxTableViewDelegateProxy(parentObject: self)     }    \t... }<\/code><\/pre>\n<p>  \u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 RxTableViewDelegateProxy \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 RxScrollViewDelegateProxy)<\/p>\n<pre><code>public class RxTableViewDelegateProxy     : RxScrollViewDelegateProxy     , UITableViewDelegate {      public weak private(set) var tableView: UITableView?      public required init(parentObject: AnyObject) {         self.tableView = (parentObject as! UITableView)         super.init(parentObject: parentObject)     } }<\/code><\/pre>\n<p>  \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u0441\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0430 \u043f\u0440\u043e\u043a\u0441\u0438.<\/p>\n<p>  \u041e\u0447\u0435\u0440\u0435\u0434\u043d\u0430\u044f UML \u0441\u0445\u0435\u043c\u0430, \u043f\u043e\u0437\u0430\u0431\u043e\u0440\u0438\u0441\u0442\u0435\u0439, \u043d\u0430 \u043d\u0435\u0439 \u0432\u0438\u0434\u043d\u043e \u043a\u0430\u043a \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u043f\u0440\u0438\u0441\u0432\u043e\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u043a\u0441\u0438 \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f (\u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430 \u043a\u043b\u0438\u043a\u0430\u0431\u0435\u043b\u044c\u043d\u0430).<\/p>\n<p>  <a href=\"https:\/\/habrastorage.org\/files\/44d\/0e4\/992\/44d0e4992fd5462c80cc01d1ce48decb.png\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/44d\/0e4\/992\/44d0e4992fd5462c80cc01d1ce48decb.png\"\/><\/a><\/p>\n<p>  \u041f\u043e\u0434\u0432\u0435\u0434\u0435\u043c \u0438\u0442\u043e\u0433. RxSwift \u0442\u0435\u043c\u0430 \u043e\u0447\u0435\u043d\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f, \u0445\u043e\u0442\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u043d\u0435 \u0431\u0435\u0437 \u0448\u0435\u0440\u043e\u0445\u043e\u0432\u0430\u0442\u043e\u0441\u0442\u0435\u0439. \u0420\u0430\u0437\u043e\u0431\u0440\u0430\u0432\u0448\u0438\u0441\u044c \u0441 \u0442\u0435\u043c \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0443\u0436\u043d\u043e \u0434\u0443\u043c\u0430\u0442\u044c \u043a\u0430\u043a \u0433\u0440\u0430\u043c\u043e\u0442\u043d\u043e \u044d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b.<\/p>\n<p>  \u0427\u0442\u043e \u0436. \u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0445 \u0441\u0442\u0430\u0442\u0435\u0439 \u0441 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0433\u043b\u0443\u0431\u0436\u0435 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u043c, \u0441 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u043e\u0442\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0435\u043c\u0430\u043b\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u0415\u0441\u0442\u044c \u043b\u0438 \u0441\u043c\u044b\u0441\u043b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e \u044d\u0442\u043e\u0439 \u0442\u0435\u043c\u0435? <br \/>  \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e \u044f \u043d\u0435 \u043c\u043e\u0433\u0443 \u0441\u0435\u0431\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u043a\u0440\u0443\u0442\u043e\u0433\u043e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u043e\u0440\u0430, \u0441\u043a\u043e\u0440\u0435\u0435 \u043a\u0430\u043a \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0430 \u0432 \u043f\u043e\u0438\u0441\u043a\u0430\u0445 \u00ab\u0441\u0435\u0440\u0435\u0431\u0440\u044f\u043d\u043e\u0439 \u043f\u0443\u043b\u0438\u00bb, \u0442\u0430\u043a \u0447\u0442\u043e \u043c\u043e\u0438 \u0432\u044b\u0432\u043e\u0434\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043a\u0430\u043a \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b, \u0442\u0430\u043a \u0438 \u043d\u0435\u0432\u0435\u0440\u043d\u044b, \u043d\u043e \u0434\u043e\u0440\u043e\u0433\u0443 \u043e\u0441\u0438\u043b\u0438\u0442 \u0438\u0434\u0443\u0449\u0438\u0439.<br \/>  \u041e\u0431\u043e \u0432\u0441\u0435\u0445 \u043e\u0448\u0438\u0431\u043a\u0430\u0445 \u043a\u0430\u043a \u0432\u0441\u0435\u0433\u0434\u0430 \u2014 \u0432 \u043b\u0438\u0447\u043a\u0443.               <\/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\/283128\/\"> https:\/\/habrahabr.ru\/post\/283128\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>       <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/49a\/a66\/dfc\/49aa66dfc7e34d5ca6292d7dc9c5e387.png\"\/><\/p>\n<p>  \u041c\u043e\u044f <a href=\"https:\/\/habrahabr.ru\/post\/281292\/\">\u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e RxSwift<\/a> \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u043b\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0441\u0435 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b, \u0431\u0435\u0437 \u0437\u043d\u0430\u043d\u0438\u0439 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043d\u0435 \u0438\u043c\u0435\u043b\u043e \u043e\u0441\u043e\u0431\u043e\u0433\u043e \u0441\u043c\u044b\u0441\u043b\u0430. \u041d\u043e \u044d\u0442\u043e \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u0430\u043b\u0444\u0430\u0432\u0438\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043d\u044f\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 GUI.<\/p>\n<p>  \u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0434\u043b\u044f \u043f\u0440\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0437 RxExample, \u043d\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432 \u0431\u044b\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0430 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 UIExplanation \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0432 RxExample<br \/>  \u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0437\u0434\u0435\u0441\u044c <a href=\"https:\/\/github.com\/sparklone\/RxSwift\/\">github.com\/sparklone\/RxSwift<\/a><\/p>\n<p>  \u041f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 UI \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0432 Rx \u0435\u0441\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0438:<br \/>  1) <a href=\"#Driver\">\u043f\u043e\u043d\u044f\u0442\u044c \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u0430\u043c\u043d\u0438 \u043d\u0430\u0441 \u043e\u0436\u0438\u0434\u0430\u044e\u0442 \u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435 \u0438 \u0437\u0430\u0447\u0435\u043c \u043d\u0443\u0436\u0435\u043d Driver<\/a><br \/>  2) <a href=\"#UIBindingObserver\">\u043d\u0430\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 UI \u043a Observable, \u0447\u0442\u043e\u0431\u044b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b Observable \u043c\u0435\u043d\u044f\u043b\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\/\u0441\u0432\u043e\u0439\u0441\u0442\u0432 UI \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430. \u042d\u0442\u043e \u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e UIBindingObserver<\/a><br \/>  3) <a href=\"#ControlEvent\">\u043d\u0430\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u0430\u0442\u0442\u0435\u0440\u043d target-action \u043d\u0430 \u0440\u0435\u043b\u044c\u0441\u044b Rx. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ControlEvent<\/a><br \/>  4) <a href=\"#ControlProperty\">\u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0432\u0443\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u044e\u044e \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c UI \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ControlProperty<\/a><br \/>  5) <a href=\"#DelegateProxy\">\u0442.\u043a. \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u0443 UI \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 delegate\/dataSource \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0442\u0441\u044f \u0432 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u0447\u0438\u0441\u043b\u0435, \u2014 \u0432\u0432\u0435\u043b\u0438 \u043a\u043b\u0430\u0441\u0441 DelegateProxy, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0434\u0435\u043b\u0435\u0433\u0430\u0442, \u0442\u0430\u043a \u0438 Rx \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/a><\/p>\n<p>  \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u0436\u0434\u0443\u044e \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e  <\/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-279763","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/279763","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=279763"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/279763\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=279763"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=279763"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=279763"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}