How To Synchronize Core Data with a Web Service – Part 1

This is a post by iOS Tutorial Team Member Chris Wagner, an enthusiast in software engineering always trying to stay ahead of the curve. You can also find him on Google+. A lot of apps that store their data in a remote database only work when an Internet connection is available. Think about Twitter or […] By Chris Wagner.

Leave a rating/review
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

Manually trigger sync with remote service

Right now, your App will automatically sync when the user opens the App. This is generally an acceptable practice; however some users may want to refresh the dataset without leaving the App. You’ll next implement a refresh button on both the Holiday table view and Birthday table view in order to accomplish this.

Start by opening Storyboard.storyboard, locating the Holidays Date Table View Controller and dragging a Bar Button Item onto the top left side of the navigation bar. Once you have dragged the bar button item onto the nav bar, change its Identifier attribute to “Refresh” as seen below:

Now open the Assistant editor (the bow tie button in Xcode) and make sure SDDateTableViewController.h opens in the editor. Holding down the CTRL key, click and drag from the Refresh button to your interface to add a new IBAction named “refreshButtonTouched”:

Do this same process again, but this time instead of creating an Action, create an Outlet for the button and name it ‘refreshButton’. The outlet should be a strong reference, not a weak one — otherwise when the button is replaced by the activity indicator, it will be nil when the time comes to replace the button on the navigation bar.

Now select the Refresh button in your Storyboard, and while holding the Option/Alt key, click and drag it to your Birthdays Date Table View Controller to copy it, by copying you will also copy the outlets you already set up. Once you copy the button, with the Assistant editor still open you can hover the circles in the gutter next to your IBAction and IBOutlet to visually see the referenced outlets in the Storyboard, both buttons should highlight as shown below.

Open SDDateTableViewController.m and add an import for SDSyncEngine.h:

#import "SDSyncEngine.h"

Next complete the -refreshButtonTouched: method that was created for you during the Storyboard editing you just did, and add the following methods at the bottom of your class above @end:

- (IBAction)refreshButtonTouched:(id)sender {
    [[SDSyncEngine sharedEngine] startSync];
}

- (void)checkSyncStatus {
    if ([[SDSyncEngine sharedEngine] syncInProgress]) {
        [self replaceRefreshButtonWithActivityIndicator];
    } else {
        [self removeActivityIndicatorFromRefreshButton];
    }
}

- (void)replaceRefreshButtonWithActivityIndicator {
    UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 25, 25)];
    [activityIndicator setAutoresizingMask:(UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin)];
    [activityIndicator startAnimating];
    UIBarButtonItem *activityItem = [[UIBarButtonItem alloc] initWithCustomView:activityIndicator];
    self.navigationItem.leftBarButtonItem = activityItem;
}

- (void)removeActivityIndicatorFromRefreshButton {
    self.navigationItem.leftBarButtonItem = self.refreshButton;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"syncInProgress"]) {
        [self checkSyncStatus];
    }
}

-checkSyncStatus will ask the SDSyncEngine singleton if the sync is in progress. If so, it will call -replaceRefreshButtonWithActivityIndicator which does what it says,which is replace the refresh button with a UIActivityIndicatorView. Otherwise, the method will remove the UIActivityIndicatorView by replacing it with the refreshButton.

You will also implement -observeValueForKeyPath:ofObject:change:context: in order to observe changes in SDSyncEngine. To do so you will need to register for those notifications:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    [self checkSyncStatus];

    [[NSNotificationCenter defaultCenter] addObserverForName:@"SDSyncEngineSyncCompleted" object:nil queue:nil usingBlock:^(NSNotification *note) {
        [self loadRecordsFromCoreData];
        [self.tableView reloadData];
    }];
    [[SDSyncEngine sharedEngine] addObserver:self forKeyPath:@"syncInProgress" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"SDSyncEngineSyncCompleted" object:nil];
    [[SDSyncEngine sharedEngine] removeObserver:self forKeyPath:@"syncInProgress"];
}

Update -viewDidAppear: and -viewDidDisappear: to look like the above, also notice when the view appears we check the sync status immediately.

Now when you build and run the App, you will see an activity indicator while the sync is in progress and a refresh button when the sync is inactive. Touching the refresh button fires off the sync engine.

That’s it, folks! This concludes Part 1 of the tutorial.

Where To Go From Here!

You can download the project at this stage here.

Stay tuned for part 2 of this tutorial, where you’ll finish the app by adding the following features:

  1. Delete local objects when deleted on server
  2. Push locally created records to remote service
  3. Delete records on server when deleted locally

If you have any questions or comments, please join the forum discussion below!


This is a post by iOS Tutorial Team Member Chris Wagner, an enthusiast in software engineering always trying to stay ahead of the curve. You can also find him on .

Chris Wagner

Contributors

Chris Wagner

Author

Over 300 content creators. Join our team.