简体   繁体   English

UIWebView loadRequest未在自定义函数中触发

[英]UIWebView loadRequest not firing in custom function

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. 多年来,我从StackOverflow获得了许多快速解决问题的方法。

I'm new to Object C and iOS programming, but starting with what I think should be a super simple app. 我是Object C和iOS编程的新手,但从我认为应该是一个超级简单的应用程序开始。 It receives a push notification (which works fine) and redirects to a webpage when it has figured out its appid. 它会收到一个推送通知(工作正常),并在确定其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. 问题是,虽然我可以将UIWebView放入viewDidLoad中的loadRequest中,但相同的代码将不会在另一个函数中执行。

Here's the code: 这是代码:

AppDelegate.m 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: ViewController.h:

//  UFViewController.h
#import <UIKit/UIKit.h>

@interface UFViewController : UIViewController
- (void)handleOpenURL:(NSURL *)url;
@end

ViewController.m: 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. 当按此处的代码运行时,雅虎页面从didload中的loadRequest中显示,但是handleOpenURL仍然不会触发。 If I comment out the loadRequest out of viewDidLoad, a blank page shows up and the handleOpenURL still does not fire. 如果我从viewDidLoad中注释掉loadRequest,则会显示空白页面,并且handleOpenURL仍然不会触发。

Here's the debug sequence. 这是调试顺序。 viewDidLoad fires and completes before receiving the AppID and manually firing handleOpenURL: 在接收到AppID并手动触发handleOpenURL之前,viewDidLoad触发并完成:

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? 您确定这里只有UFViewController一个实例吗?

-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. -didRegisterForRemoteNotificationsWithDeviceToken在局部变量中初始化了一个新的Web视图控制器,但我看不到它如何显示给用户-创建vc后,您不会对其进行任何操作。

Here's what I think might be happening: 我认为这可能正在发生:

  1. App starts. 应用启动。 You have an instance of UFViewController in a storyboard. 您在情节UFViewController中有一个UFViewController实例。 It loads, its -viewDidLoad is called, the log statements print and the webview loads correctly. 它加载,调用-viewDidLoad ,打印日志语句,并正确加载webview。
  2. A little later, the -didRegisterForRemoteNotificationsWithDeviceToken: method is called. 稍后,将-didRegisterForRemoteNotificationsWithDeviceToken:方法。 This instantiates a UFViewController , and calls the -handleOpenUrl method on it. 这将实例化UFViewController ,并在其上调用-handleOpenUrl方法。 The -handleOpenURL log methods fire. -handleOpenURL日志方法启动。 However, this controller has not been loaded into the view hierarchy, so its view is never instantiated, and its -viewDidLoad is never called. 但是,此控制器尚未加载到视图层次结构中,因此永远不会实例化其视图,也永远不会调用其-viewDidLoad This means that the webview that the -loadRequest: is being called on is nil . 这意味着正在调用-loadRequest:-loadRequest:nil In Objective-C, it is valid to send a message to nil - unlike most other languages, no error or exception will be thrown. 在Objective-C中,将消息发送为nil是有效的-与大多数其他语言不同,不会引发任何错误或异常。 Instead, absolutely nothing happens, hence no web load. 相反,绝对没有任何反应,因此没有Web负载。 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. UFViewController中的-handleOpenUrl仅由方法内的局部变量引用,因此,在方法完成时,对该方法的最后一个强引用将消失并被释放。

To check this is correct: 要检查是否正确:

- NSLog(@"%@",[self description]); NSLog(@"%@",[self description]); in your vc methods - this will log the address of the objects and tell you whether they are the same. 在您的vc方法中-这将记录对象的地址并告诉您它们是否相同。

- NSLog the web controller's view, to check whether it's nil in handleOpenURL - NSLog网络控制器的视图,以检查它是否是nilhandleOpenURL

To solve your problem, I suggest using an NSNotification posted by the AppDelegate and listened for by the UFViewController that is fully instantiated. 为了解决您的问题,我建议使用AppDelegate发布的NSNotification并由完全实例化的UFViewController监听。 So in the vc you'd do: 因此,在vc中,您可以执行以下操作:

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(handleRegistration:) name:@"HandleRegistrationNotification" object:nil];

and then implement the handleRegistration method: 然后实现handleRegistration方法:

-(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) (这一点很重要,因为否则在取消分配vc时可能会崩溃)

Then, in the -didRegisterForRemoteNotifications: method: 然后,在-didRegisterForRemoteNotifications:方法中:

[[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. 如果您需要通过通知传递任何信息(例如url),则可以使用object参数-在vc上通过NSNotification参数的object属性调用的方法中可以访问该参数。

Full docs on notifications in Objective-C can be found here . 有关Objective-C中通知的完整文档,请参见此处

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. 有几点要点-将视图控制器之类的东西theView而不是theViewController通常是一个坏主意,因为其他人(或您六个月后的时间)最终会认为它们是UIView Also the webview property should not start with a capital letter- that's generally only used for class names. 同样,webview属性不应以大写字母开头-通常仅用于类名。

This should be called, "How to call a storyboard viewcontroller method from the appdelegate". 这应该称为“如何从appdelegate调用情节提要viewviewler方法”。 And the answer is: 答案是:

in AppDelegate.m: 在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. 区别在于我的原始代码将一个新的UFViewController对象实例化为一个局部变量,而正确的代码只是获取了已在情节提要中创建的视图控制器的句柄并调用了它的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM