First, thanks to everyone that takes the time to answer questions. I have gotten so many quick answers to problems over the years from StackOverflow.
I'm new to Object C and iOS programming, but starting with what I think should be a super simple app. It receives a push notification (which works fine) and redirects to a webpage when it has figured out its appid.
The problem is that the while I can get my UIWebView to loadRequest in the viewDidLoad, the same code will not execute in another function.
Here's the code:
AppDelegate.m
// UFAppDelegate.m
#import "UFAppDelegate.h"
#import "UFViewController.h"
@implementation UFAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Add registration for remote notifications
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationType)(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
return YES;
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {
// ....
NSString *urlString = @"http://www.google.com";
NSURL *url = [NSURL URLWithString:urlString];
NSLog(@"Navigating to URL: %@", url);
UFViewController *theview = [[UFViewController alloc] init];
[theview handleOpenURL:url];
}
@end
ViewController.h:
// UFViewController.h
#import <UIKit/UIKit.h>
@interface UFViewController : UIViewController
- (void)handleOpenURL:(NSURL *)url;
@end
ViewController.m:
// UFViewController.m
#import "UFViewController.h"
@interface UFViewController ()
@property (weak, nonatomic) IBOutlet UIWebView *UFHWebView;
- (void)handleOpenURL:(NSURL *)url;
@end
@implementation UFViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"UFViewController.viewDidLoad started");
// This block that assigns the url and loads it works perfectly here... but not down below.
NSString *urlString = @"http://search.yahoo.com/";
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[_UFHWebView loadRequest:requestObj];
NSLog(@"UFViewController.viewDidLoad completed");
}
- (void)handleOpenURL:(NSURL *)url
{
NSLog(@"UFViewController.handleOpenURL started");
NSLog(@"url = %@",url);
// The below loadRequest does not load!
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[_UFHWebView loadRequest:requestObj];
NSLog(@"UFViewController.handleOpenURL completed");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
NSLog(@"Error - %@", error);
}
- (BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
return YES;
}
@end
When run as coded here, the yahoo page shows from the loadRequest in the didload, but the handleOpenURL one still does not fire. If I comment out the loadRequest out of viewDidLoad, a blank page shows up and the handleOpenURL still does not fire.
Here's the debug sequence. viewDidLoad fires and completes before receiving the AppID and manually firing handleOpenURL:
2013-12-12 15:28:32.606 UF[5896:60b] UFViewController.viewDidLoad started
2013-12-12 15:28:32.608 UF[5896:60b] UFViewController.viewDidLoad completed
2013-12-12 15:28:32.765 UF[5896:60b] Navigating to URL: http://www.google.com
2013-12-12 15:28:32.769 UF[5896:60b] UFViewController.handleOpenURL started
2013-12-12 15:28:32.773 UF[5896:60b] url = http://www.google.com
2013-12-12 15:28:32.775 UF[5896:60b] UFViewController.handleOpenURL completed
Any help appreciated!
Are you sure you have just one instance of UFViewController
here?
-didRegisterForRemoteNotificationsWithDeviceToken
initializes a new web view controller in a local variable, but I can't see how it's getting shown to the user - you aren't doing anything with the vc once it's created.
Here's what I think might be happening:
UFViewController
in a storyboard. It loads, its -viewDidLoad
is called, the log statements print and the webview loads correctly. -didRegisterForRemoteNotificationsWithDeviceToken:
method is called. This instantiates a UFViewController
, and calls the -handleOpenUrl
method on it. The -handleOpenURL
log methods fire. However, this controller has not been loaded into the view hierarchy, so its view is never instantiated, and its -viewDidLoad
is never called. This means that the webview that the -loadRequest:
is being called on is nil
. In Objective-C, it is valid to send a message to nil
- unlike most other languages, no error or exception will be thrown. Instead, absolutely nothing happens, hence no web load. The UFViewController
in -handleOpenUrl
is only referred to by a local variable within the method, so when the method completes, the last strong reference to it vanishes and it is released. To check this is correct:
- NSLog(@"%@",[self description]);
in your vc methods - this will log the address of the objects and tell you whether they are the same.
- NSLog
the web controller's view, to check whether it's nil
in handleOpenURL
To solve your problem, I suggest using an NSNotification
posted by the AppDelegate
and listened for by the UFViewController
that is fully instantiated. So in the vc you'd do:
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(handleRegistration:) name:@"HandleRegistrationNotification" object:nil];
and then implement the handleRegistration
method:
-(void)handleRegistration:(NSNotification*)notification
{
//your handleOpenUrl code
}
and also
-(void)dealloc
{
[[NSNotificationCenter defaultCenter]removeObserver:self name:@"HandleRegistrationNotification" object:nil];
}
(this bit is important because otherwise you may get a crash when the vc is dealloc'd)
Then, in the -didRegisterForRemoteNotifications:
method:
[[NSNotificationCenter defaultCenter]postNotificationName:@"HandleRegistrationNotification" object:nil];
If you need to pass any information through the notification (eg urls) you can use the object
parameter - this is accessible in the method called on the vc via the object
property of the NSNotification
parameter.
Full docs on notifications in Objective-C can be found here .
Some minor points - it's generally a bad idea to call your view controllers things like theView
rather than theViewController
since other people (or you in 6 months time) will end up thinking they're UIView
s. Also the webview property should not start with a capital letter- that's generally only used for class names.
This should be called, "How to call a storyboard viewcontroller method from the appdelegate". And the answer is:
in AppDelegate.m:
#import "UFViewController.h"
...
UFViewController *rootViewController = (UFViewController*)self.window.rootViewController;
[rootViewController handleOpenURL:url];
In my code snippets above, this means replacing these lines
UFViewController *theview = [[UFViewController alloc] init];
[theview handleOpenURL:url];
with the ones above. The difference is my original code instantiates a new UFViewController object into a local variable, while the correct code just gets a handle to the view controller already created in the storyboard and calls its method.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.