Facebook iPhone SDK: show a progress bar while uploading an image - iphone

I want to show a progress bar while my iPhone app is uploading an image to Facebook. Is it possible?
Can I do it with every FBRequest that I make? I also use FBRequest to check extended permission and sometimes takes a lot of time.
Thank you.

For the progress bar there is a little hack you can do. In the FBRequest.h file add this line in the FBRequestDelegate protocol:
- (void)request:(FBRequest *)request didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite;
After that in the FBRequest.m file add this function:
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite {
if ([_delegate respondsToSelector:#selector(request:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:)]) {
[_delegate request:self didSendBodyData:bytesWritten totalBytesWritten:totalBytesWritten totalBytesExpectedToWrite:totalBytesExpectedToWrite];
}
}
Now your delegate will receive a message every time more data it's posted to the server. So basically if you implement this into your delegate you should see some activity in your log:
- (void)request:(FBRequest *)request didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
NSLog(#"%d bytes out of %d sent.", totalBytesWritten, totalBytesExpectedToWrite);
}
Let me know if you have any problems hacking this into the current Facebook SDK.

You can't know when it gonna log you in but you can put an UIActivityIndicatorView.
You start it when you click on publish button and you end it when you enter the 'didConnect' method

Related

How to know if admob are not coming in iOS?

I am using admobs and i want to know if admobs are not coming.
If admobs are not coming then i should hide that view and when they start coming again then i have to show them onscren.
if my question is silly then don't mind please.
any help?
You should use delegate functions to know whether ads are getting received or not and then handle it accordingly.
Use GADBannerViewDelegate
Implement delegate functions like this:
// We've received an ad successfully.
- (void)adViewDidReceiveAd:(GADBannerView *)adView {
NSLog(#"Received ad successfully");
}
// Ad Not Recieved
- (void)adView:(GADBannerView *)view
didFailToReceiveAdWithError:(GADRequestError *)error {
NSLog(#"Failed to receive ad with error: %#", [error localizedFailureReason]);
}
- (void)adViewWillPresentScreen:(GADBannerView *)bannerView
{
NSLog(#"will Present");
}

How to check how much data send to server with three20?

I want make some progress bar in my application with three20 library when sending data to server. Can someone help me with this?
I am using
- (void)requestDidStartLoad:(TTURLRequest*)request
and
- (void)requestDidFinishLoad:(TTURLRequest*)request
You can implement
- (void)requestDidUploadData:(TTURLRequest *)request
and check the totalBytesLoaded and totalBytesExpected properties, per http://api.three20.info/protocol_t_t_u_r_l_request_delegate-p.php#a9c831806650a4b887f5cf963f6bbba1c.
I have found solution.
You must call
[request send];
to call this delegate function:
- (void)requestDidUploadData:(TTURLRequest *)request
{
float progress = request.totalBytesLoaded / (float)request.totalBytesExpected;
HUD.progress = progress;
HUD.labelText = [NSString stringWithFormat:#"Progress %d%%", (int)(progress*100)];
}
if you call sendSynchronously data will send but you can't get totalBytesLoaded.

How can i know web view is loading completed

i have web view in that i am loading pdf file .
pdf file has 2 mb size so it tacking time. i want to add indicator .
for that how can i know my file is loaded in web view ? ...
UIWebViewDelegate
in particular:
- (void)webViewDidFinishLoad:(UIWebView *)webView
James P has the right answer (^'ed), but here is the code to show and hide the indicator.
After you've registered with the UIWebViewDelegate...
- (void)webViewDidStartLoad:(UIWebView *)webView {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
// Other stuff...
}
And then
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
// Other stuff...
}
Also you probably want to check for failures and hide the activity indicator there as well...
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
// Other stuff...
}
first Add the delegate "UIWebViewDelegate", then you can use the below methods.
– webView:shouldStartLoadWithRequest:navigationType:
– webViewDidStartLoad:
– webViewDidFinishLoad:
– webView:didFailLoadWithError:
You could pull your PDF down using ASIHTTPRequest, which would let you set up a progress bar showing real progress, and then feed it to your UIWebView once it's downloaded.
EDIT: ASIHTTPRequest is a free third-party library that provides a MUCH improved interface to iOS HTTP client functions. LOTS of code samples and instructions here: http://allseeing-i.com/ASIHTTPRequest/How-to-use

How to handle app URLs in a UIWebView?

I recently found that my UIWebView was choking on ITMS links. Specifically, from the UIWebView in my app, if I navigate to a site such as this one and click the "Available on the App Store" link, UIWebView would error out with "Error Domain=WebKitErrorDomain Code=101 The URL can't be shown."
After a bit of Googling, I realized that I needed to catch requests for app links and have iOS handle them. I started out by looking to see if the scheme starts with "itms" in -webView:shouldStartLoadWithRequest:navigationType:, but realized that there might be other kinds of app links that the system can handle. So I came up with this, instead:
- (void)webView:(UIWebView *)wv didFailLoadWithError:(NSError *)error {
// Give iOS a chance to open it.
NSURL *url = [NSURL URLWithString:[error.userInfo objectForKey:#"NSErrorFailingURLStringKey"]];
if ([error.domain isEqual:#"WebKitErrorDomain"]
&& error.code == 101
&& [[UIApplication sharedApplication]canOpenURL:url])
{
[[UIApplication sharedApplication]openURL:url];
return;
}
// Normal error handling…
}
I have two questions about this:
Is this sane? I'm specifically checking for the error domain and error code and fetching the URL string from the userInfo. Is that stuff likely to remain?
This does work for the above-linked app store link, but when I switch back to my app, there appears to have been a subsequent failed request that failed with "Frame load interrupted". how can I get rid of that? It doesn't happen when I have the OS handle the request from -webView:shouldStartLoadWithRequest:navigationType:, so it's a bit annoying.
How do you handle such requests?
Here's what I came up with. In webView:shouldStartLoadWithRequest:navigationType:, I ask the OS to handle any non-http and non-https requests that it can, like so:
- (BOOL)webView:(UIWebView *)wv shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
// Determine if we want the system to handle it.
NSURL *url = request.URL;
if (![url.scheme isEqual:#"http"] && ![url.scheme isEqual:#"https"]) {
if ([[UIApplication sharedApplication]canOpenURL:url]) {
[[UIApplication sharedApplication]openURL:url];
return NO;
}
}
return YES;
}
This works very well except for the bloody "Frame Load Interrupted" error. I had thought that by returning false from webView:shouldStartLoadWithRequest:navigationType: that the web view would not load the request and therefore there would be no errors to handle. But even though I return NO above, I still "Frame Load Interrupted" error. Why is that?
Anyway, I'm assuming it can be ignored in -webView:didFailLoadWithError::
- (void)webView:(UIWebView *)wv didFailLoadWithError:(NSError *)error {
// Ignore NSURLErrorDomain error -999.
if (error.code == NSURLErrorCancelled) return;
// Ignore "Fame Load Interrupted" errors. Seen after app store links.
if (error.code == 102 && [error.domain isEqual:#"WebKitErrorDomain"]) return;
// Normal error handling…
}
And now iTunes URLs work properly, as do mailto:s and app links.
Starting with Theory's code, examine the URL for "itms" scheme(s) (this method can be called multiple times due to redirects). Once you see an "itms" scheme, stop the webView from loading and open the URL with Safari. My WebView happens to be in a NavigationController, so I pop out of that after opening Safari (less flashing).
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request
navigationType:(UIWebViewNavigationType)navigationType
{
if ([[[request URL] scheme] isEqualToString:#"itms-apps"]) {
[webView stopLoading];
[[UIApplication sharedApplication] openURL:[request URL]];
[self.navigationController popViewControllerAnimated:YES];
return NO;
} else {
return YES;
}
}
Does it help if you register your app for handling itms: links?
e.g.
http://inchoo.net/iphone-development/launching-application-via-url-scheme/
You may start with scheme http but then get an itms redirect, which could fail if your app is not registered as handling that scheme.

UIWebView - How to identify the "last" webViewDidFinishLoad message?

The webViewDidFinishLoad message seems to be sent each time any object in the page has been loaded. Is there a way to determine that all loading of content is done?
I'm guessing that iframes cause the webViewDidStartLoad / webViewDidFinishLoad pair.
The [webView isLoading] check mentioned as an answer didn't work for me; it returned false even after the first of two webViewDidFinishLoad calls. Instead, I keep track of the loading as follows:
- (void)webViewDidStartLoad:(UIWebView *)webView {
webViewLoads_++;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
webViewLoads_--;
if (webViewLoads_ > 0) {
return;
}
…
}
- (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error {
webViewLoads_--;
}
(Note this will only work if the start / finished pairs don't come serially, but in my experience so far that hasn't happened.)
Check this one, it will definitely work for you:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
if ([[webView stringByEvaluatingJavaScriptFromString:#"document.readyState"] isEqualToString:#"complete"]) {
// UIWebView object has fully loaded.
}
}
Interesting, I wouldn't have thought it would work like that. Although I'm sure there are other ways to do it (is there a way to extract the URL from the webViewDidFinishLoad message so that you can see which one is the main page finishing loading?), the main thing I can think of is using the estimatedProgress to check the progress of the page and fire off whatever you want to do when it's 100% finished loading, which is what I do in my app. Google "iphone webview estimatedprogress" and click the first link for a guide I wrote on how to do this.
Update:
Please use phopkins' answer below instead of mine! Using private APIs in your apps is a bad idea and you will probably get rejected, and his solution is the right one.
Another way to monitor load progress with less control is to observe the WebViewProgressEstimateChangedNotification, WebViewProgressFinishedNotification, and WebViewProgressStartedNotification notifications. For example, you could observe these notifications to implement a simple progress indicator in your application. You update the progress indicator by invoking the estimatedProgress method to get an estimate of the amount of content that is currently loaded.
from http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/WebKit/Classes/WebView_Class/Reference/Reference.html
You can also use this short Category I wrote that adds blocks into UIWebView and also lets you choose between default UIWebView behavior (getting notified after each object load), or the "expected" behavior (getting notified only when the page has fully loaded).
https://github.com/freak4pc/UIWebView-Blocks
I needed to capture a variable from the page which was not fully loaded yet.
This worked for me:
- (void) webViewDidFinishLoad:(UIWebView *)webView {
NSString *valueID = [webView stringByEvaluatingJavaScriptFromString:#"document.valueID;"];
if([valueID isEqualToString:#""]){
[webView reload];
return;
}
//page loaded
}
All of the options did not really work for my use case. I used phopkins example slightly modified. I found that if the HTML loaded into the webview contained an image that would be a separate request that happened serially so we have to account for that and I did that with a timer. Not the best solution but it seems to work.:
- (void)webViewActuallyFinished {
_webViewLoads--;
if (_webViewLoads > 0) {
return;
}
//Actually done loading
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
_webViewLoads++;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(webViewActuallyFinished) userInfo:nil repeats:NO];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
_webViewLoads--;
}
hi it may be a bit far back already but i hope this helps.
i just used a notification when it enters the webViewDidFinishLoad method so that i can capture one instance of the method and then i'll detect the notification and do my logic from there.
hope this helps. it does not capture the last called instance of the webViewDidFinishLoad method, but allows you to do something once it has been called and not be repeated calls to that particular method (eg. showing a button) too.
*********EDIT*********
i did a test and managed to test it out. it actually works and the method called from the notification will be called after the full page has been loaded.
alternatively, i think you can do a counter on the delegate method webViewDidStartLoad and also on webViewDidFinishLoad to make sure that they are the same before you run your codes. this though, is an ugly hack as we will never know how many times it will be called unless like me, you are loading a html feed and can add a JavaScript to check how many elements there are on the page that you are loading. i'm just sharing some of the methods i have tried to solve this. hope it helps.
feedback is encouraged. thanks!
Here's what I use to show a spinner while DOM loads, built on top of #Vinod's answer.
Note that between webViewDidStartLoad and webViewDidFinishLoad the readyState is completed from the previous request (if any), that's why the polling should begin after webViewDidFinishLoad.
readyState possible values are loading, interactive or completed (and maybe nil ?)
- (void)webViewDidStartLoad:(UIWebView *)webView {
[self spinnerOn];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[self startDOMCompletionPolling];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
[self startDOMCompletionPolling];
}
- (void)startDOMCompletionPolling {
if (self.domCompletionListener) {
[self.domCompletionListener invalidate];
}
self.domCompletionListener = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(checkDOMCompletion) userInfo:nil repeats:YES];
}
- (void)checkDOMCompletion {
NSString *readyState = [self.webView stringByEvaluatingJavaScriptFromString:#"document.readyState"];
if (readyState != nil) {
if (readyState.length > 0) {
if ([readyState isEqualToString:#"loading"]) { //keep polling
return;
}
}
}
//'completed', 'interactive', nil, others -> hide spinner
[self.domCompletionListener invalidate];
[self spinnerOff];
}
The way I do it is this:
- (void)webViewDidFinishLoad:(UIWebView *)webview {
if (webview.loading)
return;
// now really done loading code goes next
[logic]
}