Inheritance: NSManagedObject
        public override NSView GetViewForItem(NSTableView tableView, NSTableColumn tableColumn, nint row)
        {
            string          identifier = tableColumn.Identifier;
            NSTableCellView cellView   = (NSTableCellView)tableView.MakeView(identifier, this);
            Quake           quake      = quakesSource [(int)row];

            if (identifier == ColumnIdentifierPlace)
            {
                cellView.TextField.StringValue = quake.Location;
            }
            else if (identifier == ColumnIdentifierTime)
            {
                cellView.TextField.ObjectValue = quake.Date;
            }
            else if (identifier == ColumnIdentifierMagnitude)
            {
                cellView.TextField.ObjectValue = quake.Magnitude;
            }

            return(cellView);
        }
        void FetchQuakes(object sender, EventArgs e)
        {
            fetchQuakesButton.Enabled = false;
            var jsonURL           = new NSUrl("http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson");
            var session           = NSUrlSession.FromConfiguration(NSUrlSessionConfiguration.EphemeralSessionConfiguration);
            NSUrlSessionTask task = session.CreateDataTask(jsonURL, (data, response, error) => {
                if (data == null)
                {
                    Console.WriteLine("Error connecting: {0}", error.LocalizedDescription);
                    return;
                }

                NSError anyError;
                NSManagedObjectContext taskContext = CreatePrivateQueueContext(out anyError);
                var jsonDictionary = NSJsonSerialization.Deserialize(data, NSJsonReadingOptions.AllowFragments, out anyError);

                if (jsonDictionary == null)
                {
                    Console.WriteLine("Error creating JSON dictionary: {0}", anyError.LocalizedDescription);
                    return;
                }

                var featuresArray     = (NSArray)jsonDictionary.ValueForKey((NSString)"features");
                int totalFeatureCount = (int)featuresArray.Count;

                int numBatches = totalFeatureCount / BatchSize;
                numBatches    += totalFeatureCount % BatchSize > 0 ? 1 : 0;
                for (int batchNumber = 0; batchNumber < numBatches; batchNumber++)
                {
                    int rangeStart  = batchNumber * BatchSize;
                    int rangeLength = Math.Min(BatchSize, totalFeatureCount - batchNumber * BatchSize);

                    NSArray featuresBatchArray = featuresArray.SubarrayWithRange(new NSRange(rangeStart, rangeLength));
                    // Create a request to fetch existing quakes with the same codes as those in the JSON data.
                    // Existing quakes will be updated with new data; if there isn't a match, then create a new quake to represent the event.
                    NSFetchRequest matchingQuakeRequest = NSFetchRequest.FromEntityName("Quake");

                    // Get the codes for each of the features and store them in an array.
                    NSArray codesDump = (NSArray)featuresBatchArray.ValueForKeyPath((NSString)"properties.code");

                    matchingQuakeRequest.Predicate = NSPredicate.FromFormat("code in %@", codesDump);
                    var rawFetch = taskContext.ExecuteFetchRequest(matchingQuakeRequest, out anyError);
                    Quake[] allMatchingQuakes = Array.ConvertAll(rawFetch, item => (Quake)item);
                    NSString[] codes          = NSArray.FromArray <NSString> (codesDump);

                    for (int k = 0; k < codes.Length; k++)
                    {
                        var code           = codes [k];
                        var matchingQuakes = allMatchingQuakes.Where(q => q.Code == code).ToArray <Quake> ();

                        Quake quake = null;

                        int matchingLength = matchingQuakes.Length;
                        switch (matchingLength)
                        {
                        case 0:
                            //Insert new item
                            quake = (Quake)NSEntityDescription.InsertNewObjectForEntityForName("Quake", taskContext);
                            break;

                        case 1:
                            //Update existing item
                            quake = matchingQuakes [0];
                            break;

                        default:
                            //Remove duplicates
                            for (int i = 1; i < matchingQuakes.Length; i++)
                            {
                                taskContext.DeleteObject(matchingQuakes [i]);
                            }

                            quake = matchingQuakes [0];
                            break;
                        }

                        var result          = featuresBatchArray.GetItem <NSDictionary> ((nuint)k);
                        var quakeDictionary = (NSDictionary)result.ObjectForKey((NSString)"properties");
                        quake.UpdateFromDictionary(quakeDictionary);
                    }

                    if (!taskContext.Save(out anyError))
                    {
                        Console.WriteLine("Error saving batch: {0}", anyError.LocalizedDescription);
                        return;
                    }

                    taskContext.Reset();
                }

                // Bounce back to the main queue to reload the table view and reenable the fetch button.
                NSOperationQueue.MainQueue.AddOperation(() => {
                    ReloadTableView();
                    fetchQuakesButton.Enabled = true;
                });
            });

            task.Resume();
        }