iPhone App Cookie Delay - iphone

My iPhone app has a UIWebView that loads a page containing javascript that sets a cookie. It seems that if i set a cookie and exit the app within 10-15 seconds then the cookie is never saved, however if i set the cookie, wait 10-15 seconds THEN exit the app, the cookie is saved.
Anyone have any info about why their is a delay and how to go about having the cookies saved immediately.

The only workaround i was able to come up with is to save the cookies to the user defaults right before the app terminates. When the app is opened, go through the user defaults, pull out the cookies, and rewrite them to the cookie storage. It works but if your app is forcefully terminated then it doesnt really.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
[cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
// Load the saved cookies
NSDate *currentDate = [NSDate date];
NSTimeInterval expirationAmount = 5 * 365 * 24 * 60 * 60;
NSDate *expirationDate = [currentDate dateByAddingTimeInterval:expirationAmount];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
for (id theKey in [defaults dictionaryRepresentation]) {
if ([theKey hasPrefix:#"cookie:"]) {
[self setCookie:[theKey substringFromIndex:7] value:[defaults objectForKey:theKey] expiration:[expirationDate description] domain:urlDomain];
}
}
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Save the cookies to the user defaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray* theCookies = [cookieStorage cookies];
for(NSHTTPCookie *myStr in theCookies) {
[defaults setValue:[myStr value] forKey:[NSString stringWithFormat:#"cookie:%#", [myStr name]]];
}
[[NSUserDefaults standardUserDefaults] synchronize];
}

Having this same problem. The delay is actually 30 seconds exactly from my tests. I lost a couple days trying to debug this. There might be a way to work around this by manually re-saving the cookies before the 30 seconds has elapsed, but I haven't tried this yet.

Related

Facebook Connect Logging In Issues

I am using Facebook Connect with my app. Everything is set up, all the code WAS working. Around yesterday, I could login with my app, then post stuff and other functions. I don't recall making any real changes. Now, as usual, whenever I press login and it goes to a Safari page where I have to confirm that I want to use this app and it says who I am logging in as. If I press ok it goes back to the app. During this whole process, in the app, Facebook never logs in. REMEMBER: JUST YESTERDAY THIS WORKS, I DONT RECALL MAKING ANY CHANGES! Here is how the connection starts:
-(IBAction)connectToFacebook {
[loginButton setImage:[UIImage imageNamed:#"LoginWithFacebookPressed#2x.png"] forState:UIControlStateNormal];
facebook = [[Facebook alloc] initWithAppId:#"387500177929927" andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"] && [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![facebook isSessionValid]) {
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"user_likes",
#"read_stream",
nil];
[facebook authorize:permissions];
[permissions release];
}
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(makeVisibleButtons) userInfo:nil repeats:NO];
}
So I press a button to call this IBAction. The NSTimer is not related, its just for the appearance of some buttons. Now, these two methods never get called (when I log it):
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [self.facebook handleOpenURL:url];
NSLog(#"handleOpenURL");
}
- (void)fbDidLogin {
NSLog(#"log in");
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
I don't understand why. Especially if it was working before. Do you have any ideas?
Facebook API having SSO(Single Sign On). So It will ask the user to login for only one time. This login is valid till that login tokens are expired. Check your code itself that you are storing your token and expiration time in NSUserDefaults. This will help the API to login again. If you want to make sure your app login functionality is working or not, then delete your app from simulator and again run it. It will ask your login credentials for the first time only. Hope you undertand.

How to get the count of number of times the app launch iPhone

Im developing a reminder app.
So my client want to set a rate this application popup message, that'll come up on the 10th time user open the app.is this possible.
How can i implement this?
Can anyone help me please.Thanks in advance
You could use NSUserDefaults for this:
NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
NSInteger appLaunchAmounts = [userDefaults integerForKey:#"LaunchAmounts"];
if (appLaunchAmounts == 10)
{
[self showMessage];
}
[userDefaults setInteger:appLaunchAmounts+1 forKey:#"LaunchAmounts"];
You can store that into the NSUserDefaults. Just update it in applicationDidFinishLaunching:.
You can save an integer in NSUserDefaults
- (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName
Retrieve it and increment it every time the appDidFinishLaunching (or appWillEnterForeground) delegate methods is called. Probably best to use appWillEnterForeground as sometimes apps can lie in the background unterminated for days.
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
NSInteger count = [defaults integerForKey:#"LaunchCount"];
count++;
/* Do checks and review prompt */
[defaults setInteger:count forKey:#"LaunchCount"];
[defaults synchronize];
This will store a value in NSUserDefaults called 'AppLaunchCount'.
- (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([[NSUserDefaults standardUserDefaults] integerForKey:#"AppLaunchCount"])
{
[[NSUserDefaults standardUserDefaults] setInteger:([[NSUserDefaults standardUserDefaults] integerForKey:#"AppLaunchCount"] + 1) forKey:#"AppLaunchCount"];
}
else
{
[[NSUserDefaults standardUserDefaults] setInteger:1 forKey:#"AppLaunchCount"];
}
}

iphone count down event

I just want to know how to make a count down for a even or a day? i did some search on google but I got got some few information to make this application ,they told me should be using NSDate and NSCalendar.however I want to stored all information and user can load when reopen the application ,should I using sqlite or core data? thanks
Ben,
1. Store your time (NSDate) at the appropriate time.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[NSDate date] forKey:#"CheckedInTime"];
[defaults synchronize];
When your app become active again:
(i.e.) -
(void)applicationDidBecomeActive:(UIApplication *)application
Start a timer to check to see if the time has expired:
self.checkinTimer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:#selector(checkinTimerCheck:) userInfo:nil repeats:YES];
- (void) checkinTimerCheck:(NSTimer *) timer {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDate * checkinTime = [defaults objectForKey:#"CheckedInTime"];
float hours = HOWEVER_MANY_HOURS_NEED_TO_PASS_TO_EXPIRE_IN_SECONDS;
if (hours < 0) {
[self alertUserThatTimeHasExpired];
}
}
Invalidate the timer check whenever your app gets
- (void)applicationWillResignActive:(UIApplication *)application
Regards,
Ken

First Time Opened Event

In my iPad app, I have a UIAlertView which pops up upon start up, however I only want this to popup the very first time the user starts the application. It's a setup prompt, saying, it's your first time, would you like to setup?
How can I do this? I have heard it's best to write out to a plist file and save a bool value, but how would I tackle this?
Modify the following code to suit your needs; you may put it in your root view controller viedDidLoad method. The code keeps track of the first run of the application, of the number of launches and whether or not the your setup prompt has been shown to the user.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults objectForKey:#"firstRun"]) {
// this is the first run
// store this information
[defaults setObject:[NSDate date] forKey:#"firstRun"];
[defaults setInteger:1 forKey:#"launches"];
[defaults setBool:NO forKey:#"setupPromptHasBeenShown"];
[defaults synchronize];
// now prompt the user to setup the app
// once the the prompt has been shown,
// if the user actually decides to setup the app,
// store this information again, so you will not prompt him/her again
[defaults setBool:YES forKey:#"setupPromptHasBeenShown"];
[defaults synchronize];
}
else{
// this is not the first run
NSInteger daysSinceInstall = [[NSDate date] timeIntervalSinceDate:[defaults objectForKey:#"firstRun"]] / 86400;
NSInteger launches = [defaults integerForKey:#"launches"];
[defaults setInteger:launches+1 forKey:#"launches"];
[defaults synchronize];
}
You could use NSUserDefaults to achieve this with just a few lines of code.
http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html

Best way to check if an iPhone app is running for the first time

I want to check if my iPhone app is running for the first time. I can create a file in the documents folder and check that file to see if this is the first time the app is running, but I wanted to know if there is a better way to do this.
I like to use NSUserDefaults to store an indication of the the first run.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults objectForKey:#"firstRun"])
[defaults setObject:[NSDate date] forKey:#"firstRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
You can then test for it later...
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if([defaults objectForKey:#"firstRun"])
{
// do something or not...
}
Ok what confuses the hell out of me about User Defaults.
WHERE are they stored?
you dont care it varies per iOS/Mac.
you just getVALUE by KEY
setVALUE by KEY + synchronize
iOS/Mac does the rest.
This is the common use case:
Checking for the existence of a value e.g firstRun.
The first time it will NOT EXIST so usually followed by setting the value.
2nd Run
- on next loop it does exist and other use case/else stmt is triggered
---- .h
#interface MyAppDelegate : UIResponder <UIApplicationDelegate>
//flag to denote if this is first time the app is run
#property(nonatomic) BOOL firstRun;
------ .m
#implementation MyAppDelegate
#synthesize firstRun = _firstRun;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//==============
//Check to see if this is first time app is run by checking flag we set in the defaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults objectForKey:#"firstRun"]){
//flag doesnt exist then this IS the first run
self.firstRun = TRUE;
//store the flag so it exists the next time the app starts
[defaults setObject:[NSDate date] forKey:#"firstRun"];
}else{
//flag does exist so this ISNT the first run
self.firstRun = FALSE;
}
//call synchronize to save default - where its saved is managed by iOS - varies by device and iOS/Mac
[[NSUserDefaults standardUserDefaults] synchronize];
//TO TEST: delete the app on the device/simulator
//run it - should be the first run
//close it - make sure you kill it and its not just in the background else didFinishLaunchingWithOptions wont be called
//just applicationDidBecomeActive
//2nd run it should self.firstRun = FALSE;
//=============
//NOTE IMPORTANT IF YOURE ROOTVIEWCONTROLLER checks appDelegate.firstRun then make sure you do the check above BEFORE setting self.window.rootViewController here
self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];
return YES;
}
---- USING THE FLAG
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
if (appDelegate.firstRun){
NSLog(#"IS FIRST RUN - Do something: e.g. set up password");
}else {
NSLog(#"FPMyMusicScreenViewController: IS NOT FIRST RUN - Prompt for password");
}
The examples above confused me a bit as they show how to check for it the first time but then mention how to 'check for it later' in the same comment.
The problem is when we find it doesnt exist we immediately create it and synchronize.
So checking for it late actually mean when you RESTART THE APP not in same run as first run.
In your app delegate register a default value:
NSDictionary *defaultsDict =
[[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithBool:YES], #"FirstLaunch", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultsDict];
[defaultsDict release];
Then where you want to check it:
NSUserDefaults *sharedDefaults = [NSUserDefaults standardUserDefaults];
if ([sharedDefaults boolForKey:#"FirstLaunch"]) {
//Do the stuff you want to do on first launch
[sharedDefaults setBool:NO forKey:#"FirstLaunch"];
[sharedDefaults synchronize];
}
You can implement it with the static method below. I think it's better since you can call this method as many times as you like, unlike the other solutions. enjoy: (Keep in mind that it's not thread-safe)
+ (BOOL)isFirstTime{
static BOOL flag=NO;
static BOOL result;
if(!flag){
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"hasLaunchedOnce"])
{
result=NO;
} else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"hasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
result=YES;
}
flag=YES;
}
return result;
}
You can use a custom category method isFirstLaunch with UIViewController+FirstLaunch.
- (BOOL)isFirstLaunch
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"kFirstLaunch"]) {
return YES;
}
else {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"kFirstLaunch"];
[[NSUserDefaults standardUserDefaults] synchronize];
return NO;
}
}
And when you need to use it in controller
BOOL launched = [self isFirstLaunch];
if (launched) {
//if launched
}
else {
//if not launched
}
Use NSUserDefaults. If the sharedDefault has a key for your app, its run before. Of course, you'll have to have the app create at least one default entry the first time the app runs.
Swift:
var isFirstLaunch: Bool {
get {
if (NSUserDefaults.standardUserDefaults().objectForKey("firstLaunchDate") == nil) {
NSUserDefaults.standardUserDefaults().setObject(NSDate(), forKey: "firstLaunchDate")
NSUserDefaults.standardUserDefaults().synchronize()
return true
}
return false
}
}
Another tip:
When using NSUserDefaults, these settings will be wiped if the app is ever deleted. If for some reason you require these settings to still hang around, you can store them in the Keychain.