I am using the new Basecamp API for my iOS basecamp client app. I want the user to be able to logout and switch accounts. But I can't as the account credentials stored in the browser cache are used every time I request authorization.
I figured out I would need to flush browser cache to do this. How do I clear the browser cache?
[[NSURLCache sharedURLCache] removeAllCachedResponses];
After that, you can deleting any associated cookies with in the UIWebView:
for(NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
if([[cookie domain] isEqualToString:someNSStringUrlDomain]) {
[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
}
}
From googling a bit, the answer to my question is "yes". But how do I test that?
I tried to inpsect the HTTP request headers (i.e. [request allHTTPHeaderFields]) in webView:shouldStartLoadWithRequest:navigationType:, but none of the request has the "Cookie" entry, even though cookies are successfully stored in [NSHTTPCookieStorage sharedHTTPCookieStorage].
try this to loop through all the cookies in the UIWebView to verify they are there
NSHTTPCookie *aCookie;
for (aCookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
NSLog(#"%#", aCookie);
}
I'm trying to track an event in my app using Yahoo Web Analytics. The code I am using looks like
ASIHTTPRequest *yahooTrack = [ASIHTTPRequest requestWithURL:
[NSURL URLWithString:#"http://s.analytics.yahoo.com/p.pl?a=xxxxxxxxxxxxx&js=no&b=yyyyyyyyyyyy&cf6=zzzzzzzzzzz"]];
yahooTrack.didFinishSelector = #selector(statisticsFinished:);
yahooTrack.delegate = self;
[yahooTrack startAsynchronous];
Then the statisticsFinished looks like:
NSLog(#"Cookies: %#", request.requestCookies);
NSLog(#"Redircount: %d", [request redirectCount]);
NSLog(#"Responsecode %d %#\nMsg: %#", request.responseStatusCode,
request.responseStatusMessage, [request responseString]);
And all the information I get back looks correct. Cookies are set, redirectcount is 1 the first time (as it redirects to s.analytics.yahoo.com/itr.pl?.... a normal browser does). Then the redirectcount is 0 for subsequent request until the app is restarted and session cleared. The responseString returns GIF89a.
Even if the data looks correct, Yahoo still won't track. As soon as I call the tracking url directly in my browser it works as expected.
I realize Flurry is a better option, but I'm forced to use Yahoo in this case. Also, using a UIWebView probably would work, but I'm against putting in a webview just for tracking purposes.
Is there any difference in how ASIHTTPRequest and Safari would handle a call to a simple URL as this? Or do you see anything else that could explain why the tracking isn't working?
I finally found the problem. ASIHTTPRequest creates a user-agent based on your applications name, and requests from this user agent is ignored by Yahoo somehow (bug?). As stated in the documentation, you can override the user-agent as follows:
[request addRequestHeader:#"User-Agent" value:#"My-User-Agent-1.0"];
I used the user-agent string of Safari on iPhone, and it worked immediately! BTW; the same problem applies for Android, and the same fix works.
I would like to gather usage statistics for my iPhone app using Google Analytics so I'm trying to configure it using the following tutorial: http://code.google.com/intl/fr-FR/apis/analytics/docs/tracking/mobileAppsTracking.html
I think I did everything they indicate in the documentation, and I get no error on the iPhone side, but I don't see any visits in Google Analytics.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
[self initGoogleAnalytics];
//...
}
-(void)initGoogleAnalytics{
[[GANTracker sharedTracker] startTrackerWithAccountID:[[NSBundle mainBundle] objectForInfoDictionaryKey:#"GoogleAnalyticsCode"]
dispatchPeriod:-1
delegate:nil
NSError *error;
if(![[GANTracker sharedTracker] trackPageview:#"/home" withError:&error]){
NSLog(#"%#", [error localizedDescription], nil);
}
[[GANTracker sharedTracker] dispatch];
}
Any idea why this is not working?
this is the same answer that I put at: Problem dispatching with google mobile analytics for iphone
The Google Analytics stop sending data when you try to send a non formatted "URL", if it is not initiated with the "/" or contain some specific chars, it will start only returning errors.
The best thing to do is, verify that you are placing the "/" on the beginning of you URL and before sending, format your URL to avoid any problem, by doing:
NSString* pageURLString = [pageURL stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
Encoding it with NSASCIIStringEncoding, will format the URL properly. The same can be used when tracking an event.
Can an iPhone application read cookies previously stored by Safari Mobile?
To actually answer your question:
No.
Mobile Safari's cookies are not accessible from SDK apps. And each SDK app is given its own WebKit cache and cookie stores, so while cookies will persist within the same app, they aren't accessible betweeen apps.
As of iOS 9 this is possible!
Use a sfSafariViewController.
You will need to setup:
A custom URL scheme in your app to receive cookie data.
The website you are getting cookies from will need to implement an API specific your app's custom URL scheme, to redirect back to your app.
You can clone this repo which has a fully working demo of this.
Hope this helps,
Liam
There is actually an interesting way if you have access to a server url.
In your app launch the server url with mobile safari.
The target server url reads the cookie and redirects back to an app specific url (myapp://cookie=123)
The app is then switched back and you can read that value from the url handler
It's a little hacky as the app would switch mobile safari and then immediately switch back to the app. But, it is possible.
Note that on iOS 8, you're probably better using Safari Password Sharing to solve some of the use cases that give rise to this problem.
This is not directly possible, but with the cooperation of the web site it is possible.
To clarify, the user case is that an Objective C application wants to read the value of a cookie that has been set by a website in mobile safari. (ie. in particular, a UIWebView was not involved in setting the cookie)
Your app should do this:
Launch mobile safari, using [[UIApplication sharedApplication] openURL:url];
The URL should be a special one, eg. http://yourwebsite.com/give-ios-app-the-cookie
On your website, when that url is launched, issue a redirect to your-app-url-scheme:cookievalue= (eg. angrybirds:cookievalue=hh4523523sapdfa )
when your app delegate receives - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation process the url to get the cookie value
Note that you should not do this automatically when the application starts - the user will see the transfer to Mobile Safari and back, which is not a good user experience and Apple will reject your app (Apple also consider this to be "uploading user's personal data to server without their prior consent"). It would be better to do it in response to the user, paying attention to the user experience - eg. wait for the user to hit a "login" button, then do it, and if the user is not logged into your website, http://yourwebsite.com/give-ios-app-the-cookie should show the user the login screen within safari. If the user is logged in you could briefly show a "Automatically logging you in..." screen for a second or two in Safari before redirecting the user back.
There's no way to get this to work with hotmail/gmail/etc of course - it needs to be your own website.
Credit goes to Unique Identifier for both mobile safari and in app in iOS for suggesting this kind of approach.
Because of sandboxing on the iPhone you don't have access to Safari's cookies. You can only access cookies created within your application - by an UIWebView for example.
Although you have asked the same question twice before, here's one approach not yet mentioned...
This may be a little convoluted, but you can do Greasemonkey-esque things with a UIWebView. Something like this:
Load your target page
craft some javascript which will read the document.cookie and return the data you need
In the webViewDidFinishLoad delegate, inject this javascript into the UIWebView with the stringByEvaluatingJavaScriptFromString message
I've used this technique to enhance 3rd party pages in an iPhone app, but I'm not sure if it will read cookies from the same place as Safari mobile.
Worth a shot though?
Here's my utils get/set cookie methods.
+(void)setCookie:(NSString *)key withValue:(NSString *)value {
NSArray *keys = [NSArray arrayWithObjects:
NSHTTPCookieDomain,
NSHTTPCookieExpires,
NSHTTPCookieName,
NSHTTPCookiePath,
NSHTTPCookieValue, nil];
NSArray *objects = [NSArray arrayWithObjects:
#"YOURDOMAIN",
[NSDate distantFuture],
key,
#"/",
value, nil];
NSDictionary *dict = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:dict];
NSHTTPCookieStorage *sharedHTTPCookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
[sharedHTTPCookieStorage setCookie:cookie];
}
+(NSString *)getCookie:(NSString *)key {
NSHTTPCookieStorage *sharedHTTPCookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSArray *cookies = [sharedHTTPCookieStorage cookiesForURL:[NSURL URLWithString:#"YOURDOMAIN"]];
NSEnumerator *enumerator = [cookies objectEnumerator];
NSHTTPCookie *cookie;
while (cookie = [enumerator nextObject])
{
if ([[cookie name] isEqualToString:key])
{
return [cookie value];
}
}
return nil;
}
You might want to check
if ([[NSHTTPCookieStorage sharedHTTPCookieStorage] cookieAcceptPolicy] != NSHTTPCookieAcceptPolicyAlways) {
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
}
But apparently NSHTTPCookieStorage does not even hold cookies from the last request in the current application on iOS (rdar://8190706)