{"action":"created","comment":{"url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/pulls/comments/34948203","id":34948203,"diff_hunk":"@@ -1,555 +1,242 @@\n # ReactiveCocoa [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n \n-ReactiveCocoa (RAC) is an Objective-C framework inspired by [Functional Reactive\n-Programming][]. It provides APIs for **composing and transforming streams of\n-values**.\n+ReactiveCocoa (RAC) is a Cocoa framework inspired by\n+[Functional Reactive\n+Programming](http://en.wikipedia.org/wiki/Functional_reactive_programming). It\n+provides APIs for composing and transforming **streams of values over time**.\n \n-If you're already familiar with functional reactive programming or know the basic\n-premise of ReactiveCocoa, check out the [Documentation][] folder for a framework\n-overview and more in-depth information about how it all works in practice.\n+ 1. [Introduction](#introduction)\n+ 1. [Example: online search](#example-online-search)\n+ 1. [Objective-C and Swift](#objective-c-and-swift)\n+ 1. [How does ReactiveCocoa relate to Rx?](#how-does-reactivecocoa-relate-to-rx)\n+ 1. [Getting started](#getting-started)\n+\n+If you’re already familiar with functional reactive programming or what\n+ReactiveCocoa is about, check out the [Documentation](Documentation) folder for more in-depth\n+information about how it all works. Then, dive straight into our [documentation\n+comments](ReactiveCocoa) for learning more about individual APIs.\n+\n+If you have a question, please see if any discussions in our [GitHub\n+issues](https://github.com/ReactiveCocoa/ReactiveCocoa/issues?q=is%3Aissue+label%3Aquestion+) or [Stack\n+Overflow](http://stackoverflow.com/questions/tagged/reactive-cocoa) have already\n+answered it. If not, please feel free to [file your\n+own](https://github.com/ReactiveCocoa/ReactiveCocoa/issues/new)!\n \n _Many thanks to [Rheinfabrik](http://www.rheinfabrik.de) for generously sponsoring the development of ReactiveCocoa 3!_\n \n-## New to ReactiveCocoa?\n-\n-ReactiveCocoa is documented like crazy, and there's a wealth of introductory\n-material available to explain what RAC is and how you can use it.\n-\n-If you want to learn more, we recommend these resources, roughly in order:\n-\n- 1. [Introduction](#introduction)\n- 1. [When to use ReactiveCocoa](#when-to-use-reactivecocoa)\n- 1. [Framework Overview][]\n- 1. [Basic Operators][]\n- 1. [Header documentation](ReactiveCocoa)\n- 1. Previously answered [Stack Overflow](https://github.com/ReactiveCocoa/ReactiveCocoa/wiki)\n-    questions and [GitHub issues](https://github.com/ReactiveCocoa/ReactiveCocoa/issues?labels=question&state=closed)\n- 1. The rest of the [Documentation][] folder\n- 1. [Functional Reactive Programming on iOS](https://leanpub.com/iosfrp/) \n-    (eBook)\n- \n-If you have any further questions, please feel free to [file an issue](https://github.com/ReactiveCocoa/ReactiveCocoa/issues/new). \n-\n ## Introduction\n \n ReactiveCocoa is inspired by [functional reactive\n programming](http://blog.maybeapps.com/post/42894317939/input-and-output).\n Rather than using mutable variables which are replaced and modified in-place,\n-RAC provides signals (represented by `RACSignal`) that capture present and\n-future values.\n-\n-By chaining, combining, and reacting to signals, software can be written\n-declaratively, without the need for code that continually observes and updates\n-values.\n-\n-For example, a text field can be bound to the latest time, even as it changes,\n-instead of using additional code that watches the clock and updates the\n-text field every second.  It works much like KVO, but with blocks instead of\n-overriding `-observeValueForKeyPath:ofObject:change:context:`.\n-\n-Signals can also represent asynchronous operations, much like [futures and\n-promises][]. This greatly simplifies asynchronous software, including networking\n-code.\n-\n-One of the major advantages of RAC is that it provides a single, unified\n-approach to dealing with asynchronous behaviors, including delegate methods,\n-callback blocks, target-action mechanisms, notifications, and KVO.\n-\n-Here's a simple example:\n-\n-```objc\n-// When self.username changes, logs the new name to the console.\n-//\n-// RACObserve(self, username) creates a new RACSignal that sends the current\n-// value of self.username, then the new value whenever it changes.\n-// -subscribeNext: will execute the block whenever the signal sends a value.\n-[RACObserve(self, username) subscribeNext:^(NSString *newName) {\n-\tNSLog(@\"%@\", newName);\n-}];\n-```\n+RAC offers “event streams,” represented by the `Signal` and `SignalProducer`\n+types, that send values over time.\n \n-But unlike KVO notifications, signals can be chained together and operated on:\n-\n-```objc\n-// Only logs names that starts with \"j\".\n-//\n-// -filter returns a new RACSignal that only sends a new value when its block\n-// returns YES.\n-[[RACObserve(self, username)\n-\tfilter:^(NSString *newName) {\n-\t\treturn [newName hasPrefix:@\"j\"];\n-\t}]\n-\tsubscribeNext:^(NSString *newName) {\n-\t\tNSLog(@\"%@\", newName);\n-\t}];\n-```\n+Event streams unify all of Cocoa’s common patterns for asynchrony and event\n+handling, including:\n \n-Signals can also be used to derive state. Instead of observing properties and\n-setting other properties in response to the new values, RAC makes it possible to\n-express properties in terms of signals and operations:\n-\n-```objc\n-// Creates a one-way binding so that self.createEnabled will be\n-// true whenever self.password and self.passwordConfirmation\n-// are equal.\n-//\n-// RAC() is a macro that makes the binding look nicer.\n-// \n-// +combineLatest:reduce: takes an array of signals, executes the block with the\n-// latest value from each signal whenever any of them changes, and returns a new\n-// RACSignal that sends the return value of that block as values.\n-RAC(self, createEnabled) = [RACSignal \n-\tcombineLatest:@[ RACObserve(self, password), RACObserve(self, passwordConfirmation) ] \n-\treduce:^(NSString *password, NSString *passwordConfirm) {\n-\t\treturn @([passwordConfirm isEqualToString:password]);\n-\t}];\n-```\n+ * Delegate methods\n+ * Callback blocks\n+ * `NSNotification`s\n+ * Control actions and responder chain events\n+ * [Futures and promises](https://en.wikipedia.org/wiki/Futures_and_promises)\n+ * [Key-value observing](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html) (KVO)\n \n-Signals can be built on any stream of values over time, not just KVO. For\n-example, they can also represent button presses:\n-\n-```objc\n-// Logs a message whenever the button is pressed.\n-//\n-// RACCommand creates signals to represent UI actions. Each signal can\n-// represent a button press, for example, and have additional work associated\n-// with it.\n-//\n-// -rac_command is an addition to NSButton. The button will send itself on that\n-// command whenever it's pressed.\n-self.button.rac_command = [[RACCommand alloc] initWithSignalBlock:^(id _) {\n-\tNSLog(@\"button was pressed!\");\n-\treturn [RACSignal empty];\n-}];\n-```\n+Because all of these different mechanisms can be represented in the _same_ way,\n+it’s easy to declaratively chain and combine them together, with less spaghetti\n+code and state to bridge the gap.\n \n-Or asynchronous network operations:\n-\n-```objc\n-// Hooks up a \"Log in\" button to log in over the network.\n-//\n-// This block will be run whenever the login command is executed, starting\n-// the login process.\n-self.loginCommand = [[RACCommand alloc] initWithSignalBlock:^(id sender) {\n-\t// The hypothetical -logIn method returns a signal that sends a value when\n-\t// the network request finishes.\n-\treturn [client logIn];\n-}];\n-\n-// -executionSignals returns a signal that includes the signals returned from\n-// the above block, one for each time the command is executed.\n-[self.loginCommand.executionSignals subscribeNext:^(RACSignal *loginSignal) {\n-\t// Log a message whenever we log in successfully.\n-\t[loginSignal subscribeCompleted:^{\n-\t\tNSLog(@\"Logged in successfully!\");\n-\t}];\n-}];\n-\n-// Executes the login command when the button is pressed.\n-self.loginButton.rac_command = self.loginCommand;\n-```\n+## Example: online search\n+\n+Let’s say you have a text field, and whenever the user types something into it,\n+you want to make a network request which searches for that query.\n+\n+#### Observing text edits\n+\n+The first step is to observe edits to the text field, using a RAC extension to\n+`UITextField` specifically for this purpose:\n \n-Signals can also represent timers, other UI events, or anything else that\n-changes over time.\n-\n-Using signals for asynchronous operations makes it possible to build up more\n-complex behavior by chaining and transforming those signals. Work can easily be\n-triggered after a group of operations completes:\n-\n-```objc\n-// Performs 2 network operations and logs a message to the console when they are\n-// both completed.\n-//\n-// +merge: takes an array of signals and returns a new RACSignal that passes\n-// through the values of all of the signals and completes when all of the\n-// signals complete.\n-//\n-// -subscribeCompleted: will execute the block when the signal completes.\n-[[RACSignal \n-\tmerge:@[ [client fetchUserRepos], [client fetchOrgRepos] ]] \n-\tsubscribeCompleted:^{\n-\t\tNSLog(@\"They're both done!\");\n-\t}];\n+```swift\n+let searchStrings = textField.rac_textSignal()\n+    |> toSignalProducer()\n+    |> map { text in text as! String }\n ```\n \n-Signals can be chained to sequentially execute asynchronous operations, instead\n-of nesting callbacks with blocks. This is similar to how [futures and promises][]\n-are usually used:\n-\n-```objc\n-// Logs in the user, then loads any cached messages, then fetches the remaining\n-// messages from the server. After that's all done, logs a message to the\n-// console.\n-//\n-// The hypothetical -logInUser methods returns a signal that completes after\n-// logging in.\n-//\n-// -flattenMap: will execute its block whenever the signal sends a value, and\n-// returns a new RACSignal that merges all of the signals returned from the block\n-// into a single signal.\n-[[[[client \n-\tlogInUser] \n-\tflattenMap:^(User *user) {\n-\t\t// Return a signal that loads cached messages for the user.\n-\t\treturn [client loadCachedMessagesForUser:user];\n-\t}]\n-\tflattenMap:^(NSArray *messages) {\n-\t\t// Return a signal that fetches any remaining messages.\n-\t\treturn [client fetchMessagesAfterMessage:messages.lastObject];\n-\t}]\n-\tsubscribeNext:^(NSArray *newMessages) {\n-\t\tNSLog(@\"New messages: %@\", newMessages);\n-\t} completed:^{\n-\t\tNSLog(@\"Fetched all messages.\");\n-\t}];\n+This gives us a [signal\n+producer](Documentation/FrameworkOverview.md#signal-producers) which sends\n+values of type `String`. _(The cast is [currently\n+necessary](https://github.com/ReactiveCocoa/ReactiveCocoa/issues/2182) to bridge\n+this extension method from Objective-C.)_\n+\n+#### Making network requests\n+\n+With each string, we want to execute a network request. Luckily, RAC offers an\n+`NSURLSession` extension for doing exactly that:\n+\n+```swift\n+let searchResults = searchStrings\n+    |> flatMap(.Latest) { query in\n+        let URLRequest = self.searchRequestWithEscapedQuery(query)\n+        return NSURLSession.sharedSession().rac_dataWithRequest(URLRequest)\n+    }\n+    |> map { data, URLResponse in\n+        let string = String(data: data, encoding: NSUTF8StringEncoding)!\n+        return parseJSONResultsFromString(string)\n+    }\n ```\n \n-RAC even makes it easy to bind to the result of an asynchronous operation:\n-\n-```objc\n-// Creates a one-way binding so that self.imageView.image will be set as the user's\n-// avatar as soon as it's downloaded.\n-//\n-// The hypothetical -fetchUserWithUsername: method returns a signal which sends\n-// the user.\n-//\n-// -deliverOn: creates new signals that will do their work on other queues. In\n-// this example, it's used to move work to a background queue and then back to the main thread.\n-//\n-// -map: calls its block with each user that's fetched and returns a new\n-// RACSignal that sends values returned from the block.\n-RAC(self.imageView, image) = [[[[client \n-\tfetchUserWithUsername:@\"joshaber\"]\n-\tdeliverOn:[RACScheduler scheduler]]\n-\tmap:^(User *user) {\n-\t\t// Download the avatar (this is done on a background queue).\n-\t\treturn [[NSImage alloc] initWithContentsOfURL:user.avatarURL];\n-\t}]\n-\t// Now the assignment will be done on the main thread.\n-\tdeliverOn:RACScheduler.mainThreadScheduler];\n+This has transformed our producer of `String`s into a producer of `Array`s\n+containing the search results.\n+\n+Additionally, `flatMap(.Latest)` here ensures that _only one search_—the\n+latest—is allowed to be running. If the user types another character while the\n+network request is still in flight, it will be cancelled before starting a new\n+one. Just think of how much code that would take to do by hand!\n+\n+#### Receiving the results\n+\n+This won’t actually execute yet, because producers must be _started_ in order to\n+receive the results (which prevents doing work when the results are never used).\n+That’s easy enough:\n+\n+```swift\n+searchResults.start(next: { results in\n+    println(\"Search results: \\(results)\")\n+}, error: { error in\n+    println(\"Error searching: \\(error)\")\n+})\n ```\n \n-That demonstrates some of what RAC can do, but it doesn't demonstrate why RAC is\n-so powerful. It's hard to appreciate RAC from README-sized examples, but it\n-makes it possible to write code with less state, less boilerplate, better code\n-locality, and better expression of intent.\n+Here, we watch for the `Next` and `Error`\n+[events](Documentation/FrameworkOverview.md#events), and just log to the\n+console. This could easily do something else instead, like update a table view\n+or a label on screen.\n \n-For more sample code, check out [C-41][] or [GroceryList][], which are real iOS\n-apps written using ReactiveCocoa. Additional information about RAC can be found\n-in the [Documentation][] folder.\n+#### Throttling requests\n \n-## When to use ReactiveCocoa\n+Now, let’s say you only want to actually perform the search when the user pauses\n+typing, to minimize traffic.\n \n-Upon first glance, ReactiveCocoa is very abstract, and it can be difficult to\n-understand how to apply it to concrete problems.\n+ReactiveCocoa has a declarative `throttle` operator that we can apply to our\n+search strings:\n \n-Here are some of the use cases that RAC excels at.\n+```swift\n+let searchStrings = textField.rac_textSignal()\n+    |> toSignalProducer()\n+    |> map { text in text as! String }\n+    |> throttle(0.5, onScheduler: UIScheduler())\n+```\n \n-### Handling asynchronous or event-driven data sources\n+This prevents values from being sent less than 0.5 seconds apart, so the user\n+must stop editing for at least that long before we’ll use their search string.\n \n-Much of Cocoa programming is focused on reacting to user events or changes in\n-application state. Code that deals with such events can quickly become very\n-complex and spaghetti-like, with lots of callbacks and state variables to handle\n-ordering issues.\n+To do this manually would require significant state, and end up much harder to\n+read! With ReactiveCocoa, we can use just one operator to incorporate _time_ into\n+our event stream.\n \n-Patterns that seem superficially different, like UI callbacks, network\n-responses, and KVO notifications, actually have a lot in common. [RACSignal][]\n-unifies all these different APIs so that they can be composed together and\n-manipulated in the same way.\n+## Objective-C and Swift\n \n-For example, the following code:\n+Although ReactiveCocoa was started as an Objective-C framework, as of version\n+3.0, all major feature development is concentrated on the Swift API.\n \n-```objc\n+RAC’s Objective-C API and Swift API are entirely separate, but there is\n+a [bridge](Documentation/ObjectiveCBridging.md) to convert between the two. This\n+is mostly meant as a compatibility layer for older ReactiveCocoa projects, or to\n+use Cocoa extensions which haven’t been added to the Swift API yet.\n \n-static void *ObservationContext = &ObservationContext;\n+The Objective-C API will continue to exist and be supported for the foreseeable\n+future, but it won’t receive many improvements. **We highly recommend that all\n+new projects use the Swift API.**\n \n-- (void)viewDidLoad {\n-\t[super viewDidLoad];\n+## How does ReactiveCocoa relate to Rx?\n \n-\t[LoginManager.sharedManager addObserver:self forKeyPath:@\"loggingIn\" options:NSKeyValueObservingOptionInitial context:&ObservationContext];\n-\t[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(loggedOut:) name:UserDidLogOutNotification object:LoginManager.sharedManager];\n+ReactiveCocoa was originally inspired, and therefore heavily influenced, by\n+Microsoft’s [Reactive\n+Extensions](https://msdn.microsoft.com/en-us/data/gg577609.aspx) (Rx) library. There are many ports of Rx, including [RxSwift](https://github.com/kzaher/RxSwift), but ReactiveCocoa is _intentionally_ not a direct port.\n \n-\t[self.usernameTextField addTarget:self action:@selector(updateLogInButton) forControlEvents:UIControlEventEditingChanged];\n-\t[self.passwordTextField addTarget:self action:@selector(updateLogInButton) forControlEvents:UIControlEventEditingChanged];\n-\t[self.logInButton addTarget:self action:@selector(logInPressed:) forControlEvents:UIControlEventTouchUpInside];\n-}\n+**Where RAC differs from Rx**, it is usually to:\n \n-- (void)dealloc {\n-\t[LoginManager.sharedManager removeObserver:self forKeyPath:@\"loggingIn\" context:ObservationContext];\n-\t[NSNotificationCenter.defaultCenter removeObserver:self];\n-}\n+ * Create a simpler API\n+ * Address common sources of confusion\n+ * More closely match Cocoa conventions\n \n-- (void)updateLogInButton {\n-\tBOOL textFieldsNonEmpty = self.usernameTextField.text.length > 0 && self.passwordTextField.text.length > 0;\n-\tBOOL readyToLogIn = !LoginManager.sharedManager.isLoggingIn && !self.loggedIn;\n-\tself.logInButton.enabled = textFieldsNonEmpty && readyToLogIn;\n-}\n+The following are some of the concrete differences, along with their rationales.\n \n-- (IBAction)logInPressed:(UIButton *)sender {\n-\t[[LoginManager sharedManager]\n-\t\tlogInWithUsername:self.usernameTextField.text\n-\t\tpassword:self.passwordTextField.text\n-\t\tsuccess:^{\n-\t\t\tself.loggedIn = YES;\n-\t\t} failure:^(NSError *error) {\n-\t\t\t[self presentError:error];\n-\t\t}];\n-}\n+#### Naming\n \n-- (void)loggedOut:(NSNotification *)notification {\n-\tself.loggedIn = NO;\n-}\n+Most operations in Rx borrow names from\n+[LINQ](https://msdn.microsoft.com/en-us/library/bb397926.aspx), which uses terms\n+reminiscient of relational databases, like `Select` and `Where`. Streams over\n+time are known as `Observable`s, which parallels the `Enumerable` type in .NET.\n \n-- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {\n-\tif (context == ObservationContext) {\n-\t\t[self updateLogInButton];\n-\t} else {\n-\t\t[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];\n-\t}\n-}\n-```\n+**RAC is focused on matching Swift naming first and foremost**, with terms like\n+`map` and `filter` instead. Other naming differences are typically inspired by\n+significantly better alternatives from [Haskell](https://www.haskell.org) or\n+[Elm](http://elm-lang.org) (which is the primary source for the “signal”\n+terminology).\n \n-… could be expressed in RAC like so:\n-\n-```objc\n-- (void)viewDidLoad {\n-\t[super viewDidLoad];\n-\n-\t@weakify(self);\n-\n-\tRAC(self.logInButton, enabled) = [RACSignal\n-\t\tcombineLatest:@[\n-\t\t\tself.usernameTextField.rac_textSignal,\n-\t\t\tself.passwordTextField.rac_textSignal,\n-\t\t\tRACObserve(LoginManager.sharedManager, loggingIn),\n-\t\t\tRACObserve(self, loggedIn)\n-\t\t] reduce:^(NSString *username, NSString *password, NSNumber *loggingIn, NSNumber *loggedIn) {\n-\t\t\treturn @(username.length > 0 && password.length > 0 && !loggingIn.boolValue && !loggedIn.boolValue);\n-\t\t}];\n-\n-\t[[self.logInButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton *sender) {\n-\t\t@strongify(self);\n-\n-\t\tRACSignal *loginSignal = [LoginManager.sharedManager\n-\t\t\tlogInWithUsername:self.usernameTextField.text\n-\t\t\tpassword:self.passwordTextField.text];\n-\n-\t\t\t[loginSignal subscribeError:^(NSError *error) {\n-\t\t\t\t@strongify(self);\n-\t\t\t\t[self presentError:error];\n-\t\t\t} completed:^{\n-\t\t\t\t@strongify(self);\n-\t\t\t\tself.loggedIn = YES;\n-\t\t\t}];\n-\t}];\n-\n-\tRAC(self, loggedIn) = [[NSNotificationCenter.defaultCenter\n-\t\trac_addObserverForName:UserDidLogOutNotification object:nil]\n-\t\tmapReplace:@NO];\n-}\n-```\n+#### Signals and Signal Producers (“hot” and “cold” observables)\n \n-### Chaining dependent operations\n-\n-Dependencies are most often found in network requests, where a previous request\n-to the server needs to complete before the next one can be constructed, and so\n-on:\n-\n-```objc\n-[client logInWithSuccess:^{\n-\t[client loadCachedMessagesWithSuccess:^(NSArray *messages) {\n-\t\t[client fetchMessagesAfterMessage:messages.lastObject success:^(NSArray *nextMessages) {\n-\t\t\tNSLog(@\"Fetched all messages.\");\n-\t\t} failure:^(NSError *error) {\n-\t\t\t[self presentError:error];\n-\t\t}];\n-\t} failure:^(NSError *error) {\n-\t\t[self presentError:error];\n-\t}];\n-} failure:^(NSError *error) {\n-\t[self presentError:error];\n-}];\n-```\n+One of the most confusing aspects of aspects of Rx is that of [“hot”, “cold”, and\n+“warm”\n+observables](http://www.introtorx.com/content/v1.0.10621.0/14_HotAndColdObservables.html) (event streams).\n \n-ReactiveCocoa makes this pattern particularly easy:\n-\n-```objc\n-[[[[client logIn]\n-\tthen:^{\n-\t\treturn [client loadCachedMessages];\n-\t}]\n-\tflattenMap:^(NSArray *messages) {\n-\t\treturn [client fetchMessagesAfterMessage:messages.lastObject];\n-\t}]\n-\tsubscribeError:^(NSError *error) {\n-\t\t[self presentError:error];\n-\t} completed:^{\n-\t\tNSLog(@\"Fetched all messages.\");\n-\t}];\n-```\n+In short, given just a method or function declaration like this, in C#:\n \n-### Parallelizing independent work\n-\n-Working with independent data sets in parallel and then combining them into\n-a final result is non-trivial in Cocoa, and often involves a lot of\n-synchronization:\n-\n-```objc\n-__block NSArray *databaseObjects;\n-__block NSArray *fileContents;\n- \n-NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init];\n-NSBlockOperation *databaseOperation = [NSBlockOperation blockOperationWithBlock:^{\n-\tdatabaseObjects = [databaseClient fetchObjectsMatchingPredicate:predicate];\n-}];\n-\n-NSBlockOperation *filesOperation = [NSBlockOperation blockOperationWithBlock:^{\n-\tNSMutableArray *filesInProgress = [NSMutableArray array];\n-\tfor (NSString *path in files) {\n-\t\t[filesInProgress addObject:[NSData dataWithContentsOfFile:path]];\n-\t}\n-\n-\tfileContents = [filesInProgress copy];\n-}];\n- \n-NSBlockOperation *finishOperation = [NSBlockOperation blockOperationWithBlock:^{\n-\t[self finishProcessingDatabaseObjects:databaseObjects fileContents:fileContents];\n-\tNSLog(@\"Done processing\");\n-}];\n- \n-[finishOperation addDependency:databaseOperation];\n-[finishOperation addDependency:filesOperation];\n-[backgroundQueue addOperation:databaseOperation];\n-[backgroundQueue addOperation:filesOperation];\n-[backgroundQueue addOperation:finishOperation];\n+```csharp\n+IObservable<string> Search(string query)\n ```\n \n-The above code can be cleaned up and optimized by simply composing signals:\n-\n-```objc\n-RACSignal *databaseSignal = [[databaseClient\n-\tfetchObjectsMatchingPredicate:predicate]\n-\tsubscribeOn:[RACScheduler scheduler]];\n-\n-RACSignal *fileSignal = [RACSignal startEagerlyWithScheduler:[RACScheduler scheduler] block:^(id<RACSubscriber> subscriber) {\n-\tNSMutableArray *filesInProgress = [NSMutableArray array];\n-\tfor (NSString *path in files) {\n-\t\t[filesInProgress addObject:[NSData dataWithContentsOfFile:path]];\n-\t}\n-\n-\t[subscriber sendNext:[filesInProgress copy]];\n-\t[subscriber sendCompleted];\n-}];\n-\n-[[RACSignal\n-\tcombineLatest:@[ databaseSignal, fileSignal ]\n-\treduce:^ id (NSArray *databaseObjects, NSArray *fileContents) {\n-\t\t[self finishProcessingDatabaseObjects:databaseObjects fileContents:fileContents];\n-\t\treturn nil;\n-\t}]\n-\tsubscribeCompleted:^{\n-\t\tNSLog(@\"Done processing\");\n-\t}];\n-```\n+… it is **impossible to tell** whether subscribing to (observing) that\n+`IObservable` will involve side effects. If it _does_ involve side effects, it’s\n+also impossible to tell whether _each subscription_ has a side effect, or if only\n+the first one does.\n \n-### Simplifying collection transformations\n+This example is contrived, but it demonstrates **a real, pervasive problem**\n+that makes it extremely hard to understand Rx code (and pre-3.0 ReactiveCocoa\n+code) at a glance.\n \n-Higher-order functions like `map`, `filter`, `fold`/`reduce` are sorely missing\n-from Foundation, leading to loop-focused code like this:\n+[ReactiveCocoa 3.0](CHANGELOG.md) has solved this problem by distinguishing side\n+effects with the separate `Signal` and `SignalProducer` types. Although this\n+means there’s another type to learn about, it improves code clarity and helps\n+communicates intent much better.\n \n-```objc\n-NSMutableArray *results = [NSMutableArray array];\n-for (NSString *str in strings) {\n-\tif (str.length < 2) {\n-\t\tcontinue;\n-\t}\n+In other words, **ReactiveCocoa’s changes here are [simple, not\n+easy](http://www.infoq.com/presentations/Simple-Made-Easy)**.\n \n-\tNSString *newString = [str stringByAppendingString:@\"foobar\"];\n-\t[results addObject:newString];\n-}\n-```\n+#### UI programming\n \n-[RACSequence][] allows any Cocoa collection to be manipulated in a uniform and\n-declarative way:\n-\n-```objc\n-RACSequence *results = [[strings.rac_sequence\n-\tfilter:^ BOOL (NSString *str) {\n-\t\treturn str.length >= 2;\n-\t}]\n-\tmap:^(NSString *str) {\n-\t\treturn [str stringByAppendingString:@\"foobar\"];\n-\t}];\n-```\n+Rx is basically agnostic as to how it’s used. Although UI programming with Rx is\n+very common, it has few features tailored to that particular case.\n \n-## System Requirements\n+RAC takes a lot of inspiration from [ReactiveUI](http://reactiveui.net),\n+including the basis for [Actions](Documentation/FrameworkOverview.md#actions).\n \n-ReactiveCocoa supports OS X 10.8+ and iOS 8.0+.\n+Unlike ReactiveUI, which unfortunately cannot directly change Rx to make it more\n+friendly for UI programming, **ReactiveCocoa has been improved many times\n+specifically for this purpose**—even when it means diverging further from Rx.\n \n-## Importing ReactiveCocoa\n+## Getting started\n+\n+ReactiveCocoa supports OS X 10.9+ and iOS 8.0+.\n \n To add RAC to your application:\n \n- 1. Add the ReactiveCocoa repository as a submodule of your application's\n-    repository.\n+ 1. Add the ReactiveCocoa repository as a\n+    [submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules) of your\n+    application’s repository.\n  1. Run `script/bootstrap` from within the ReactiveCocoa folder.\n- 1. Drag and drop `ReactiveCocoa.xcodeproj` into your\n-    application's Xcode project or workspace.\n- 1. On the \"Build Phases\" tab of your application target, add RAC to the \"Link\n-    Binary With Libraries\" phase.\n-    * **On iOS**, add `libReactiveCocoa-iOS.a`.\n-    * **On OS X**, add `ReactiveCocoa.framework`. RAC must also be added to any\n-      \"Copy Frameworks\" build phase. If you don't already have one, simply add\n-      a \"Copy Files\" build phase and target the \"Frameworks\" destination.\n- 1. Add `\"$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/include\"\n-    $(inherited)` to the \"Header Search Paths\" build setting (this is only\n-    necessary for archive builds, but it has no negative effect otherwise).\n- 1. **For iOS targets**, add `-ObjC` to the \"Other Linker Flags\" build setting.\n- 1. **If you added RAC to a project (not a workspace)**, you will also need to\n-    add the appropriate RAC target to the \"Target Dependencies\" of your\n-    application.\n-\n-If you would prefer to use [CocoaPods](http://cocoapods.org), there are some\n-[ReactiveCocoa\n-podspecs](https://github.com/CocoaPods/Specs/tree/master/Specs/ReactiveCocoa) that\n-have been generously contributed by third parties.\n-\n-To see a project already set up with RAC, check out [C-41][] or [GroceryList][],\n-which are real iOS apps written using ReactiveCocoa.\n-\n-## Standalone Development\n-\n-If you’re working on RAC in isolation instead of integrating it into another project, you’ll want to open `ReactiveCocoa.xcworkspace` and not the `.xcodeproj`.\n-\n-## More Info\n-\n-ReactiveCocoa is inspired by .NET's [Reactive\n-Extensions](http://msdn.microsoft.com/en-us/data/gg577609) (Rx). Most of the\n-principles of Rx apply to RAC as well. There are some really good Rx resources\n-out there:\n-\n-* [Reactive Extensions MSDN entry](http://msdn.microsoft.com/en-us/library/hh242985.aspx)\n-* [Reactive Extensions for .NET Introduction](http://leecampbell.blogspot.com/2010/08/reactive-extensions-for-net.html)\n-* [Rx - Channel 9 videos](http://channel9.msdn.com/tags/Rx/)\n-* [Reactive Extensions wiki](http://rxwiki.wikidot.com/)\n-* [101 Rx Samples](http://rxwiki.wikidot.com/101samples)\n-* [Programming Reactive Extensions and LINQ](http://www.amazon.com/Programming-Reactive-Extensions-Jesse-Liberty/dp/1430237473)\n-\n-RAC and Rx are both frameworks inspired by functional reactive programming. Here \n-are some resources related to FRP:\n-\n-* [What is FRP? - Elm Language](http://elm-lang.org/learn/What-is-FRP.elm)\n-* [What is Functional Reactive Programming - Stack Overflow](http://stackoverflow.com/questions/1028250/what-is-functional-reactive-programming/1030631#1030631)\n-* [Specification for a Functional Reactive Language - Stack Overflow](http://stackoverflow.com/questions/5875929/specification-for-a-functional-reactive-programming-language#5878525)\n-* [Escape from Callback Hell](http://elm-lang.org/learn/Escape-from-Callback-Hell.elm)\n-* [Principles of Reactive Programming on Coursera](https://www.coursera.org/course/reactive)\n-\n-[Basic Operators]: Documentation/BasicOperators.md\n-[Documentation]: Documentation\n-[Framework Overview]: Documentation/FrameworkOverview.md\n-[Functional Reactive Programming]: http://en.wikipedia.org/wiki/Functional_reactive_programming\n-[GroceryList]:  https://github.com/jspahrsummers/GroceryList\n-[RACSequence]: ReactiveCocoa/Objective-C/RACSequence.h\n-[RACSignal]: ReactiveCocoa/Objective-C/RACSignal.h\n-[futures and promises]: http://en.wikipedia.org/wiki/Futures_and_promises\n-[C-41]: https://github.com/AshFurrow/C-41\n+ 1. Drag and drop `ReactiveCocoa.xcodeproj` into your application’s Xcode\n+    project or workspace.\n+ 1. On the “General” tab of your application target’s settings, add\n+    `ReactiveCocoa.framework` to the “Embedded Binaries” section.","path":"README.md","position":729,"original_position":729,"commit_id":"11dd0a24de1ab72a77fa8cbea7ca2ebebe5599c1","original_commit_id":"11dd0a24de1ab72a77fa8cbea7ca2ebebe5599c1","user":{"login":"andymatuschak","id":2771,"avatar_url":"https://avatars.githubusercontent.com/u/2771?v=3","gravatar_id":"","url":"https://api.github.com/users/andymatuschak","html_url":"https://github.com/andymatuschak","followers_url":"https://api.github.com/users/andymatuschak/followers","following_url":"https://api.github.com/users/andymatuschak/following{/other_user}","gists_url":"https://api.github.com/users/andymatuschak/gists{/gist_id}","starred_url":"https://api.github.com/users/andymatuschak/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/andymatuschak/subscriptions","organizations_url":"https://api.github.com/users/andymatuschak/orgs","repos_url":"https://api.github.com/users/andymatuschak/repos","events_url":"https://api.github.com/users/andymatuschak/events{/privacy}","received_events_url":"https://api.github.com/users/andymatuschak/received_events","type":"User","site_admin":false},"body":"Perhaps we should link to the documentation again here, since practically speaking, you're not going to be able to get started without at least reading the framework overview.","created_at":"2015-07-18T14:36:37Z","updated_at":"2015-07-18T14:36:37Z","html_url":"https://github.com/ReactiveCocoa/ReactiveCocoa/pull/2181#discussion_r34948203","pull_request_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/pulls/2181","_links":{"self":{"href":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/pulls/comments/34948203"},"html":{"href":"https://github.com/ReactiveCocoa/ReactiveCocoa/pull/2181#discussion_r34948203"},"pull_request":{"href":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/pulls/2181"}}},"pull_request":{"url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/pulls/2181","id":40287108,"html_url":"https://github.com/ReactiveCocoa/ReactiveCocoa/pull/2181","diff_url":"https://github.com/ReactiveCocoa/ReactiveCocoa/pull/2181.diff","patch_url":"https://github.com/ReactiveCocoa/ReactiveCocoa/pull/2181.patch","issue_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/issues/2181","number":2181,"state":"open","locked":false,"title":"New README","user":{"login":"jspahrsummers","id":432536,"avatar_url":"https://avatars.githubusercontent.com/u/432536?v=3","gravatar_id":"","url":"https://api.github.com/users/jspahrsummers","html_url":"https://github.com/jspahrsummers","followers_url":"https://api.github.com/users/jspahrsummers/followers","following_url":"https://api.github.com/users/jspahrsummers/following{/other_user}","gists_url":"https://api.github.com/users/jspahrsummers/gists{/gist_id}","starred_url":"https://api.github.com/users/jspahrsummers/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jspahrsummers/subscriptions","organizations_url":"https://api.github.com/users/jspahrsummers/orgs","repos_url":"https://api.github.com/users/jspahrsummers/repos","events_url":"https://api.github.com/users/jspahrsummers/events{/privacy}","received_events_url":"https://api.github.com/users/jspahrsummers/received_events","type":"User","site_admin":false},"body":"Resolves #1483 and #2156.","created_at":"2015-07-18T05:33:37Z","updated_at":"2015-07-18T14:36:37Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e71ffc3e05645113513bb58f31eba7033a7420e8","assignee":null,"milestone":{"url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/milestones/4","html_url":"https://github.com/ReactiveCocoa/ReactiveCocoa/milestones/3.0","labels_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/milestones/4/labels","id":393809,"number":4,"title":"3.0","description":"Rethinking some of the [bigger underlying concepts in RAC](https://gist.github.com/jspahrsummers/7000136), particularly those inspired by Rx.\r\n\r\nHowever, we need to take backwards compatibility more seriously than we did for 1.x → 2.0, since our long-time users have already gone through that hellish migration, and we've gained even more users since then.","creator":{"login":"jspahrsummers","id":432536,"avatar_url":"https://avatars.githubusercontent.com/u/432536?v=3","gravatar_id":"","url":"https://api.github.com/users/jspahrsummers","html_url":"https://github.com/jspahrsummers","followers_url":"https://api.github.com/users/jspahrsummers/followers","following_url":"https://api.github.com/users/jspahrsummers/following{/other_user}","gists_url":"https://api.github.com/users/jspahrsummers/gists{/gist_id}","starred_url":"https://api.github.com/users/jspahrsummers/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jspahrsummers/subscriptions","organizations_url":"https://api.github.com/users/jspahrsummers/orgs","repos_url":"https://api.github.com/users/jspahrsummers/repos","events_url":"https://api.github.com/users/jspahrsummers/events{/privacy}","received_events_url":"https://api.github.com/users/jspahrsummers/received_events","type":"User","site_admin":false},"open_issues":4,"closed_issues":365,"state":"open","created_at":"2013-08-04T02:52:56Z","updated_at":"2015-07-18T06:56:55Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/pulls/2181/commits","review_comments_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/pulls/2181/comments","review_comment_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/issues/2181/comments","statuses_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/statuses/11dd0a24de1ab72a77fa8cbea7ca2ebebe5599c1","head":{"label":"ReactiveCocoa:readme-reboot","ref":"readme-reboot","sha":"11dd0a24de1ab72a77fa8cbea7ca2ebebe5599c1","user":{"login":"ReactiveCocoa","id":3422977,"avatar_url":"https://avatars.githubusercontent.com/u/3422977?v=3","gravatar_id":"","url":"https://api.github.com/users/ReactiveCocoa","html_url":"https://github.com/ReactiveCocoa","followers_url":"https://api.github.com/users/ReactiveCocoa/followers","following_url":"https://api.github.com/users/ReactiveCocoa/following{/other_user}","gists_url":"https://api.github.com/users/ReactiveCocoa/gists{/gist_id}","starred_url":"https://api.github.com/users/ReactiveCocoa/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ReactiveCocoa/subscriptions","organizations_url":"https://api.github.com/users/ReactiveCocoa/orgs","repos_url":"https://api.github.com/users/ReactiveCocoa/repos","events_url":"https://api.github.com/users/ReactiveCocoa/events{/privacy}","received_events_url":"https://api.github.com/users/ReactiveCocoa/received_events","type":"Organization","site_admin":false},"repo":{"id":3606624,"name":"ReactiveCocoa","full_name":"ReactiveCocoa/ReactiveCocoa","owner":{"login":"ReactiveCocoa","id":3422977,"avatar_url":"https://avatars.githubusercontent.com/u/3422977?v=3","gravatar_id":"","url":"https://api.github.com/users/ReactiveCocoa","html_url":"https://github.com/ReactiveCocoa","followers_url":"https://api.github.com/users/ReactiveCocoa/followers","following_url":"https://api.github.com/users/ReactiveCocoa/following{/other_user}","gists_url":"https://api.github.com/users/ReactiveCocoa/gists{/gist_id}","starred_url":"https://api.github.com/users/ReactiveCocoa/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ReactiveCocoa/subscriptions","organizations_url":"https://api.github.com/users/ReactiveCocoa/orgs","repos_url":"https://api.github.com/users/ReactiveCocoa/repos","events_url":"https://api.github.com/users/ReactiveCocoa/events{/privacy}","received_events_url":"https://api.github.com/users/ReactiveCocoa/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ReactiveCocoa/ReactiveCocoa","description":"Streams of values over time","fork":false,"url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa","forks_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/forks","keys_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/teams","hooks_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/hooks","issue_events_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/issues/events{/number}","events_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/events","assignees_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/assignees{/user}","branches_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/branches{/branch}","tags_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/tags","blobs_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/git/refs{/sha}","trees_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/statuses/{sha}","languages_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/languages","stargazers_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/stargazers","contributors_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/contributors","subscribers_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/subscribers","subscription_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/subscription","commits_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/commits{/sha}","git_commits_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/git/commits{/sha}","comments_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/comments{/number}","issue_comment_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/issues/comments{/number}","contents_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/contents/{+path}","compare_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/merges","archive_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/downloads","issues_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/issues{/number}","pulls_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/pulls{/number}","milestones_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/milestones{/number}","notifications_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/labels{/name}","releases_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/releases{/id}","created_at":"2012-03-02T22:11:24Z","updated_at":"2015-07-18T10:40:01Z","pushed_at":"2015-07-18T06:56:53Z","git_url":"git://github.com/ReactiveCocoa/ReactiveCocoa.git","ssh_url":"git@github.com:ReactiveCocoa/ReactiveCocoa.git","clone_url":"https://github.com/ReactiveCocoa/ReactiveCocoa.git","svn_url":"https://github.com/ReactiveCocoa/ReactiveCocoa","homepage":"","size":122096,"stargazers_count":9119,"watchers_count":9119,"language":"Objective-C","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1426,"mirror_url":null,"open_issues_count":128,"forks":1426,"open_issues":128,"watchers":9119,"default_branch":"swift-development"}},"base":{"label":"ReactiveCocoa:swift-development","ref":"swift-development","sha":"d7c269f2c3e6e34eeb3cd8005e72c989fe0c29fb","user":{"login":"ReactiveCocoa","id":3422977,"avatar_url":"https://avatars.githubusercontent.com/u/3422977?v=3","gravatar_id":"","url":"https://api.github.com/users/ReactiveCocoa","html_url":"https://github.com/ReactiveCocoa","followers_url":"https://api.github.com/users/ReactiveCocoa/followers","following_url":"https://api.github.com/users/ReactiveCocoa/following{/other_user}","gists_url":"https://api.github.com/users/ReactiveCocoa/gists{/gist_id}","starred_url":"https://api.github.com/users/ReactiveCocoa/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ReactiveCocoa/subscriptions","organizations_url":"https://api.github.com/users/ReactiveCocoa/orgs","repos_url":"https://api.github.com/users/ReactiveCocoa/repos","events_url":"https://api.github.com/users/ReactiveCocoa/events{/privacy}","received_events_url":"https://api.github.com/users/ReactiveCocoa/received_events","type":"Organization","site_admin":false},"repo":{"id":3606624,"name":"ReactiveCocoa","full_name":"ReactiveCocoa/ReactiveCocoa","owner":{"login":"ReactiveCocoa","id":3422977,"avatar_url":"https://avatars.githubusercontent.com/u/3422977?v=3","gravatar_id":"","url":"https://api.github.com/users/ReactiveCocoa","html_url":"https://github.com/ReactiveCocoa","followers_url":"https://api.github.com/users/ReactiveCocoa/followers","following_url":"https://api.github.com/users/ReactiveCocoa/following{/other_user}","gists_url":"https://api.github.com/users/ReactiveCocoa/gists{/gist_id}","starred_url":"https://api.github.com/users/ReactiveCocoa/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ReactiveCocoa/subscriptions","organizations_url":"https://api.github.com/users/ReactiveCocoa/orgs","repos_url":"https://api.github.com/users/ReactiveCocoa/repos","events_url":"https://api.github.com/users/ReactiveCocoa/events{/privacy}","received_events_url":"https://api.github.com/users/ReactiveCocoa/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ReactiveCocoa/ReactiveCocoa","description":"Streams of values over time","fork":false,"url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa","forks_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/forks","keys_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/teams","hooks_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/hooks","issue_events_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/issues/events{/number}","events_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/events","assignees_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/assignees{/user}","branches_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/branches{/branch}","tags_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/tags","blobs_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/git/refs{/sha}","trees_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/statuses/{sha}","languages_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/languages","stargazers_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/stargazers","contributors_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/contributors","subscribers_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/subscribers","subscription_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/subscription","commits_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/commits{/sha}","git_commits_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/git/commits{/sha}","comments_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/comments{/number}","issue_comment_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/issues/comments{/number}","contents_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/contents/{+path}","compare_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/merges","archive_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/downloads","issues_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/issues{/number}","pulls_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/pulls{/number}","milestones_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/milestones{/number}","notifications_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/labels{/name}","releases_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/releases{/id}","created_at":"2012-03-02T22:11:24Z","updated_at":"2015-07-18T10:40:01Z","pushed_at":"2015-07-18T06:56:53Z","git_url":"git://github.com/ReactiveCocoa/ReactiveCocoa.git","ssh_url":"git@github.com:ReactiveCocoa/ReactiveCocoa.git","clone_url":"https://github.com/ReactiveCocoa/ReactiveCocoa.git","svn_url":"https://github.com/ReactiveCocoa/ReactiveCocoa","homepage":"","size":122096,"stargazers_count":9119,"watchers_count":9119,"language":"Objective-C","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1426,"mirror_url":null,"open_issues_count":128,"forks":1426,"open_issues":128,"watchers":9119,"default_branch":"swift-development"}},"_links":{"self":{"href":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/pulls/2181"},"html":{"href":"https://github.com/ReactiveCocoa/ReactiveCocoa/pull/2181"},"issue":{"href":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/issues/2181"},"comments":{"href":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/issues/2181/comments"},"review_comments":{"href":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/pulls/2181/comments"},"review_comment":{"href":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/pulls/2181/commits"},"statuses":{"href":"https://api.github.com/repos/ReactiveCocoa/ReactiveCocoa/statuses/11dd0a24de1ab72a77fa8cbea7ca2ebebe5599c1"}}}}