Repository: realm/realm-swift
File: Realm/RLMUpdateChecker.mm (Objective-C++)

Code before:
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#import "RLMUpdateChecker.hpp"

#import "RLMVersion.h"

void RLMCheckForUpdates() {
#if TARGET_IPHONE_SIMULATOR
    if (getenv("REALM_DISABLE_UPDATE_CHECKER")) {
        return;
    }

    // Only check if it's been at least a day since our last check
    NSUserDefaults *settings = [[NSUserDefaults alloc] initWithSuiteName:@"io.Realm.Realm"];
    double lastUpdateCheck = [settings doubleForKey:@"Last Update Check"];
    if ([[NSDate dateWithTimeIntervalSince1970:lastUpdateCheck] timeIntervalSinceNow] > -24 * 60 * 60) {
        return;
    }

    auto handler = ^(NSData *data, __unused NSURLResponse *response, NSError *error) {
        if (error) {
            NSLog(@"Failed to check for updates to Realm: %@", error);
            return;
        }
        switch (RLMProcessUpdateResponse(data, RLMVersionString, RLMVersionNumber)) {
            case RLMUpdateCheckerResult::InvalidateVersionFormat:
                NSLog(@"Failed to check for updates to Realm: Got version number in unexpected format");
                return;
            case RLMUpdateCheckerResult::UpdateAvailable:
                NSLog(@"A new version of Realm is available: http://static.realm.io/downloads/cocoa/latest");
                // fallthrough
            case RLMUpdateCheckerResult::UpToDate:
                [settings setDouble:NSDate.date.timeIntervalSince1970 forKey:@"Last Update Check"];
                break;
        }
    };

    NSString *url = [NSString stringWithFormat:@"http://static.realm.io/update/latest?%@", RLMVersionString];
    [[NSURLSession.sharedSession dataTaskWithURL:[NSURL URLWithString:url] completionHandler:handler] resume];
#endif
}

RLMUpdateCheckerResult RLMProcessUpdateResponse(NSData *data, const NSString *versionString, const int *versionNumber) {
    NSString *version = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    if ([versionString hasPrefix:version]) {
        return RLMUpdateCheckerResult::UpToDate;
    }

    NSArray *parts = [[version substringFromIndex:1] componentsSeparatedByString:@"."];
    if (parts.count != 3) {
        return RLMUpdateCheckerResult::InvalidateVersionFormat;
    }

    for (NSString *part in parts) {
        int partValue = part.intValue;
        if (*versionNumber > partValue) {
            // User has something newer than latest release
            return RLMUpdateCheckerResult::UpToDate;
        }
        if (*versionNumber++ < partValue) {
            return RLMUpdateCheckerResult::UpdateAvailable;
        }
    }
    return RLMUpdateCheckerResult::UpToDate;
}


Review comment (suggestion):
`< 24 * 60 * 60` won't work because `timeIntervalSinceNow` returns negative values for dates in the past. Keep it as-is.


Code after:
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#import "RLMUpdateChecker.hpp"

#import "RLMRealm.h"

void RLMCheckForUpdates() {
#if TARGET_IPHONE_SIMULATOR
    if (getenv("REALM_DISABLE_UPDATE_CHECKER")) {
        return;
    }

    // Only check if it's been at least a day since our last check
    NSUserDefaults *settings = [[NSUserDefaults alloc] initWithSuiteName:@"io.Realm.Realm"];
    double lastUpdateCheck = [settings doubleForKey:@"Last Update Check"];
    if (NSDate.timeIntervalSinceReferenceDate - lastUpdateCheck < 24 * 60 * 60) {
        return;
    }

#ifdef REALM_VERSION
    NSString *version = @REALM_VERSION;
#else
    NSBundle *bundle = [NSBundle bundleForClass:[RLMRealm class]];
    NSString *version = [bundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
#endif

    auto handler = ^(NSData *data, __unused NSURLResponse *response, NSError *error) {
        if (error) {
            NSLog(@"Failed to check for updates to Realm: %@", error);
            return;
        }

        NSString *latestVersion = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        if (![version isEqualToString:latestVersion]) {
            NSLog(@"Version %@ of Realm is now available: http://static.realm.io/downloads/cocoa/latest", latestVersion);
        }

        [settings setDouble:NSDate.timeIntervalSinceReferenceDate forKey:@"Last Update Check"];
    };

    NSString *url = [NSString stringWithFormat:@"http://static.realm.io/update/cocoa?%@", version];
    [[NSURLSession.sharedSession dataTaskWithURL:[NSURL URLWithString:url] completionHandler:handler] resume];
#endif
}