FBLoginDialog not shown - iphone

I'm an iphone newb. I added the following code to my viewDidLoad() method but a blank screen shows up. What am I doing wrong?
FBSession *session = [FBSession
sessionForApplication:#"a31c3e53bba4a5f2b3955d6e5e 876717"
secret:#"6ecbefa3807406bd13187297e58efae9" delegate:self];
FBLoginDialog* dialog = [[[FBLoginDialog alloc] initWithSession:session] autorelease];
[dialog show];
Thanks!

I put the code into the AppDelegate's didFinishLaunchingWithOptions method and it worked!

the call to [dialog show] has to occur on the main thread (as all UI related calls)

Related

Delay execution of code following UIAlertView show statement, until the alert is showing

I'm attempting to create a "Please wait" UIAlertView that will appear while my code is downloading and calculating some data, then disappear when it has finished. Specifically, it is parsing an xml file it receives from Geonames.org.
The alert works fine, and i have the Show statement before my code, followed by the dismiss statement. My problem, however, is that the screen dims as if it were about to show the alert, parses and uses the xml, then appears for a split second and dismisses, essentially rendering the alert useless!
Below is an excerpt of my code:
//Show Alert
UIAlertView *waitAlert = [[UIAlertView alloc] initWithTitle:#"Please Wait"
message:#"Determining your current suburb."
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:nil];
[waitAlert show];
//Activity Indicator
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
activityIndicator.center = CGPointMake(waitAlert.bounds.size.width / 2.0f, waitAlert.bounds.size.height - 40.0f);
[activityIndicator startAnimating];
[waitAlert addSubview:activityIndicator];
[activityIndicator release];
//Reverse Geocode
//Parse xml
NSURL *apiUrl = [[NSURL alloc] initWithString:#"http://api.geonames.org/findNearbyPlaceName?lat=-34.032188&lng=151.084494&username=l_plater"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:apiUrl];
[xmlParser setDelegate:self];
[xmlParser parse];
[xmlParser release];
[apiUrl release];
[waitAlert dismissWithClickedButtonIndex:0 animated:YES];
[waitAlert release];
I would perform the calculations in a background thread, but i need these to be completed before the user is allowed to continue.
Thanks heaps in advanced, any help is much appreciated :)
That's totally normal.
NSXMLParser's initWithContentsOfURL download the data (at the specified URL) synchronously, so the download of the XML data is done in a blocking way.
Your main thread is then frozen until the data has finished downloaded and parsed.
You have to defer the download of your XML data in a separate thread, or much more efficiently, use NSURLConnection and its asynchronous download mechanism to download your XML data. Thus your main thread will continue executing without freezing, and your UIAlertView will be shown.
Then, after the download is done in the background, you will be asynchronously informed when the XML data has been downloaded, using the NSURLConnection delegate methods. That's the place to create your NSXMLParser, parse the data that has been asychronously downloaded, then dismiss your alertview once done.

Showing alert while calling webservice

i have the following code.
UIActivityIndicator *activity = [[UIActivityIndicator alloc] initWithActivityIndicatorStyle:
UIActivityIndicatorStyleWhite];
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Processing" delegate:self otherButtonTitles:nil];
[alert addSubview:activity];
[activity startAnimating];
[alert show];
WebServiceController *web = [[WebServiceController alloc]init];
NSDictionary *dict = [web getDetails];
The problem is that the alert is not getting displayed. The WebServiceController is an XML parser which gets details from a specified URL and returns them. The alert should be shown while the service is called as it takes time to get the details. But it displays the alert only after the service call is over. Why is that?
because [alert show] will require animation, since the service controller call is taking place on the main thread, the main thread is busy executing the service call, blocking the alert view animation to execute.
You need to perform the ServiceCall on backend thread, see NSOperation or PerformSelectorOnBackgroundThread, make sure you pass in delegate of the ViewController that has the AlertView to the backend thread, callback the delegate as soon as the service call is completed. Make sure you perform the call for the callback on the mainthread using performSelectorOnMainThread. All UI related calls should be executed on the main thread.
Adding to the above post, you have to write the alert like this:
UIActivityIndicator *activity = [[UIActivityIndicator alloc] initWithActivityIndicatorStyle:
UIActivityIndicatorStyleWhite];
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Processing" delegate:self otherButtonTitles:nil];
[alert addSubview:activity];
[activity startAnimating];
[alert show];
[self performSelectorInBackground:#selector(doTheWork) object:nil];
You need to declare a function (doTheWork) which will take care of the web service call as follows:
-(void)doTheWork {
WebServiceController *web = [[WebServiceController alloc]init];
NSDictionary *dict = [web getDetails];
[alert dismissWithClickedButtonIndex:0 animated:YES]; //dismissing the alert
}

Update text in alert message

Still trying to update the message in an UIAlertview while the alert is active. I removed most of the first part of the question and publish more code in the update below.
UPDATE 3: Adding more code!
In the .h file I declare the following (among others):
#interface WebViewController : UIViewController <UIWebViewDelegate> {
IBOutlet UIWebView *webView;
UIAlertView *alert;
}
I #property and #synthesize the UIAlertview to.
Next I create the alert in an IBAction which is run by a button click:
-(IBAction)convert {
convertButton.enabled = NO;
mailButton.enabled = NO;
backButton.enabled = NO;
//show the alert window
alert = [[UIAlertView alloc] initWithTitle:#"Converting in progress\nPlease Wait..." message:#"\n\n\n" delegate:self cancelButtonTitle:nil otherButtonTitles: nil];
[alert show];
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
// Adjust the indicator so it is up a few pixels from the bottom of the alert
indicator.center = CGPointMake(alert.bounds.size.width / 2, alert.bounds.size.height - 50);
[indicator startAnimating];
[alert addSubview:indicator];
[indicator release];
[alert setMessage:#"getting roster"];
}
It then jumps to the following function:
- (void)didPresentAlertView:(UIAlertView *)progressAlert {
//A lot of code
[alert setMessage:#"Checking history"];
//more code
[alert setMessage:#"writing history"];
//even more code
[alert setMessage:#"converting roster"];
}
The didPresentAlertView method ends with an ASIHTTPRequest to post data to a webpage and when this request is finished the code finally jumps to the last method to exit the UIAlertView and closes everything up:
- (void)requestFinished:(ASIHTTPRequest *)request {
[timer invalidate];
[alert dismissWithClickedButtonIndex:0 animated:YES];
backButton.enabled = YES;
[alert release];
}
I also removed the autorelease from my UIAlertView init to make sure it exists during the rest of the process.
As it is now, the code only fires the very first setMessage -> 'getting roster' and the very last -> 'converting roster'. The setMessage requests in the middle do not get fired..
Really hope someone can help me here!
Thanks all!
Now I see the problem.
When you update the message property, it doesn't fire redrawing the view right away. The view is marked as 'needed to be drawn', and the actual drawing happens later, typically at the end of the current or next runloop in the main thread.
Therefore, while your didPresentAlertView method is running on the main thread, the alert view is not redrawn until the method is finished. This is why a computation-intensive job needs to run on a separate thread to increase the responsiveness of the UI, as the UI-related job is done on the main thread.
What you should do is run your //A lot of code //more code and //even more code on a separate thread, and update the message property on the main thread.
For example, your code may look similar to :
// this is inside didPresentAlertView method
NSOperationQueue* aQueue = [[NSOperationQueue alloc] init];
[aQueue addOperationWithBlock: ^{
// A lot of code
[alert performSelector:#selector(setMessage:) onThread:[NSThread mainThread]
withObject:#"Checking history" waitUntilDone:NO];
// more code
[alert performSelector:#selector(setMessage:) onThread:[NSThread mainThread]
withObject:#"writing history" waitUntilDone:NO];
// it goes on
}];
If you are working with iOS 4.0 and later, and want to use the GDC, be careful because it may detect independency of your computation and message updates and let them happen concurrently (which is not desired here).

UIAlertViews disappear when calling UIActivityIndicatorView method

if I show an Alert and then call a method of an Activity Indicator, the alert disappears like the user has pressed OK.
Declaration of alert:
UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:#"Error loading content" message:errorString delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
Declaration of Activity Indicator:
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
indicator.hidesWhenStopped = YES;
[indicator stopAnimating];
Method call which causes this problem:
[indicator stopAnimating];
What can I do?
Edit: I noticed that my app isn't working correct, if NSXML Parser is getting a wrong URL. At the moment I cannot say if the activity indicator is causing a error.
you could have the ActivityIndicator embedded in your alertview, looks neat and tidy:
http://kwigbo.com/post/394670170/iphone-sdk-uialertview-with-activity-indicator
Edit: Re-read your question, above solution might not be suitable for your needs.
Let me ask, what exactly are you trying to do with those two views?

FBDialog cancel button callback

When user hits the Cancel button in the FBStreamDialog, which inherits from FBDialog, I am having trouble differentiating it from when user clicks on the Publish button. Seems that the callback FBDialog dismissWithSuccess is always passed with the status:NO regardless of which button is clicked. What am I doing wrong? Thanks!
Here's the class that handles all the FBConnect in my app:
#interface SocialMediaViewController : UIViewController <FBSessionDelegate, FBRequestDelegate, FBDialogDelegate> {...
Here's how I instantiated the login.
FBLoginDialog* dialog = [[[FBLoginDialog alloc] initWithSession:self.fbSession] autorelease];
dialog.delegate = self;
[dialog show];
Here's how I instantiated the FBStreamDialog.
FBStreamDialog* dialog = [[FBStreamDialog alloc] init];
dialog.delegate = self;
dialog.userMessagePrompt = #"Enter additional comment:";
dialog.attachment = [NSString stringWithFormat:#"{\"name\":\"My name string %#\"," "\"href\":\"http://xyz.com/\"," "\"caption\":\"placeholder-%#\",\"description\":\"%#\"," "\"properties\":{\"More like this\":{\"text\":\"XYZ website\",\"href\":\"http://XYZ.com/\"}}}", self.curReview.businessName, self.curReview.reviewType, self.curReview.reviewDetail];
[dialog show];
Add the following as the first line in FBDialog.m / webViewDidFinishLoad :
[_webView stringByEvaluatingJavaScriptFromString:#"document.getElementById('cancel').onclick = function onclick(event) { window.location.href = 'fbconnect:cancel'; }"];
Bear in mind that Facebook doesn't let you "punish" users for canceling :-)