http authenitcation in Xcode - iphone

I am trying to make Twitter work in my app and everything works fine except the code does not seem to recognize an error from Twitter. If the username/password are not valid, I get an error message through this function:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSString* strData = [[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSASCIIStringEncoding] autorelease];
NSLog(#"Received data: %#", strData ) ;
return ;
}
It prints: Received data:
Could not authenticate you.
.
However, the app continues to the post a tweet view I have and ignores the error. Obviously, I do not have something setup right to detect such an error from twitter so my question is how do I get Xcode to recognize an error like this? This uses basic http auth btw and don't mention anything about OAuth...just trying to get this to work for now.
-(void) onLogin:(id)sender
{
[loading1 startAnimating];
NSString *postURL = #"http://twitter.com/account/verify_credentials.xml";
NSMutableURLRequest *request = [ [ NSMutableURLRequest alloc ] initWithURL: [ NSURL URLWithString:postURL ] ];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:request delegate:self];
if (!theConnection)
{
UIAlertView* aler = [[UIAlertView alloc] initWithTitle:#"Network Error" message:#"Failed to Connect to twitter" delegate:nil cancelButtonTitle:#"Close" otherButtonTitles:nil];
[aler show];
[aler release];
}
else
{
receivedData = [[NSMutableData data] retain];
}
[request release];
}
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge previousFailureCount] == 0 && ![challenge proposedCredential])
{
NSURLCredential *newCredential;
newCredential=[NSURLCredential credentialWithUser:txtUsername.text
password:txtPassword.text
persistence:NSURLCredentialPersistenceNone];
[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
}
else
{
isAuthFailed = YES;
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}

Your delegate needs to implement...
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
Which should get call if the server you are trying to connect to requires authentication. Here's some example code from a program of mine...
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge previousFailureCount] == 0) {
NSURLCredential *newCredential;
newCredential=[NSURLCredential credentialWithUser:_username
password:_password
persistence:NSURLCredentialPersistenceNone];
[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
} else {
[[challenge sender] cancelAuthenticationChallenge:challenge];
NSLog(#"Bad Username Or Password");
}
}
}

The method - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data is called zero or more times depending on how much data is available.
In the case of a web request, it is likely that it'll be called more than once. What you need to do is create an NSMutableData object and store it as an instance variable. Then when this method is called you need to append the new data to your NSMutableData object, like so:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
//myMutableData should be an instance of NSMutableData and stored as an instance variable in your class. Don't forget to initialise it.
[myMutableData appendData:data];
}
If you don't do this, you could be missing parts of the response.
I don't know exactly how your performing the request or what kind of response you're getting back, but ideally, you will want a response formatted in XML or JSON, and you should use a parser to turn the response into something you can use.
That way, you would be able to extract error codes, messages, etc and act upon them accordingly.
Finally, if you're going to be using Twitter from your application, consider using a prebuilt library like MGTwitterEngine. It'll save you a lot of grief and hassle. Also, even though you said not to mention it, MGTwitterEngine supports OAuth now, as well, which would save you having to patch your code once the basic auth is turned off.

