Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

Stephen McMillan
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Stephen McMillan
iOS Development with Swift Techdegree Graduate 33,994 Points

Changing a string after 24 hours?

I'm in the process of creating a new app however I can't find a solution for my problem.

Basically I want a label to change everyday at a time the user chooses (via DatePicker) It needs to work when the app closes... I've tried UILocalNotification but it's completely confused me.

Any suggestions would be greatly appreciated =)

1 Answer

One way to approach this is to do something like "every time the app launches and the label is about to be shown, if it's after the time the user specified, then change the label". One way to do this check is to store the hour and minute the user specifies (and optionally seconds) on the device and check if the current device time is greater than that time. The first step, though, is storing the hour (military time so all values are unique!) and minute on the device, between app launches. You can do this with NSUserDefaults. NSUserDefaults is basically like a dictionary that is unique to your application - when you set something in NSUserDefaults, the device will save it to the device so you can access it later, even after you quit the application. Here's how you use it:

[[NSUserDefaults standardUserDefaults] setInteger:hour forKey:@"UserSpecifiedHour"];

[NSUserDefaults standardUserDefaults] gets the shared NSUserDefaults instance for your app, and then setInteger:forKey: (one of the methods for setting info) adds the given NSInteger for the given key (which is a string, but can be anything you want - you just have to remember it later if you want to access the data stored in NSUserDefaults).

To retrieve info from NSUserDefaults, do something like this:

NSInteger hour = [[NSUserDefaults standardUserDefaults] integerForKey:@"UserSpecifiedHour"];

One extra case you have to be careful about is if you try to access something in NSUserDefaults before you've set it the first time. To avoid this, there's a method called [-registerDefaults] that sets the default values for NSUserDefaults. So the first time your app launches, your NSUserDefaults will have default values. If you change NSUserDefaults later, the defaults will be overwritten. You use [-registerDefaults] like this:

NSDictionary *defaults = @{@"UserSpecifiedHour": hour, @"UserSpecifiedMinute": minute}; // The first-time defaults for the time
[[NSUserDefaults standardUserDefaults] registerDefaults: defaults];

This will set a default time for changing the label until the user overwrites it.

The second piece is how to compare times. We can easily get an NSDate representing the current date/time by calling [NSDate date]:

NSDate *now = [NSDate date];

It's also easy to compare NSDates. So let's turn our hour and minute into an NSDate. To do that, we have to make an NSDateComponents, fill it in with our hour and minute, and make a date out of it. But since we only have the hour and minute, we need to pull the day, month, and year from the current date:

NSDate *now = [NSDate date];

// Make a new NSDateComponents representing the current date.  It will only have the day, month,
// and year from the current date (since those are the only components we need - we can set the rest).
NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:now];

// Set the hour and minute
[dateComponents setHour:hour];
[dateComponents setMinute:minute];

// Now make a date out of the updated date components
NSDate *changeDate = [[NSCalendar currentCalendar] dateFromComponents:dateComponents];

To compare dates, use the [-compare] method. It returns either NSOrderedSame, NSOrderedAscending, or NSOrderedDescending depending on which date is later:

 switch([changeDate compare:now]) {
         case NSOrderedDescending:
                NSLog(@"changeDate is later than now");
                break;
         case NSOrderedAscending:
               NSLog(@"changeDate is earlier than now"); // This is where you would change the label!
               break;
         case NSOrderedSame:
               NSLog(@"changeDate is the same as now");
               break;
    }

Sorry for the long explanation - date calculations are unfortunately complicated in Obj-C. Hope this helps!