After looking at a bunch of SO posts about detecting if this is a fresh install or not, I'm assuming what I want to do is impossible, but I'm going to ask just in case there's a trick I'm unsure of.
I am building an SDK to be integrated into apps, and I want to be able to tell when the SDK gets initialized for the very first time if it's from a brand new install, or from an app update which included our SDK.
I could have the integrator to call something like [MySDK initializeIsNewInstall:YES/NO] and force them to figure out which it is (using NSDefaults or whatever), but I'd rather be able to figure it out automatically somehow.
If anyone has any ideas, that would be great.
I would like to suggest pretty good trick by using [NSUserDefaults standardUserDefaults]
do it like this,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if([[NSUserDefaults standardUserDefaults] boolForKey:#"isApplicationUpdated"]){
// application was updated//
// make another userDefaults to store version number and confirm if it is updated here.
}
else{
[[NSUserDefaults standardUserDefaults] setBookForKey:#"isApplicationUpdated"]
// as for the first time application would not find this key and you can use it after you have updated the app do stuff here
}
Afaik the only way to detect whether your app was updated or freshly installed in your case is to check your persistence for something that should be there from a previous version. For future checks you can add your own flag to your persistence.
Related
I wondered if there are a way to be notified when a new application is installed in my device and trigger some treatment in my applications. Like PACKAGE_ADDED BroadcastReceiver in android
Thank's
Apple does not provide such information. Instead, you could add something like:
if([[NSUserDefaults standardUserDefaults] objectForKey:#"firstRun"] == nil)
{
//This is a first run
[[NSUserDefaults standardUserDefaults] setObject:#"NotFirstRun" forKey:#"firstRun"];
}
to applicationDidFinishLaunchingWithOptions:
update
If you instead want to detect the installation of another app the approach is different:
You can't detect when an app is installed, but for SOME apps you can detect if they are installed.
Doing your own app launch (or perhaps using a backgroundfetch process) you can see if an app is installed IF the app responds to a URL Scheme AND you know that scheme.
Take a look at
([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:customURL]])
If this methode returns YES for a given URL Scheme you know that app is installed. Here is a partial list of URL Schemes for some common apps or search http://handleopenurl.com/. You can of course also make your own URL Scheme if you want to detect your own app.
No. Apple doesn't give you this data.
What you can do, however, is maintain an user defaults data and manipulate in applicationDidFinishLaunchingWithOptions: delegate.
I've used a library called 'GBVersionTracking' for detect when is his first launch.
Importing this library you can send messages to the class 'GBVersionTracking' like:
[GBVersionTracking isFirstLaunchEver];
[GBVersionTracking isFirstLaunchForVersion];
[GBVersionTracking isFirstLaunchForBuild];
https://github.com/lmirosevic/GBVersionTracking
I've got the following problem:
I created a Today Extension, which contains an UISwitch. The IBAction of this switch in Today Extension should store the on-state using the NSUserDefaults with the initWithSuite like this:
- (IBAction)switchStateChanged:(id)sender {
BOOL isOn = self.preferenceSwitch.isOn;
NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.x.TodayExtensionSharingDefaults"];
[sharedDefaults setBool: isOn forKey: #"SwitchState"];
[sharedDefaults synchronize];
}
Now in my Containing App, I know that i can access the switch state using this:
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.x.TodayExtensionSharingDefaults"];
BOOL value = [defaults boolForKey:#"SwitchState"];
I'm looking for a solution that gives me a callback in my main containing app, when the value of the switch is changed.
In this solution, i have to set a NSTimer that refresh the user-defaults every 200ms for example.
Is there any solution by adding an Observer to the sharedDefaults?
I think this will work for your use case:
When you leave your app and open up Notification Center,
- (void)applicationWillResignActive:(UIApplication *)application
is called in your AppDelegate. When you come back from the widget,
- (void)applicationDidBecomeActive:(UIApplication *)application
is called in your AppDelegate. So just check your value then and fire off a internal notification to your controller. You shouldn't have any need for a timer.
Observing the change in your app is not a good solution, even if you could make it work, because you can't be certain that your app is even running when the switch value changes. It's also not how today extensions are intended to work.
If your app needs to know the state of this switch the next time it runs (recognizing that it might not be running when the switch is tapped), you're already doing the right thing.
If you need to immediately notify your app that the switch value has changed (again, recognizing that your app might not be running and that doing this might launch your app), you should create a custom URL scheme for your app and then open the URL from the extension. This would be something like:
In the app, declare a custom URL scheme in the "URL types" section of the app's "Info" settings.
Also in the app, add code to the app delegate to receive requests to open URLs.
In the app extension, use [NSExtensionContext openURL:completionHandler:] to open the URL. This will launch your app and pass the provided URL.
If the URL scheme is something like mygreatapp, the app extension would open a URL like mygreatapp:. You can add detail to the URL if needed, or the app can just use user defaults to look up the saved value.
I use [NSUserDefaults standardDefaults] to store a boolean to see if it is the first time that application is being launched ... If so, the app should show a registration window.
It was working fine till last week, but now, sometimes when I switch to other apps and come back after a little while, I see that registration page loads while it shouldn't.
I used NSLog to see what is stored in [NSUserDefaults standardDefaults] and I see that the values I stored has been set to nil (null) while I haven't done that anywhere in my code.
Does anyone know why the values do reset ?
P.S: Actually the values are not permanently lost , because if I don't do anything in registration page and quit the app instead, It will launch normally the next time I enter the app !!!
A long time ago I encountered this issue, turns out a third party library that I was using uses the same key when storing values to NSUserDefaults. Try searching your project for this key, maybe something else is resetting it.
Here are the ways I know about to lose values in NSUserDefaults, in order of likelihood:
The key was never saved in the first place
Your app deletes it later on
The app is deleted and reinstalled
Another app overwrites or removes the key
The phone or simulator is reset
During the night, the phone is replaced by an identical-looking, different phone
It sounds like, from the discussion here, that you've ruled out 1,2,4, and probably 3 & 5. The only next debug step I can think of is to store the test phone in a locked drawer at all times.
But I'd leave my money on an intermittent problem causing #1. For that, we'd need posted code to investigate.
EDIT -
A high % of NSUserDefaults problems posted here are about storing BOOLs and other scalar types. It looks like the OP knows about wrapping in NSNumbers, but BOOLS in particular are fraught because it's easy to confuse false-y values like NO no and nil, and NSNull instance.
Let's throw that on the list for this question at #2.5. There again, would need code to confirm.
If this is happening while testing, it's normal. The fact that the program is even making this decision (should I show the registration page?) suggests that the app has been forcibly quit and is starting from scratch. When testing, this can result in clearing out the app sandbox as the app is reloaded from Xcode. In the real life of a real user, however, that won't happen (unless the user deletes the app from the device).
Make sure you are calling [[NSUserDefaults standardUserDefaults] synchronize] just after setting preferences and you are not overwriting you preferences.
I'm developing an iOS app that makes use of an sqlite database directly, without using Core Data. I've the tables for the database defined in a file that I read to copy the database to Documents the first time I need it.
I'm worrying about publishing app updates in the App Store once the app submitted when such updates have changes in database tables. I asked how to handle this database updates in another post, and I was told that the way to proceed is to upload an app version that removes the former database and copies the new one into Documents with another name. I do that, but I'm still not sure of what the appropriate way to manage this issue should be. I mean, I'm currently doing this way:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Database
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults boolForKey:#"firstLaunch"] == 0) {
dispatch_queue_t queue = dispatch_queue_create(DatabaseQueue, NULL);
dispatch_async(queue,^{
[self replaceDatabase:#"former_database.sqlite" withDatabase:#"new_database.sqlite"];
[self doDataInsertions];
[defaults setBool:1 forKey:#"firstLaunch"];
});
dispatch_release(queue);
}
}
But I donĀ“t know if this will work when a user will download and install an update. When installing an update, are the values in NSUserDefaults kept? I suppose this scenario, managing database updates when updating app version in App Store, is a common one, so could somebody clarify me what the correct way to manage this is? I don't completely understand how the app updates submission thing work, this will be my first submission.
Thanks so much
I'm making an app as a part of my project and I've been asked to add a disclaimer.
At first I made a separate view with a textview that holds the disclaimer, when the user presses the Disclaimer button they will see this.
But I've been asked to change this so that the disclaimer is shown if the app is being used for the first time. If the user accepts it, they won't see it again and if they don't they'll see it every time they open the app.
I don't know how to go about this. I tried changing it so that the first thing the app shows when launched is the disclaimer, but that got annoying because every time I launch the app it goes to the disclaimer.
Anyone have any suggestions or examples ?
You can use NSUserDefaults to achieve this. Once the user has accepted the disclaimer, write a BOOL called disclaimerAccepted (or similar) to your defaults. Use the following code in the AppDelegate method application:didFinishLaunchingWithOptions: to check this:
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"disclaimerAccepted"]) {
// Show the disclaimer.
}
And use this code when the user accepts the disclaimer:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:YES forKey:#"disclaimerAccepted"];
[defaults synchronize];
Hope this is helpful.
Why not use NSUserDefaults to store info whether user dismissed or accepted the disclaimer & show the dialog accordingly. NSUserDefaults are persisted even if app is closed.
edit:
Here is an example Using User Defaults
The best solution I found is given here: iPhone: How do I detect when an app is launched for the first time?
If you like it add your upvote there - I only just used it a couple of days ago and I think it is really good!