ok so I can now get an error response or a authentication response in xml. now, how do I say, use this response as a triggering factor for connectionDidFailWithError because if twitter send me back an error, I want to give an in-app error.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[receivedData appendData:data];
NSXMLParser* parser = [[NSXMLParser alloc] initWithData:data];
[parser setDelegate:self];
[parser parse];
return;
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSMutableString *)string
{
NSLog(#"response: %#", string);
}

Related

UIActivityIndicatorView freeze

i have this function which call a function to check CMS for info. but the UIActivityIndicatorView freeze till the check is completed. not sure why.
EDIT: one thing funny, i commented out the performselector. the UIActivityIndicatorView still freezed. until i tapped my back button then it started to spin....
i'm using storyboard, iOS 5
-(void)showLoading
{
[activity startAnimating];
//loading is a label to show "File Loading"
loading.alpha =1;
//is a label to show a 0.3 alpha of the label
blackOverlay.hidden =0;
[self performSelector:#selector(updateFromInternet:) withObject:#"a" afterDelay:2];
//[self updateFromInternet:#"a"];
}
-(void)updateFromInternet:(NSString *)urlStr
{
NSString *URLString = #"http://sites.google.com/site/iphonesdktutorials/xml/Books.xml";
NSURL *updateDataURL = [NSURL URLWithString:URLString];
NSMutableURLRequest *WPXMLFetchRequest = [NSMutableURLRequest requestWithURL:updateDataURL];
self.receivedData = [NSMutableData data];
self.updateConnection = [NSURLConnection connectionWithRequest:WPXMLFetchRequest delegate:self];
NSLog(#"Checking update at : %#", updateDataURL);
//[self.updateConnection cancel];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
////NSlog(#"Receiving data");
[self.receivedData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
////NSlog(#"Failed to receive data");
self.receivedData = nil;
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
////NSlog(#"Received response from data");
[self.receivedData setLength:0];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *data=[[NSString alloc]initWithData:self.receivedData encoding:NSUTF8StringEncoding];
NSLog(#"data %#",data);
NSError *parseError = nil;
//NSDictionary *xmlDict = [XMLReader dictionaryForXMLData:self.receivedData error:&parseError];
self.receivedDict = [XMLReader dictionaryForXMLData:self.receivedData error:&parseError];
[self showDataOnScrollView];
}
You should delay the "heavy" function a bit and let the Activity Indicator fire.
try adding a 2.0 and not 2 to your delay (I would use a much smaller value - say 0.3)
[self performSelector:#selector(updateFromInternet:) withObject:#"a" afterDelay:0.3];
if this does not solve's your problem you should look (or post) the code related to the extra stuff you have in your code like : loading.alpha =1; and blackOverlay.hidden =0; which I assume are elements added to the Activity Indicator

Get data from asynchronous requests in right order

I need to load data from my API without waiting 20s each time I launch my application.
So I use:
NSURL *myUrlCourses = [[NSURL alloc] initWithString:url];
NSMutableURLRequest *request = [NSURLRequest requestWithURL: myUrlCourses];
NSURLConnection *connexion = [[NSURLConnection alloc] initWithRequest:request delegate:self];
for my 10 first request in while loop which permit to get data in background.
But, when I get data from this request with:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{}
The result don't match.
So, I think I have to use thread or something like that to get the right data for each request but I don't really know how!?
Could you help me to solve this problem?
Thanks
Store all of your connections in variables with describing names and then compare the pointer values.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
if(connection == _theFacebookConnection)
{
//Handle Facebook code
}
else if(connection == _theTwitterConnection)
{
//Handle Twitter code
}
}
I use a CFMutableDictionaryRef to save another mutable dictionary for each connection. This inner dictionary can hold as much data as you want.
like this:
#interface Foo {
CFMutableDictionaryRef connections;
}
#implementation Foo
- (id)init {
self = [super init];
if (self) {
connections = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
}
return self;
}
- (BOOL)addURLRequest:(NSURLRequest *)request successSelector:(SEL)successSelector errorSelector:(SEL)errorSelector {
NSMutableDictionary *connectionInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSMutableData data], #"receivedData",
[NSValue valueWithPointer:successSelector], #"successSelector",
[NSValue valueWithPointer:errorSelector], #"errorSelector",
request, #"request",
nil];
NSURLConnection *connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO] autorelease];
CFDictionaryAddValue(connections, connection, connectionInfo);
[connection start];
return YES;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSMutableDictionary *connectionInfo = (NSMutableDictionary *)CFDictionaryGetValue(connections, connection);
[[connectionInfo objectForKey:#"receivedData"] appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSMutableDictionary *connectionInfo = (NSMutableDictionary *)CFDictionaryGetValue(connections, connection);
NSData *data = [connectionInfo objectForKey:#"receivedData"];
LogInfo(#"Finished Connection %#", connection);
SEL selector = [[connectionInfo objectForKey:#"successSelector"] pointerValue];
if ([self respondsToSelector:selector]) {
[self performSelector:selector withObject:data];
}
CFDictionaryRemoveValue(connections, connection);
}
I use ASIHTTPRequest for this sort of thing because I can use [request setUserInfo:(NSDictionary *)] to specify additional data that travels around with the request responses.
Then when I receive each response, I can look at that requests UserInfo dictionary and process the data accordingly.
What's nice about this is you can put as much or as little data into the UserInfo Dictionary as you require.

Second asynchronous NSURLConnection doesn't call delegate methods

From my ApplicationDelegate, I'm doing an NSURLConnection fetch over the network (it's wrapped in a class, as you'll see below). This one seems to work correctly: I get all the data in didReceiveData and I get the completion call connectionDidFinishLoading. At the end of connectionDidFinishLoading, I instantiate one or more of a slightly different kind of wrapper class, but they're essentially the same thing. The problem is that the second NSURLConnection's delegate is never having it's methods called.
I've looked at many different answers, but all to no avail. I'm not spawning any new threads and all the [NSThread isMainThread] checks I've littered throughout the code return true.
I'm stumped. Can anyone help me out? Here's the relevant code:
App Delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
ConnectionWrapper* w = [[ConnectionWrapper alloc] initWithParams:self
url:[NSURL URLWithString:<url>]];
[w beginFetch];
return YES;
}
...
-(void)fetchCompleted:(NSURL*)url directory:(NSString*)directory
{
NSLog(#"fetch completed");
}
-(void)fetchFailed:(NSURL*)url
{
NSLog(#"fetch failed");
}
...
ConnectionWrapper:
-(id)initWithParams:(id<ConnectionWrapperDelegate>)d url:(NSURL*)url
{
delegate = d;
connURL = url;
return [self init];
}
-(void)beginFetch
{
NSURLRequest* request = [[NSURLRequest alloc] initWithURL:connURL];
NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn release];
[request release];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"append");
[responseData appendData:data];
}
- (void) connectionDidFinishLoading: (NSURLConnection*) connection
{
... parsing ....
DifferentConnectionWrapper* w = [[DifferentConnectionWrapper alloc] initWithParams:self
url:[NSURL URLWithString:<different url>]];
[w beginFetch];
}
-(void)fetchCompleted:(NSURL*)URL
{
NSLog(#"completed: %#", URL);
}
-(void)fetchFailed:(NSURL*)URL
{
NSLog(#"failed");
}
DifferentConnectionWrapper:
-(id)initWithParams:(id)d url:(NSURL*)url
{
delegate = d;
connURL = url;
return [self init];
}
-(void)beginFetch
{
NSURLRequest* request = [[NSURLRequest alloc] initWithURL:connURL];
NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn release];
[request release];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"append");
[responseData appendData:data];
}
- (void) connectionDidFinishLoading: (NSURLConnection*) connection
{
... parsing ....
DifferentConnectionWrapper* w = [[DifferentConnectionWrapper alloc] initWithParams:self
url:[NSURL URLWithString:<different url>]];
[w beginFetch];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(#"got response");
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"got data");
[responseData appendData:data];
}
- (void) connectionDidFinishLoading: (NSURLConnection*) connection
{
NSLog(#"image saver completed: %#", connURL);
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"error");
}
ConnectionWrapper and DifferentConnectionWrapper have similar functions, but there's other logic that I've omitted here for brevity.
thanks for the help. I appreciate it.
A couple of things: I don't see a didFailWithError: in your first wrapper class, and (a little off topic) are you leaking memory with your DifferentConnectionWrapper *w ?
Anyway, what I would try is: see if you can invoke DifferentConnectionWrapper directly from the appDelegate instead of the ConnectionWrapper.
And I would try to decouple the two calls in any event. When the first one finishes, and calls appDelegate, can't you launch your DifferentConnectionWrapper from there?
I realize this doesn't explain your problem, but you might get it working (and which of THOSE two things is more important, is an entirely different debate.)
I believe the problem is that you’re releasing the URL connection in -beginFetch:
-(void)beginFetch
{
NSURLRequest* request = [[NSURLRequest alloc] initWithURL:connURL];
NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn release];
[request release];
}
The URL connection object should be kept alive and released when the connection has finished loading:
- (void) connectionDidFinishLoading: (NSURLConnection*) connection
{
... parsing ....
// *** Release the connection and whatever data you’ve kept related to
// this particular connection
[connection release];
[responseData release];
// *** or [responseData setLenght:0]; depending on how you’re
// managing responseData
DifferentConnectionWrapper* w = [[DifferentConnectionWrapper alloc] initWithParams:self
url:[NSURL URLWithString:<different url>]];
[w beginFetch];
}
or when there’s been an error:
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
// *** Release the connection and whatever data you’ve kept related to
// this particular connection
[connection release];
[responseData release];
// *** or [responseData setLenght:0]; depending on how you’re
// managing responseData
// inform the user
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
Edit: Your initialiser is a tad weird:
-(id)initWithParams:(id<ConnectionWrapperDelegate>)d url:(NSURL*)url
{
delegate = d;
connURL = url;
return [self init];
}
There’s no way to know what happens unless we see the code for -init and, at any rate, this should be the designated initialiser, so it shouldn’t be sending -init to self anyway. Furthermore, you should be retaining the url object that’s being passed to the initialiser.
The following makes more sense:
-(id)initWithParams:(id<ConnectionWrapperDelegate>)d url:(NSURL*)url
{
self = [super init];
if (self) {
delegate = d;
connURL = [url retain];
}
return self;
}
Don’t forget to release the url object in -dealloc or when you’re assigning another value to connURL.
OK. It turns out that this bug was caused by something I missed. I was going into a hard spin right after that second request, which would probably screw up just about anything. Once I fixed that problem, everything worked just fine.
Thanks for the help.

didReceiveAuthenticationChallenge method crashes in the SDK 3.1.2

I have code running good in 3.0 and 3.1 but when I use the SDK 3.1.2 is crash at the didReceiveAuthenticationChallenge method says a log "obj_msgSend" . It happens always when using didReceiveAuthenticationChallenge .
Also I have all the other methods in that class
didreceive response
connectionfinishloading
didfailwitherror etc
Please help me out
I got the answer do not release the [newCredential release];
in didreceiveauthentiationchallenge
I am posting the twitter request class method , which is calling the twitter XML API URL for sending messages .
Which require authentication .
-(void)statuses_update:(NSString *)status delegate:(id)requestDelegate requestSelector:(SEL)requestSelector; {
isPost = YES;
// Set the delegate and selector
self.delegate = requestDelegate;
self.callback = requestSelector;
// The URL of the Twitter Request we intend to send
NSURL *url = [NSURL URLWithString:#"http://twitter.com/statuses/update.xml"];
requestBody = [NSString stringWithFormat:#"status=%#",status];
[self request:url];
}
-(void)request:(NSURL *) url {
theRequest = [[NSMutableURLRequest alloc] initWithURL:url];
if(isPost) {
NSLog(#"ispost");
[theRequest setHTTPMethod:#"POST"];
[theRequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[theRequest setHTTPBody:[requestBody dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]];
[theRequest setValue:[NSString stringWithFormat:#"%d",[requestBody length] ] forHTTPHeaderField:#"Content-Length"];
}
theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
// Create the NSMutableData that will hold
// the received data
// receivedData is declared as a method instance elsewhere
receivedData=[[NSMutableData data] retain];
} else {
// inform the user that the download could not be made
}
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge {
//NSLog(#"challenged %#",[challenge proposedCredential] );
if ([challenge previousFailureCount] == 0) {
NSURLCredential *newCredential;
newCredential=[NSURLCredential credentialWithUser:[self username] password:[self password] persistence:NSURLCredentialPersistenceNone];
[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
[newCredential release];
} else {
[[challenge sender] cancelAuthenticationChallenge:challenge];
// inform the user that the user name and password
// in the preferences are incorrect
NSLog(#"Invalid Username or Password");
isFirstTime==NO;
UIAlertView * userNameAlert = [[UIAlertView alloc]initWithTitle:#"Alert" message:#"Invalid credentials. Please check your login details !" delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK",nil];
[userNameAlert show];
if(delegate && callback) {
if([delegate respondsToSelector:self.callback]) {
[delegate performSelector:self.callback withObject:nil];
} else {
NSLog(#"No response from delegate");
}
}
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
// this method is called when the server has determined that it
// has enough information to create the NSURLResponse
// it can be called multiple times, for example in the case of a
// redirect, so each time we reset the data.
// receivedData is declared as a method instance elsewhere
[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
//NSLog([[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
// append the new data to the receivedData
// receivedData is declared as a method instance elsewhere
[receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
// release the connection, and the data object
[connection release];
// receivedData is declared as a method instance elsewhere
[receivedData release];
[theRequest release];
// inform the user
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
if(errorCallback) {
[delegate performSelector:errorCallback withObject:error];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// do something with the data
if(delegate && callback) {
UIAlertView * userNameAlert = [[UIAlertView alloc]initWithTitle:#"Congratulation" message:#"Your Message is successfully posted to twitter !" delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK",nil];
[userNameAlert show];
isLoginChanged =YES;
isFirstTime==NO;
if([delegate respondsToSelector:self.callback]) {
[delegate performSelector:self.callback withObject:receivedData];
} else {
NSLog(#"No response from delegate");
}
}
// release the connection, and the data object
[theConnection release];
[receivedData release];
[theRequest release];
}

Need help: My program should react when an other class is doing something specific - Not as easy as it sounds

I´m writing an program that uses twitter. I want that my app shows an UIAlertView when the user presses on the "Tweet"-Button and the username or password is wrong.
For my Twitterfunction I use the TwitterRequest.m/h from Brandon Trebitowski. If everthing works great and the username/password is right, this happens in my app:
TwitterRequest * t = [[TwitterRequest alloc] init];
(...);
[t statuses_update:twittermessage.text delegate:self requestSelector:#selector(status_updateCallback:)];
loadingActionSheet = [[UIActionSheet alloc] initWithTitle:#"Posting to Twitter..." delegate:nil
cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
[loadingActionSheet showInView:self.view];
}
- (void) status_updateCallback: (NSData *) content {
[loadingActionSheet dismissWithClickedButtonIndex:0 animated:YES];
[loadingActionSheet release];
NSLog(#"%#",[[NSString alloc] initWithData:content encoding:NSASCIIStringEncoding]);
}
But how can I show an UIAlertView when the username/password was wrong?
Here is the TwitterRequest.m:
#import "TwitterRequest.h"
#implementation TwitterRequest
#synthesize username;
#synthesize password;
#synthesize receivedData;
#synthesize delegate;
#synthesize callback;
#synthesize errorCallback;
-(void)friends_timeline:(id)requestDelegate requestSelector:(SEL)requestSelector{
isPost = NO;
// Set the delegate and selector
self.delegate = requestDelegate;
self.callback = requestSelector;
// The URL of the Twitter Request we intend to send
NSURL *url = [NSURL URLWithString:#"http://twitter.com/statuses/friends_timeline.xml"];
[self request:url];
}
-(void)statuses_update:(NSString *)status delegate:(id)requestDelegate requestSelector:(SEL)requestSelector; {
isPost = YES;
// Set the delegate and selector
self.delegate = requestDelegate;
self.callback = requestSelector;
// The URL of the Twitter Request we intend to send
NSURL *url = [NSURL URLWithString:#"http://twitter.com/statuses/update.xml"];
requestBody = [NSString stringWithFormat:#"status=%#",status];
[self request:url];
}
-(void)request:(NSURL *) url {
theRequest = [[NSMutableURLRequest alloc] initWithURL:url];
if(isPost) {
NSLog(#"ispost");
[theRequest setHTTPMethod:#"POST"];
[theRequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[theRequest setHTTPBody:[requestBody dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]];
[theRequest setValue:[NSString stringWithFormat:#"%d",[requestBody length] ] forHTTPHeaderField:#"Content-Length"];
}
theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
// Create the NSMutableData that will hold
// the received data
// receivedData is declared as a method instance elsewhere
receivedData=[[NSMutableData data] retain];
} else {
// inform the user that the download could not be made
}
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
//NSLog(#"challenged %#",[challenge proposedCredential] );
if ([challenge previousFailureCount] == 0) {
NSURLCredential *newCredential;
newCredential=[NSURLCredential credentialWithUser:[self username]
password:[self password]
persistence:NSURLCredentialPersistenceNone];
[[challenge sender] useCredential:newCredential
forAuthenticationChallenge:challenge];
} else {
[[challenge sender] cancelAuthenticationChallenge:challenge];
// inform the user that the user name and password
// in the preferences are incorrect
NSLog(#"Invalid Username or Password"); //THIS MUST be important. The console shows this message, if the username/password is wrong. Here is also the place, where I set the bool to TRUE
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// this method is called when the server has determined that it
// has enough information to create the NSURLResponse
// it can be called multiple times, for example in the case of a
// redirect, so each time we reset the data.
// receivedData is declared as a method instance elsewhere
//[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
//NSLog([[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
// append the new data to the receivedData
// receivedData is declared as a method instance elsewhere
[receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
// release the connection, and the data object
[connection release];
// receivedData is declared as a method instance elsewhere
[receivedData release];
[theRequest release];
// inform the user
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
if(errorCallback) {
[delegate performSelector:errorCallback withObject:error];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// do something with the data
if(delegate && callback) {
if([delegate respondsToSelector:self.callback]) {
[delegate performSelector:self.callback withObject:receivedData];
} else {
NSLog(#"No response from delegate");
}
}
// release the connection, and the data object
[theConnection release];
[receivedData release];
[theRequest release];
}
-(void) dealloc {
[super dealloc];
}
#end
I know that the important line in the TwitterRequest.m is in the else-cause of the -(void)connection-methode, because the Console writes always Invalid Username or Password, when they are wrong. So I tried to make there a bool as propertey, which will be set to TRUE, when the name/password is wrong(= when the else-cause will be used). In my ViewController I made this:
if (t.stimmtNicht == TRUE) {
[loadingActionSheet dismissWithClickedButtonIndex:0 animated:YES];
[loadingActionSheet release];
UIAlertView *alert;
alert = [[UIAlertView alloc] initWithTitle:#"Ouch!"
message:#"Your Username or Password is wrong!"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[alert show];
[alert release];
}
But he always doesn't use the if-cause, even if the password is wrong. I think the code go faster through the if-quere than the TwitterRequest set it to TRUE. What can I do?
Thanks for your help and sorry for this stupid question, but I'm learning Objective-C and programming in general since just one week and I don´t know correctly how to interact from my ViewController with other classes.
Also sorry for my bad English!
Two ways I can think of:
Apparently your TwitterRequest class has a "delegate" ivar; try calling the delegate to tell him (her?) that your credentials are wrong.
Send an NSNotification through the NSNotificationCenter
In both cases, the class who gets notified should display the login view (with the username and password fields), and that's it.