I want that my app shows an actionsheet 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:@开发者_StackOverflow中文版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 other actionsheet 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");
}
}
- (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
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.
To implement an action sheet, you must first implement the UIActionSheetDelegate in the header file (include UIActionSheetDelegate in the @interface definition between the <>).
In your code you are going to display the action sheet and catch the actions from the button press. To display an action sheet, do the following:
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:@"Choose one, por favor"
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@"Save Favorite", @"Email", nil];
actionSheet.actionSheetStyle = UIActionSheetStyleBlackTranslucent;
actionSheet.cancelButtonIndex = 2;
[actionSheet showInView:self.view];
[actionSheet release];
To act on the button press, use the following method:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
// the user clicked one of the OK/Cancel buttons
NSLog(@"The button index is: %i", buttonIndex);
switch (buttonIndex) {
case 0:
NSLog(@"Button 0");
[self saveNew];
break;
case 1:
NSLog(@"Button 1");
[self sendEmail];
break;
case 2:
NSLog(@"Button 2");
break;
default:
break;
}
}
Your other option is to use an alert -- for an incorrect username/password, this may be the best option. The alert is a modal box displayed in the center of the screen. To implement an alert, implement the UIAlertViewDelegate in your header file.
Sample alert code is as follows:
UIAlertView *alert;
alert = [[UIAlertView alloc] initWithTitle:@"Ouch!"
message:@"Your message is placed here"
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles: nil];
[alert show];
[alert release];
if you want to react when the user receives a request for authentication, you need to work inside didReceiveAuthenticationChallenge.
specifically, right above this line:
newCredential=[NSURLCredential credentialWithUser:[self username]
password:[self password]
persistence:NSURLCredentialPersistenceNone];
is where you want to be getting the username and password from the user.
if you want to handle a failure on authentication, you wanna piggyback on the 'else' clause in the previousCountFailure if statement.
specifically, after this line is where you want to tell the user they failed:
[[challenge sender] cancelAuthenticationChallenge:challenge];
精彩评论