I have an app with a standard view controller with multiple buttons on it. Each button links to a separate view controller with a unique UIWebView. Each UIWebView has didFailLoadWithError implemented and it seems to work fine: when I turn off wifi, and try to load the UIWebView from the main view controller page, I correctly get the error message from didFailLoadWithError. When I turn on wifi and load the UIWebView, it works fine - no error. However, when I click on a link within that UIWebView page, I get the didFailLoadWithError error again. Even more interesting, I clear the error message and the new page still loads from the link I just clicked, so I know the connection is good. Here is my implementation...does anyone know of a way to force didFailLoadWithError to only run once on first load and suppress it from running again once you verify a web connection is good?
#synthesize webView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Network Alert" message:#"No Internet Connection - Please Check Your Network Settings and Try Again" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[alert show];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString: #"http://www.site.com/index.html"]]];
[webView addSubview:activity];
timer=[NSTimer scheduledTimerWithTimeInterval:(1.0/2.0)
target:self selector:#selector(loading) userInfo:nil repeats:YES];
}
- (void)loading {
if (!webView.loading)
[activity stopAnimating];
else
[activity startAnimating];
}
I just had this problem. Whats going on, is when you click on a link within the web view, while the page is still loading, you will get error -999. This translates to NSURLErrorCancelled.
You can find out more in the following link. Goto the URL Loading System Error Codes section. https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Constants/Reference/reference.html
In my code i was telling an alert view to pop up saying the internet connect was lost upon -webView:didFailLoadWithError: being called. I wrapped that code around a condition on the error object. Heres an example.
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
if ([error code] == NSURLErrorNotConnectedToInternet || [error code] == NSURLErrorNetworkConnectionLost) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:#"Check internet connection." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
}
}
Related
I am having issues not being able to close CDVViewController when calling this custom refresh, it stays loaded in the background and loads a new one causing memory leaks/high memory usage. I have tried to use both release and removeFromSuperview for the webView, subview, CDVViewController, ChildViewController but none of them work. I am running a Tab Bar Controller via Storyboard, (another reason why I have to call CDVViewController as a subview) and when I use the web inspector via safari I can see the pages building up on that tab, and when I refresh on another tab (not using CDVViewController/phonegap) it works fine. Any help is much appreciated.
So here is my .h
#import <UIKit/UIKit.h>
#import <ifaddrs.h>
#import <arpa/inet.h>
#import <Cordova/CDVViewController.h>
#interface ThirdViewController : CDVViewController <UIWebViewDelegate>
{
IBOutlet CDVViewController *webView;
IBOutlet UIActivityIndicatorView *activityind;
}
- (IBAction)Refresh:(id)sender;
#end
And my .m
#interface ThirdViewController ()
#end
#implementation ThirdViewController
- (void)viewDidLoad
{
webView = [CDVViewController new];
webView.startPage = #"MYWEBSITE";
[self addChildViewController:webView];
[self.webView addSubview:webView.view];
webView.view.frame = CGRectMake(0, 0, 0, 0);
[activityind startAnimating];
[self.webView addSubview: activityind];
[self CustomActivity];
}
-(void) CustomActivity
{
if ([webView.reference isEqualToString:#"TRUE"]){ //webView.reference is something I added into phonegap CDVViewController so that I am able to see when it is being loaded/used to load the custom activity/activity ind to work.
[activityind removeFromSuperview];
}else{
[NSTimer scheduledTimerWithTimeInterval:.5 target:self selector:#selector(CustomActivity) userInfo:nil repeats:NO];
}
}
- (IBAction)Refresh:(id)sender {
webView = [CDVViewController new];
webView.startPage = #"MYWEBSITE";
[self addChildViewController:webView];
[self.webView addSubview:webView.view];
webView.view.frame = CGRectMake (0,0,self.view.frame.size.width,(self.view.frame.size.height -44));
[activityind startAnimating];
[self.webView addSubview: activityind];
[self CustomActivity];
}
- (void)webViewDidStartLoad:(UIWebView *)webView {}
- (void)webViewDidFinishLoad:(UIWebView *)subview {}
- (void)loading {}
- (void)didReceiveMemoryWarning{[super didReceiveMemoryWarning];}
#end
Found the solution, I had to implement [webView.webView reload];
- (IBAction)Refresh:(id)sender {
[webView.webView reload];
}
Is it possible to play a track when the app has exited/gone into a background state?
For example:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSURL *trackURL = [NSURL URLWithString:#"spotify:track:489K1qunRVBm2OpS4XGLNd"];
[[SPSession sharedSession] trackForURL:trackURL callback:^(SPTrack *track) {
if (track != nil) {
[SPAsyncLoading waitUntilLoaded:track timeout:kSPAsyncLoadingDefaultTimeout then:^(NSArray *tracks, NSArray *notLoadedTracks) {
[self.playbackManager playTrack:track callback:^(NSError *error) {
if (error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Cannot Play Track"
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
} else {
self.currentTrack = track;
}
}];
}];
}
}];
}
The above code was taken from the Simple Player app provided with cocoalibspotify.
Copying and pasting code like this won't get you far when backgrounding - you can't use UI elements like UIAlertView, for a start.
You need to declare your application as supporting the audio background mode as documented by Apple. Then, when you go into the background you should make a background task to start playback.
I'm trying to alert the user if a web view loads for more than 10 seconds. The error is incase there is slow or no internet connection. The problem is that this code does not work.
In the first case I'm attempting to start the timer when the web view starts loading. Then either expire with doing nothing or display an alert after 10 seconds that the web view is loading very slow or not at all.
In the second case I've attempted to start the timer when the web view starts and either show the alert after 10 seconds or invalidate the timer before it expires.
Neither of which seem to work correctly.
- (void)viewDidLoad
{
timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(webViewLoading) userInfo:nil repeats:YES];
webViewLoadTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:#selector(showAlert) userInfo:nil repeats:NO];
[super viewDidLoad];
[self configureView];
}
-(void)showAlert
{
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle: #"Warning"
message: #""
delegate: self
cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil];
if (self.bgWebView.loading){[alert show];}
}
I have tried putting the timer in the following method, but then it alerts every time regardless of whether the device is connected to internet or not. It doesn't seem to invalidate.
-(void)webViewLoading
{
if (self.bgView.loading)
{
[self.avBackGround startAnimating];
webViewLoadTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:#selector(showAlert) userInfo:nil repeats:NO];
}
else
{
[self.avBackGround stopAnimating];
[webViewLoadTimer invalidate];
}
if (self.icnWebView.loading)
{
[self.avIcon startAnimating];
}
else
{
[self.avIcon stopAnimating];
}
}
I apologize if I have missed a post on this. I just can't seem to put this together.
Thanks for any help!
I want to launch MSN through my iphone App.
I am using url shema-
BOOL msn = [[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"msnim://"]];
if (msn) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"msnim://"]];
}
else {
UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle: #"MSN not Installed" message: nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
but its not working.
Am i using wrong custom url for MSN????
If yes,then what is the url scheme for MSN.
I just wrote a iOS app to test the UIAlertView. When I ran it, the UIAlertView just appear with the screen went dark first without the UIAlertView, and "a long time" later ,the UIAlertView appeared. This happens on both Simulator and iPhone (IOS 4.2). I don't know why, Please help me, thanks.
Description:(You can also download the Project HERE)
Its a very simple View based app With 3 Classes: AppDelgate ViewControler and a TestOperation which implement NSOperation;
AppDelegate was just the one produced by XCode;
TestOperation.h:
#import <Foundation/Foundation.h>
#protocol TestOperationDelegate
- (void)didFinishTestOperaion;
#end
#interface TestOperation : NSOperation {
id <TestOperationDelegate> delegate;
}
#property (nonatomic, assign) id <TestOperationDelegate> delegate;
#end
TestOperation.m
#import "TestOperation.h"
#implementation TestOperation
#synthesize delegate;
- (void)main {
[delegate didFinishTestOperaion];
}
#end
ViewContoller.m
- (void)viewDidLoad {
[super viewDidLoad];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
TestOperation *testOperation = [[TestOperation alloc] init];
testOperation.delegate = self;
[queue addOperation:testOperation];
[testOperation release];
}
- (void)didFinishTestOperaion {
NSLog(#"start uialertview");
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Oops!" message:#"Here's the UIAlertView"
delegate:self cancelButtonTitle:#"Confirm" otherButtonTitles:nil];
[alert show];
[alert release];
}
//Solved!! Use performSelectorOnMainThread to make
the UI run on Main Thread
Solved!! Use performSelectorOnMainThread to make the UI run on Main Thread
[alert performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:NO];
What are you attempting to test in the UIAlertView? If you simply called the UIAlertView from viewDidAppear: in your ViewController, is the UIAlertView displayed rapidly as expected?
I expect that the issues you are having are related to how you are calling the UIAlertView, and that the UIAlertView is being displayed before the UIView controlled by your ViewController has appeared.