{"action":"created","comment":{"url":"https://api.github.com/repos/reactiveui/ReactiveUI/pulls/comments/26900514","id":26900514,"diff_hunk":"@@ -278,30 +234,74 @@ void resetupAll(IReadOnlyList<TSectionInfo> newSectionInfo)\n             //\n             // TODO: Instead of listening to Changed events and then reseting,\n             // we could listen to more specific events and avoid some reloads.\n-            disp.Add(sectionChanging.Subscribe(_ => {\n+            disp.Add(sectionChanging.ObserveOn(ImmediateScheduler.Instance).Subscribe(_ => {","path":"ReactiveUI/Cocoa/CommonReactiveSource.cs","position":null,"original_position":174,"commit_id":"c1d1eaa13668e8dd11da47aceb1a35f9d701da63","original_commit_id":"7d31351029443e23fd6b271599e36d28f4c6a805","user":{"login":"paulcbetts","id":1396,"avatar_url":"https://avatars.githubusercontent.com/u/1396?v=3","gravatar_id":"","url":"https://api.github.com/users/paulcbetts","html_url":"https://github.com/paulcbetts","followers_url":"https://api.github.com/users/paulcbetts/followers","following_url":"https://api.github.com/users/paulcbetts/following{/other_user}","gists_url":"https://api.github.com/users/paulcbetts/gists{/gist_id}","starred_url":"https://api.github.com/users/paulcbetts/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paulcbetts/subscriptions","organizations_url":"https://api.github.com/users/paulcbetts/orgs","repos_url":"https://api.github.com/users/paulcbetts/repos","events_url":"https://api.github.com/users/paulcbetts/events{/privacy}","received_events_url":"https://api.github.com/users/paulcbetts/received_events","type":"User","site_admin":false},"body":"Doing better than I am, I can't even build _Events.iOS64 right now, it fails telling me I need to include System.Runtime 4.0","created_at":"2015-03-22T07:24:33Z","updated_at":"2015-03-22T07:24:33Z","html_url":"https://github.com/reactiveui/ReactiveUI/pull/820#discussion_r26900514","pull_request_url":"https://api.github.com/repos/reactiveui/ReactiveUI/pulls/820","_links":{"self":{"href":"https://api.github.com/repos/reactiveui/ReactiveUI/pulls/comments/26900514"},"html":{"href":"https://github.com/reactiveui/ReactiveUI/pull/820#discussion_r26900514"},"pull_request":{"href":"https://api.github.com/repos/reactiveui/ReactiveUI/pulls/820"}}},"pull_request":{"url":"https://api.github.com/repos/reactiveui/ReactiveUI/pulls/820","id":30926777,"html_url":"https://github.com/reactiveui/ReactiveUI/pull/820","diff_url":"https://github.com/reactiveui/ReactiveUI/pull/820.diff","patch_url":"https://github.com/reactiveui/ReactiveUI/pull/820.patch","issue_url":"https://api.github.com/repos/reactiveui/ReactiveUI/issues/820","number":820,"state":"open","locked":false,"title":"Issue 808 (and 740)","user":{"login":"kentcb","id":1901832,"avatar_url":"https://avatars.githubusercontent.com/u/1901832?v=3","gravatar_id":"","url":"https://api.github.com/users/kentcb","html_url":"https://github.com/kentcb","followers_url":"https://api.github.com/users/kentcb/followers","following_url":"https://api.github.com/users/kentcb/following{/other_user}","gists_url":"https://api.github.com/users/kentcb/gists{/gist_id}","starred_url":"https://api.github.com/users/kentcb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kentcb/subscriptions","organizations_url":"https://api.github.com/users/kentcb/orgs","repos_url":"https://api.github.com/users/kentcb/repos","events_url":"https://api.github.com/users/kentcb/events{/privacy}","received_events_url":"https://api.github.com/users/kentcb/received_events","type":"User","site_admin":false},"body":"Fixes #808 and #740.\r\n\r\nApologies for the long descripion, but this was non-trivial to understand and fix so I want to elaborate for future (and current) reference. But let's start with some moving pictures:\r\n\r\nTable View:\r\n\r\n![rxui_808_pr_-_tableview](https://cloud.githubusercontent.com/assets/1901832/6593502/19ea919c-c829-11e4-8678-b2950b78d965.gif)\r\n\r\nCollection View:\r\n\r\n![rxui_808_pr_-_collectionview](https://cloud.githubusercontent.com/assets/1901832/6593544/761d202e-c829-11e4-8b05-52a5a630a599.gif)\r\n\r\nThe above is showing a repro that was failing very rapidly with the old code. Every 5-250 milliseconds, up to 18 items are randomly changed in a single UI message. One section (titled \"Rare\") is particularly, um, rare, so it pops in and out of existence quite often.\r\n\r\n# The Problems\r\n\r\nThe existing implementation of `CommonReactiveSource` (which serves as the base class for both `ReactiveTableViewSource` and `ReactiveCollectionViewSource`) has a number of deficiencies that prevent it from successfully and accurately functioning when batches of changes are made to the underlying list of data. It's probably best to address each problem individually.\r\n\r\n## Reload Completion Detection\r\n\r\nHaving accurate knowledge of when a reload is actually finished is crucial to being able to determine whether a change in the underlying data is already accounted for in the UI or not. If a change happens *after* iOS has finished reloading, it must be applied separately. If a change occurs *before* iOS has finished reloading, it must not be applied a second time when the reload completes.\r\n\r\nThe current code contains a hack to attempt to detect when iOS has finished processing a call to `ReloadData()`. Essentially, it uses a call to `NumberOfSections()` as a signal for completion of a previous call to `ReloadData()`. Alas, this does not always work and also occurs too early. iOS is yet to *completely* finish reloading when it calls this method - it calls other methods afterwards.\r\n\r\n## Batching Changes\r\n\r\nThe original code takes the approach of using `Buffer()` to batch together changes and then apply them. However, the use of `RxApp.MainThreadScheduler` is allowing iOS to interject some of its messages, which means it could see an inconsistent view of the data. Moreover, the result is perhaps a little less than ideal because client code has no way of making a batch of changes appear as one. Since the application of changes is time-based rather than batch-based, things could be applied at any point in the batch (if it worked, which it doesn't).\r\n\r\n## Index Normalization\r\n\r\nThe existing code made no attempt to \"normalize\" the changes within a batch to something that iOS can understand and work with. The simplest possible example is this:\r\n\r\n```C#\r\nsomeSection.Add(\"new item\");\r\nsomeSection.RemoveAt(0);\r\n```\r\n\r\nThis will result in an exception with the old code. Suppose there are 2 items already in the list when this code executes. The index received in the `NotifyCollectionChangedEventArgs` when calling `Add()` will therefore be `2`. So the old code will tell iOS \"insert at 2 and delete at 0\". iOS applies deletions first and then expects insertion indices to be relative to the list *with deletions already applied*. Thus, the correct thing to tell iOS is \"insert at 1 and delete at 0\" which iOS will enact as \"delete at 0 then insert at 1\".\r\n\r\nFar more complicated situations can arise because changes to the underlying data can be made in any order and indexes in those changes can refer to anywhere in the list. Thus, latter changes can affect the indices for prior changes and vice-versa. On top of that, iOS requires that we detect annulling changes and to not mention them. For example:\r\n\r\n```C#\r\nsomeSection.Insert(0, \"transient item\");\r\nsomeSection.RemoveAt(0);\r\n```\r\n\r\nThe above should result in no calls at all to insert/remove items because from iOS' perspective, nothing in the UI requires updating. On the other hand:\r\n\r\n```C#\r\nsomeSection.Insert(0, \"new item\");\r\nsomeSection.RemoveAt(1);\r\n```\r\n\r\nThat should result in \"remove at 0 and delete at 0\".\r\n\r\nBasically, the whole index normalization thing is entirely non-trivial and difficult to get your head around (at least it was for me). Try to visualize, for example, how a batch of updates `\"D0:A0:A0:A5:A2:D3:A5:D2:A3:A1\"` (A=add, D=delete) would normalize to `\"D0:A2:A0:A7:D1:A6:A4:A1\"`. I had to spend a great deal of time shifting labelled paperclips about to get my head around the normalization process.\r\n\r\n# The Solutions\r\n\r\n## Reload Completion Detection\r\n\r\nThe fact that Apple hasn't surfaced an API for this is beyond terrible. There are lots of people struggling with this on the Interwebs.\r\n\r\nThe solution I settled on was to expose an `IObservable<bool>` from `IUICollViewAdapter` that ticks `false` if data is not reloading, or `true` if it is. The implementation basically involves calling `ReloadData()` and then immediately queueing another \"finished\" message. The idea is that 'RefreshData()' is queueing its own work and so any message scheduled afterwards will execute after the iOS work is completed.\r\n\r\nUnfortunately, iOS screws things up by sometimes scheduling *additional* work (*after* I have scheduled my work) that will result in calls to `GetCell()`. This creates the possibility of the data changing before the calls to `GetCell()`, which could result in invalid index exceptions. So in addition to queueing the separate message, I also call `LayoutIfNeeded()` on the view once the \"finish\" message is executed. Only once that layout has been instigated (thus initiating the calls to `GetCell()`) do I tick `true` on the `IsReloading` observable. So now the client code (in `CommonReactiveSource`) can accurately determine whether reloading is happening or not.\r\n\r\n## Batching Changes\r\n\r\nThe new code takes the approach of enacting changes immediately by use of the immediate scheduler. For clarity, it is purposely explicit in its use of the immediate scheduler, even though I believe it's the default for all cases.\r\n\r\nBy immediately detecting a change, the code can schedule a future message to apply those changes on the UI thread. Meanwhile, it collects changes to apply into a list. In addition, it can use the `IsReloading` observable in the adapter to determine whether changes that come in should instigate another reload or not.\r\n\r\nThe client code should also just use the immediate (default) scheduler when constructing its various reactive collections for the sections and the section's contents.\r\n\r\n## Index Normalization\r\n\r\nThe index normalization algorithm is manifest in the `IndexNormalizer` class. There are accompanying tests, which is great because of the difficulty of reasoning about what the expected results should be.\r\n\r\nAll `NotifyCollectionChangedEventArgs`' are reduced down to one or more `Update` instances, which have a `Type` of either `Add` or `Delete`, plus an `Index`. The essence of the normalization algorithm is to take any number of these updates (whose indexes initially refer to the original index specified by client code) and return a new set of `Update` instances whose indices are iOS-specific and are calculated by examining the updates before or after them. Annulling updates are also removed.\r\n\r\n# Possible Future Enhancements\r\n\r\nIn this PR, I've only made the changes necessary to fix the actual bugs. If I ever find the time, there are some other things I'd like to do...\r\n\r\n## Bug in Collection View Support\r\n\r\nThere is a strange bug in the collection view implementation. Some time (> 1 minute) after my \"Hammer Time!\" scenario starts execution (see GIF above) I get an exception like this:\r\n\r\n```\r\nMonoTouch.Foundation.MonoTouchException: Objective-C exception thrown.  Name: NSInternalInconsistencyException Reason: request for index path for global index 10458164 when there are only 20 items in the collection view\r\n  at MonoTouch.ObjCRuntime.Runtime.ThrowNSException (IntPtr ns_exception) [0x00000] in /Developer/MonoTouch/Source/maccore/src/ObjCRuntime/Runtime.cs:156 \r\n  at MonoTouch.ObjCRuntime.Runtime.throw_ns_exception (IntPtr exc) [0x00000] in /Developer/MonoTouch/Source/maccore/runtime/Delegates.generated.cs:100 \r\n  at (wrapper native-to-managed) MonoTouch.ObjCRuntime.Runtime:throw_ns_exception (intptr)\r\n  at (wrapper managed-to-native) MonoTouch.ObjCRuntime.Messaging:void_objc_msgSend_IntPtr_IntPtr (intptr,intptr,intptr,intptr)\r\n  at MonoTouch.UIKit.UICollectionView.PerformBatchUpdates (MonoTouch.Foundation.NSAction updates, MonoTouch.UIKit.UICompletionHandler completed) [0x0005f] in /Developer/MonoTouch/Source/monotouch/src/build/compat/UIKit/UICollectionView.g.cs:384 \r\n  at ReactiveUI.UICollectionViewAdapter.PerformBatchUpdates (System.Action updates, System.Action completion) [0x0000e] in Y:\\Repository\\ReactiveUI\\ReactiveUI\\Cocoa\\ReactiveCollectionViewSource.cs:84 \r\n  at ReactiveUI.CommonReactiveSource`4[RxUIReactiveTableViewSourceRepro.ItemViewModel,MonoTouch.UIKit.UICollectionView,MonoTouch.UIKit.UICollectionViewCell,ReactiveUI.CollectionViewSectionInformation`1[RxUIReactiveTableViewSourceRepro.ItemViewModel]].ApplyPendingChanges () [0x0002b] in Y:\\Repository\\ReactiveUI\\ReactiveUI\\Cocoa\\CommonReactiveSource.cs:325 \r\n  at ReactiveUI.CommonReactiveSource`4[RxUIReactiveTableViewSourceRepro.ItemViewModel,MonoTouch.UIKit.UICollectionView,MonoTouch.UIKit.UICollectionViewCell,ReactiveUI.CollectionViewSectionInformation`1[RxUIReactiveTableViewSourceRepro.ItemViewModel]].<AttachToSectionInfo>b__20_9 () [0x00000] in Y:\\Repository\\ReactiveUI\\ReactiveUI\\Cocoa\\CommonReactiveSource.cs:292 \r\n  at System.Reactive.Concurrency.Scheduler.Invoke (IScheduler scheduler, System.Action action) [0x00000] in <filename unknown>:0 \r\n  at ReactiveUI.NSRunloopScheduler+<>c__DisplayClass2_0`1[System.Action].<Schedule>b__0 () [0x00013] in Y:\\Repository\\ReactiveUI\\ReactiveUI\\Cocoa\\NSRunloopScheduler.cs:35 \r\n  at MonoTouch.CoreFoundation.DispatchQueue.static_dispatcher_to_managed (IntPtr context) [0x00036] in /Developer/MonoTouch/Source/maccore/src/CoreFoundation/Dispatch.cs:310 \r\nNSInternalInconsistencyException: request for index path for global index 10458164 when there are only 20 items in the collection view\r\n\t0   CoreFoundation                      0x0077e946 __exceptionPreprocess + 182\r\n\t1   libobjc.A.dylib                     0x07415a97 objc_exception_throw + 44\r\n\t2   CoreFoundation                      0x0077e7da +[NSException raise:format:arguments:] + 138\r\n\t3   Foundation                          0x00e05810 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 118\r\n\t4   UIKit                               0x0380341b -[UICollectionViewData indexPathForItemAtGlobalIndex:] + 279\r\n\t5   UIKit                               0x037db2b3 -[UICollectionViewLayout prepareForCollectionViewUpdates:] + 634\r\n\t6   UIKit                               0x037ce9e4 -[UICollectionView _prepareLayoutForUpdates] + 322\r\n\t7   UIKit                               0x037d2fcb -[UICollectionView _updateWithItems:] + 1490\r\n\t8   UIKit                               0x037ce71c -[UICollectionView _endItemAnimations] + 14609\r\n\t9   UIKit                               0x037d45c8 -[UICollectionView _endUpdates] + 44\r\n\t10  UIKit                               0x037d477a -[UICollectionView performBatchUpdates:completion:] + 429\r\n\t11  ???                                 0x17731a14 0x0 + 393419284\r\n\t12  ???                                 0x17bb4c9c 0x0 + 398150812\r\n\t13  ???                                 0x17bb48e0 0x0 + 398149856\r\n\t14  ???                                 0x179d5403 0x0 + 396186627\r\n\t15  ???                                 0x179d5210 0x0 + 396186128\r\n\t16  ???                                 0x173080fe 0x0 + 389054718\r\n\t17  ???                                 0x1772e063 0x0 + 393404515\r\n\t18  ???                                 0x17724658 0x0 + 393365080\r\n\t19  ???                                 0x172fd464 0x0 + 389010532\r\n\t20  libdispatch.dylib                   0x0772d03f _dispatch_client_callout + 14\r\n\t21  libdispatch.dylib                   0x07716764 _dispatch_main_queue_callback_4CF + 470\r\n\t22  CoreFoundation                      0x006d895e __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 14\r\n\t23  CoreFoundation                      0x00697760 __CFRunLoopRun + 2256\r\n\t24  CoreFoundation                      0x00696bcb CFRunLoopRunSpecific + 443\r\n\t25  CoreFoundation                      0x006969fb CFRunLoopRunInMode + 123\r\n\t26  GraphicsServices                    0x098e724f GSEventRunModal + 192\r\n\t27  GraphicsServices                    0x098e708c GSEventRun + 104\r\n\t28  UIKit                               0x030a08b6 UIApplicationMain + 1526\r\n\t29  ???                                 0x1612b650 0x0 + 370325072\r\n\t30  ???                                 0x1612b450 0x0 + 370324560\r\n\t31  ???                                 0x16129788 0x0 + 370317192\r\n\t32  ???                                 0x16129534 0x0 + 370316596\r\n\t33  ???                                 0x1612966a 0x0 + 370316906\r\n\t34  RxUIReactiveTableViewSourceRepro    0x00185b45 mono_jit_runtime_invoke + 725\r\n\t35  RxUIReactiveTableViewSourceRepro    0x00223e9f mono_runtime_invoke + 127\r\n\t36  RxUIReactiveTableViewSourceRepro    0x00228ca1 mono_runtime_exec_main + 401\r\n\t37  RxUIReactiveTableViewSourceRepro    0x00228a64 mono_runtime_run_main + 628\r\n\t38  RxUIReactiveTableViewSourceRepro    0x000e41dd mono_jit_exec + 93\r\n\t39  RxUIReactiveTableViewSourceRepro    0x002c6324 xamarin_main + 2500\r\n\t40  RxUIReactiveTableViewSourceRepro    0x002dc945 main + 117\r\n\t41  libdyld.dylib                       0x07753ac9 start + 1\r\n```\r\n\r\nIt looks like it might be a Xamarin/iOS issue, so I'll try to create a useful repro and submit to them. Note that there is nothing wrong with the indices being passed in - something funky is going on inside `PerformBatchUpdates()`, and the table view is not susceptible presumably because it does batch updates via a different mechanism.\r\n\r\n## Section Change Support\r\n\r\nBoth the old code and new reload data whenever a section is added or removed. It would be cool if changes *to* sections underwent the same process as changes *within* a section. The existing code already has a TODO around this, but it should be far more viable now because normalizing indices for sections can use exactly the same logic as normalizing indices for changes within those sections.\r\n\r\nUnfortunately, changes to sections can result in required changes to the section numbers recorded for changes within sections:\r\n\r\n```C#\r\n// change occurs against section 0\r\ndata[0].Insert(0, \"Some data\");\r\n// but section 0 now becomes section 1\r\ndata.Insert(0, new List<string>());\r\n```\r\n\r\nNote that I have modified the `IUICollViewAdapter` interface and its implementations to include methods for manipulating individual sections, but nothing currently uses those new methods. I can remove if you think that necessary.\r\n\r\n## Move Support\r\n\r\nIt would be awesome if the removal and insertion of the same item is detected as a move, and thus the correct move animation is triggered rather than separate remove and add animations.\r\n\r\n# Random Thoughts\r\n\r\nI put quite a bit of effort into a test harness (pictured in the GIFs above) that was super useful in tracking down various issues. For future reference, I have made it available [here](http://cl.ly/270m0d1q2N2U). It just needs package restore and a reference to the ReactiveUI_iOS project.","created_at":"2015-03-11T09:34:13Z","updated_at":"2015-03-22T07:24:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f1d38ad192bb04703fb884d998e687dd978a569e","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/reactiveui/ReactiveUI/pulls/820/commits","review_comments_url":"https://api.github.com/repos/reactiveui/ReactiveUI/pulls/820/comments","review_comment_url":"https://api.github.com/repos/reactiveui/ReactiveUI/pulls/comments{/number}","comments_url":"https://api.github.com/repos/reactiveui/ReactiveUI/issues/820/comments","statuses_url":"https://api.github.com/repos/reactiveui/ReactiveUI/statuses/c1d1eaa13668e8dd11da47aceb1a35f9d701da63","head":{"label":"kentcb:Issue808","ref":"Issue808","sha":"c1d1eaa13668e8dd11da47aceb1a35f9d701da63","user":{"login":"kentcb","id":1901832,"avatar_url":"https://avatars.githubusercontent.com/u/1901832?v=3","gravatar_id":"","url":"https://api.github.com/users/kentcb","html_url":"https://github.com/kentcb","followers_url":"https://api.github.com/users/kentcb/followers","following_url":"https://api.github.com/users/kentcb/following{/other_user}","gists_url":"https://api.github.com/users/kentcb/gists{/gist_id}","starred_url":"https://api.github.com/users/kentcb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kentcb/subscriptions","organizations_url":"https://api.github.com/users/kentcb/orgs","repos_url":"https://api.github.com/users/kentcb/repos","events_url":"https://api.github.com/users/kentcb/events{/privacy}","received_events_url":"https://api.github.com/users/kentcb/received_events","type":"User","site_admin":false},"repo":{"id":31523102,"name":"ReactiveUI","full_name":"kentcb/ReactiveUI","owner":{"login":"kentcb","id":1901832,"avatar_url":"https://avatars.githubusercontent.com/u/1901832?v=3","gravatar_id":"","url":"https://api.github.com/users/kentcb","html_url":"https://github.com/kentcb","followers_url":"https://api.github.com/users/kentcb/followers","following_url":"https://api.github.com/users/kentcb/following{/other_user}","gists_url":"https://api.github.com/users/kentcb/gists{/gist_id}","starred_url":"https://api.github.com/users/kentcb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kentcb/subscriptions","organizations_url":"https://api.github.com/users/kentcb/orgs","repos_url":"https://api.github.com/users/kentcb/repos","events_url":"https://api.github.com/users/kentcb/events{/privacy}","received_events_url":"https://api.github.com/users/kentcb/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/kentcb/ReactiveUI","description":"A MVVM framework that integrates with the Reactive Extensions for .NET to create elegant, testable User Interfaces that run on any mobile or desktop platform. Supports Xamarin.iOS, Xamarin.Android, Xamarin.Mac, WPF, Windows Forms, Windows Phone 8 and Windows Store apps.","fork":true,"url":"https://api.github.com/repos/kentcb/ReactiveUI","forks_url":"https://api.github.com/repos/kentcb/ReactiveUI/forks","keys_url":"https://api.github.com/repos/kentcb/ReactiveUI/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kentcb/ReactiveUI/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kentcb/ReactiveUI/teams","hooks_url":"https://api.github.com/repos/kentcb/ReactiveUI/hooks","issue_events_url":"https://api.github.com/repos/kentcb/ReactiveUI/issues/events{/number}","events_url":"https://api.github.com/repos/kentcb/ReactiveUI/events","assignees_url":"https://api.github.com/repos/kentcb/ReactiveUI/assignees{/user}","branches_url":"https://api.github.com/repos/kentcb/ReactiveUI/branches{/branch}","tags_url":"https://api.github.com/repos/kentcb/ReactiveUI/tags","blobs_url":"https://api.github.com/repos/kentcb/ReactiveUI/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kentcb/ReactiveUI/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kentcb/ReactiveUI/git/refs{/sha}","trees_url":"https://api.github.com/repos/kentcb/ReactiveUI/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kentcb/ReactiveUI/statuses/{sha}","languages_url":"https://api.github.com/repos/kentcb/ReactiveUI/languages","stargazers_url":"https://api.github.com/repos/kentcb/ReactiveUI/stargazers","contributors_url":"https://api.github.com/repos/kentcb/ReactiveUI/contributors","subscribers_url":"https://api.github.com/repos/kentcb/ReactiveUI/subscribers","subscription_url":"https://api.github.com/repos/kentcb/ReactiveUI/subscription","commits_url":"https://api.github.com/repos/kentcb/ReactiveUI/commits{/sha}","git_commits_url":"https://api.github.com/repos/kentcb/ReactiveUI/git/commits{/sha}","comments_url":"https://api.github.com/repos/kentcb/ReactiveUI/comments{/number}","issue_comment_url":"https://api.github.com/repos/kentcb/ReactiveUI/issues/comments{/number}","contents_url":"https://api.github.com/repos/kentcb/ReactiveUI/contents/{+path}","compare_url":"https://api.github.com/repos/kentcb/ReactiveUI/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kentcb/ReactiveUI/merges","archive_url":"https://api.github.com/repos/kentcb/ReactiveUI/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kentcb/ReactiveUI/downloads","issues_url":"https://api.github.com/repos/kentcb/ReactiveUI/issues{/number}","pulls_url":"https://api.github.com/repos/kentcb/ReactiveUI/pulls{/number}","milestones_url":"https://api.github.com/repos/kentcb/ReactiveUI/milestones{/number}","notifications_url":"https://api.github.com/repos/kentcb/ReactiveUI/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kentcb/ReactiveUI/labels{/name}","releases_url":"https://api.github.com/repos/kentcb/ReactiveUI/releases{/id}","created_at":"2015-03-02T04:16:16Z","updated_at":"2015-03-02T04:16:18Z","pushed_at":"2015-03-22T06:18:47Z","git_url":"git://github.com/kentcb/ReactiveUI.git","ssh_url":"git@github.com:kentcb/ReactiveUI.git","clone_url":"https://github.com/kentcb/ReactiveUI.git","svn_url":"https://github.com/kentcb/ReactiveUI","homepage":"http://www.reactiveui.net","size":70054,"stargazers_count":0,"watchers_count":0,"language":"C#","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"reactiveui:master","ref":"master","sha":"238524a922aed50f8141a1d26ff24b8f2b101b60","user":{"login":"reactiveui","id":2327577,"avatar_url":"https://avatars.githubusercontent.com/u/2327577?v=3","gravatar_id":"","url":"https://api.github.com/users/reactiveui","html_url":"https://github.com/reactiveui","followers_url":"https://api.github.com/users/reactiveui/followers","following_url":"https://api.github.com/users/reactiveui/following{/other_user}","gists_url":"https://api.github.com/users/reactiveui/gists{/gist_id}","starred_url":"https://api.github.com/users/reactiveui/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/reactiveui/subscriptions","organizations_url":"https://api.github.com/users/reactiveui/orgs","repos_url":"https://api.github.com/users/reactiveui/repos","events_url":"https://api.github.com/users/reactiveui/events{/privacy}","received_events_url":"https://api.github.com/users/reactiveui/received_events","type":"Organization","site_admin":false},"repo":{"id":715082,"name":"ReactiveUI","full_name":"reactiveui/ReactiveUI","owner":{"login":"reactiveui","id":2327577,"avatar_url":"https://avatars.githubusercontent.com/u/2327577?v=3","gravatar_id":"","url":"https://api.github.com/users/reactiveui","html_url":"https://github.com/reactiveui","followers_url":"https://api.github.com/users/reactiveui/followers","following_url":"https://api.github.com/users/reactiveui/following{/other_user}","gists_url":"https://api.github.com/users/reactiveui/gists{/gist_id}","starred_url":"https://api.github.com/users/reactiveui/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/reactiveui/subscriptions","organizations_url":"https://api.github.com/users/reactiveui/orgs","repos_url":"https://api.github.com/users/reactiveui/repos","events_url":"https://api.github.com/users/reactiveui/events{/privacy}","received_events_url":"https://api.github.com/users/reactiveui/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/reactiveui/ReactiveUI","description":"A MVVM framework that integrates with the Reactive Extensions for .NET to create elegant, testable User Interfaces that run on any mobile or desktop platform. Supports Xamarin.iOS, Xamarin.Android, Xamarin.Mac, WPF, Windows Forms, Windows Phone 8 and Windows Store apps.","fork":false,"url":"https://api.github.com/repos/reactiveui/ReactiveUI","forks_url":"https://api.github.com/repos/reactiveui/ReactiveUI/forks","keys_url":"https://api.github.com/repos/reactiveui/ReactiveUI/keys{/key_id}","collaborators_url":"https://api.github.com/repos/reactiveui/ReactiveUI/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/reactiveui/ReactiveUI/teams","hooks_url":"https://api.github.com/repos/reactiveui/ReactiveUI/hooks","issue_events_url":"https://api.github.com/repos/reactiveui/ReactiveUI/issues/events{/number}","events_url":"https://api.github.com/repos/reactiveui/ReactiveUI/events","assignees_url":"https://api.github.com/repos/reactiveui/ReactiveUI/assignees{/user}","branches_url":"https://api.github.com/repos/reactiveui/ReactiveUI/branches{/branch}","tags_url":"https://api.github.com/repos/reactiveui/ReactiveUI/tags","blobs_url":"https://api.github.com/repos/reactiveui/ReactiveUI/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/reactiveui/ReactiveUI/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/reactiveui/ReactiveUI/git/refs{/sha}","trees_url":"https://api.github.com/repos/reactiveui/ReactiveUI/git/trees{/sha}","statuses_url":"https://api.github.com/repos/reactiveui/ReactiveUI/statuses/{sha}","languages_url":"https://api.github.com/repos/reactiveui/ReactiveUI/languages","stargazers_url":"https://api.github.com/repos/reactiveui/ReactiveUI/stargazers","contributors_url":"https://api.github.com/repos/reactiveui/ReactiveUI/contributors","subscribers_url":"https://api.github.com/repos/reactiveui/ReactiveUI/subscribers","subscription_url":"https://api.github.com/repos/reactiveui/ReactiveUI/subscription","commits_url":"https://api.github.com/repos/reactiveui/ReactiveUI/commits{/sha}","git_commits_url":"https://api.github.com/repos/reactiveui/ReactiveUI/git/commits{/sha}","comments_url":"https://api.github.com/repos/reactiveui/ReactiveUI/comments{/number}","issue_comment_url":"https://api.github.com/repos/reactiveui/ReactiveUI/issues/comments{/number}","contents_url":"https://api.github.com/repos/reactiveui/ReactiveUI/contents/{+path}","compare_url":"https://api.github.com/repos/reactiveui/ReactiveUI/compare/{base}...{head}","merges_url":"https://api.github.com/repos/reactiveui/ReactiveUI/merges","archive_url":"https://api.github.com/repos/reactiveui/ReactiveUI/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/reactiveui/ReactiveUI/downloads","issues_url":"https://api.github.com/repos/reactiveui/ReactiveUI/issues{/number}","pulls_url":"https://api.github.com/repos/reactiveui/ReactiveUI/pulls{/number}","milestones_url":"https://api.github.com/repos/reactiveui/ReactiveUI/milestones{/number}","notifications_url":"https://api.github.com/repos/reactiveui/ReactiveUI/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/reactiveui/ReactiveUI/labels{/name}","releases_url":"https://api.github.com/repos/reactiveui/ReactiveUI/releases{/id}","created_at":"2010-06-11T05:24:29Z","updated_at":"2015-03-22T04:26:12Z","pushed_at":"2015-03-22T06:18:48Z","git_url":"git://github.com/reactiveui/ReactiveUI.git","ssh_url":"git@github.com:reactiveui/ReactiveUI.git","clone_url":"https://github.com/reactiveui/ReactiveUI.git","svn_url":"https://github.com/reactiveui/ReactiveUI","homepage":"http://www.reactiveui.net","size":85142,"stargazers_count":1458,"watchers_count":1458,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":335,"mirror_url":null,"open_issues_count":83,"forks":335,"open_issues":83,"watchers":1458,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/reactiveui/ReactiveUI/pulls/820"},"html":{"href":"https://github.com/reactiveui/ReactiveUI/pull/820"},"issue":{"href":"https://api.github.com/repos/reactiveui/ReactiveUI/issues/820"},"comments":{"href":"https://api.github.com/repos/reactiveui/ReactiveUI/issues/820/comments"},"review_comments":{"href":"https://api.github.com/repos/reactiveui/ReactiveUI/pulls/820/comments"},"review_comment":{"href":"https://api.github.com/repos/reactiveui/ReactiveUI/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/reactiveui/ReactiveUI/pulls/820/commits"},"statuses":{"href":"https://api.github.com/repos/reactiveui/ReactiveUI/statuses/c1d1eaa13668e8dd11da47aceb1a35f9d701da63"}}}}