This question already has answers here:
NSDate: Get precise time independent of device clock? [duplicate]
(4 answers)
Closed 9 years ago.
Currently i am developing one gaming iOS application which i will give to some of my customer for demo.
But while distribution of my app i want to set an expiry mechanism in my app, so that it will get expire after "N" number of days.
It means that (e.g. after 30 days) my app won't work.i can able to this by using system date & time, it means whenever my program starts i check today date and expire date.
The problem is if the user changes system time, my comparison won't be correct.
Also if user delete & reinstall the app,it wont work.
Any help or suggestion?
Look at Ad Hoc Distribution
Ad-hoc development builds last for 3 months, however if you want to add a time limit then you could:
Add a key-value in NSUserDefaults which stores the start date of the app (time taken from a webservice such as http://www.earthtools.org/webservices.htm#timezone) then every time the app enters the foreground check the time against it and if it is over the threshold then to cancel loading the app.
NSDate *now = //load current datetime from restkit
NSDate *startDate = [[NSUserDefaults standardUserDefaults] objectForKey:#"startDate"];
NSDate *futureDate = [NSDate dateWithTimeInterval:60 * 60 * 24 * 30 sinceDate:startDate];
if ([futureDate compare:now] == NSOrderedAscending) {
//stop the application loading by loading a NIB and displaying a message.
}
I would recommend using RestKit to request data from the web-service.
When the app expires, store something in the Keychain to indicate this fact. Then just check that at startup, rather than the date.
Alternatively, you can have it check a web service you control.
Related
In my app I want to get the accurate date and time , Basically, in my application there is going to be a time sensitive portion that users can not start until after a certain time.
But if I go and grab the date and time from the device, the user can easily change the date and time on their device, Settings > General > Time & Date change it here.
I also tried with GPS locations time stamp but no luck, [CLLocation timeStamp] is also give device time,
I have searched all said to use ios-ntp, but it is not when user not have internet connection,
I have refer following StackOverflow questions:
Accurate time on iPhone
Network Time Protocol for iPhone
Is there any way to get the tamper-proof date and time on iPhone?
Retrieving Current Time from Carrier in iPhone
Time-based syncing for iOS app
but not getting result I want,
Is there other way to get accurate/ actual time ?
NOTE : ios have to store the currentdate some where , because when i change current system date from settings , and again set to Settings > General > Time & Date > set automatically > ON it will set the current accurate date, so can we get that date ?? or some trick ?
Example :
Suppose that In device right now time is 2014-01-01 15:04:57 +0000 ( right now set automatically is ON in Settings > General > Time & Date > set automatically > ON ),
now
user set set automatically > OFF and change current dateto 2014-03-02 11:14:32 +0000
SO when in app i write NSLog(#"cdate: %#",[NSDate date]); it will print
cdate: 2014-03-02 11:14:32 +0000 but what i want is to print the current actual
date that is 2014-01-01 15:04:57 +0000
Do you realise you are asking the impossible? If you need to get the time and you don't have network connectivity, the only place to get the time from is the device. Either you trust the device time, or you get the time from NTP. There are no other choices.
How you handle this depends on exactly why you need to get the time. If, there is functionality in your app that absolutely must not be enabled before a certain date, I would get the time from an external server and if it proves to be after the said date, set a flag in your defaults to say you have verified the date and the functionality is allowed, so you don't need to network connectivity thereafter. If the networking connectivity is not there, you don't set the flag but maybe put a message up to say that you need to connect to the Internet to enable the new functionality.
If it's just some part of a game, use device time and let them cheat if they want.
I'm currently making a TODO app and I save the date that the user has to do a thing. Let's say that he saves the date 28-7-2016 to do something, I make another column tobenotified and I take the date minus it by 1 and save it, so the user should be notified the previous day that tomorrow has a thing to do.
But what if the user has closed the app(killed it). What is the proper way to send a notification from the Realm database when the date tobenotified is equal with NSDate() / the current date?
It's not as simple like that. Realm queries can neither match against a live-updating current date nor send notifications from the background.
You want to look into UILocalNotification and set it up with the tobenotified date as fireDate and schedule it locally. Note that you will require your users consent and have asked them initially by registering for local notification types so that you're permitted by the OS to schedule and present notifications. Also if the user can modify or delete a reminder, then you need to find a way to identify the notification via the the provided identifier and remove or re-schedule it accordingly.
In a few weeks I'll be releasing my iOS app to a group of beta testers. I'm allowing them to test from a Friday evening until the following Sunday night. I want to disallow any usage after that Sunday. I don't want to use NSDate because testers could change the date on their device and keep playing after the session ended. Any ideas?
The date option is probably good enough as most people won't bother changing the date on their device, it would mess up too many other apps. The only case to worry about there would be someone with a device dedicated to your game.
Another option though: add a network request to your server with some code that says if it's allowed to play or not, then you can just change the flag on your server.
If you don't want to set up a server or worry about network connectivity, you can do two things that make it stronger than using a single NSDate:
Record the NSDate whenever someone opens the app (and when they leave)
The next time they use the app, make sure the current time is higher than the previous open/close time. And make sure it is less than your future date.
This will give a shrinking time window that will be harder and harder to circumvent.
There are dozens of ways to prevent this, some more complicated that others. But the first two that come to my mind are:
Option 1: You can check the date on a server instead of the system time.
Option 2: If you want to avoid the network hassle... If the user opens the app after sunday, write a boolean in userDefaults (e.g. expired). When starting the app check both the date and the expired flag. Even if the user changes the date, the expired flag would be set.
If you do not wish network and server connectivity, use the keychain to store the last open date. The keychain is more secure and harder for people to change than the user defaults, which are a mere plist file in the app's library.
Here is the secure option. You make it know that the BETA version of your app requires internet access. So when application starts, it will send a request to the beta server asking if it's alright to play. By default, your app won't play unless it gets a valid response.
The server create a valid response, the server will send at least two pieces of information. The first piece is a flag indicating that the beta period is valid. And the second is the current date/time. The server will sign the response using it's private key.
The application when it receive the response will verify its a valid by using the server public key. The server public key should be in the application as a resource. After verifying the message is valid and authentic, it compare the date/time that was sent to the device's date/time. If the time differences is less than 10 seconds for example, the application know its a current message. Not a message that has been saved and replay using some sort of HTTP proxy.
First, check out this link for a good way to check your time against an NTP server:
https://github.com/jbenet/ios-ntp
Then, you can get the date by calling [NSDate networkDate];
Now, you should be able to do your restriction in your appDelegate. I have done something similar for restricting running an iPhone app on an iPad:
if ([[NSDate networkDate] compare:startDate] == NSOrderedAscending) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Beta Not Started" message:#"Beta starts [[STARTDATE]]." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
return NO;
} else if ([[NSDate networkDate] compare:endDate] == NSOrderedDescending) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Beta Ended" message:#"Beta ended [[ENDDATE]]." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
return NO;
}
Then, in your UIAlertViewDelegate:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
exit(0);
}
Hope this helps!
so I'm using OCPrayerTimes to get a set of strings in an
I use this code to get the array,
NSMutableArray *prayerTimes = [prayerTime prayerTimesDate:[NSDate date]
latitude:3.1667
longitude:101.7000
andTimezone:[prayerTime getTimeZone]];
I then set notifications for each date in that array. Now my problem is that everyday those dates change so the user would have to re-open the app at midnight to get the new dates so the notifications would work.
Would I have to somehow run the viewdidload method at midnight everyday?
Thanks.
You can't automatically run your app every day, but you can schedule up to 64 local notifications, so you could calculate the prayer times for the next 12 days, and schedule notifications for all of them. This way the app wouldn't have to be opened every day.
I'm seeing really weird behaviour in my iOS app using the ABAddressBook library. Wondering if anyone can give me some insight into whats happening in the background or if I have a logic error I just can't see.
Long story short I'm making a VOIP app that relies heavily on importing the user's contacts. I keep an online backup of these that are also used in conjunction with push notifications.
As they are modified on the phone I need to send an update request to the server to keep them accurate. The problem is many user devices are frequently spamming the server with very large blocks of contacts, at random intervals. One day it will be 50+ contacts, 5 mins later another 10, then it will be a month before a single one is updated. I have asked a few users that are friends and they can't recall modifying half of their address book over night.
My code is very simple, I store an NSDate every time I am required to send an update to the server, e.g. addition, modification or deletion. I know there is a callback that triggers when the address book has been updated, but this requires keeping a reference to the address book in memory at all times. I've done some testing and if the app crashes or the user kills the app, I loose any updates. Given its a background running VOIP app I feel it is possible people will kill it on an occasion to save battery or whatever. So for that reason I loop through all the contacts checking the kABPersonModificationDateProperty property against the last NSDate I have recorded. If the modified is newer I begin my update, like so.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSDate *lastChecked = [dateFormatter dateFromString:[PListData readStringFromFile:#"lastContactsArchive"]];
CFDateRef modifyDate = ABRecordCopyValue(ref, kABPersonModificationDateProperty);
...
...
else if ([(__bridge NSDate*)modifyDate compare:lastChecked]==NSOrderedDescending) // if modified after last check, create new contact and update
{
...
}
Is there something that I'm missing, is the modification date only updated when the name / phone numbers / email etc are changed ? Are they modified when iCloud syncs for example ? is a counter updated if they call the person on the phone ? etc.
I've tried debugging on 3 phones and all behave as I would expect. I'm really drawing a blank here and the server isn't happy with me so any help would be appreciated.
Contacts may also update in background when iphone syncs contacts with iCloud / CardDav / Gmail / Exchange account.
Note that it also may happen while your app is running, so you should subscribe for address book updates.