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

时间:2013-12-13 15:40:44

标签: ios iphone objective-c uiwebview

首先,感谢每个人花时间回答问题。多年来,我从StackOverflow获得了很多问题的快速解答。

我是Object C和iOS编程的新手,但从我认为应该是一个超级简单的应用程序开始。它接收推送通知(工作正常)并在找到其appid时重定向到网页。

问题是,虽然我可以在viewDidLoad中将我的UIWebView加载到loadRequest,但相同的代码不会在另一个函数中执行。

以下是代码:

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

当在此处编码运行时,yahoo页面显示来自didload中的loadRequest,但handleOpenURL仍然不会触发。如果我从viewDidLoad中注释掉loadRequest,则会显示一个空白页面,而handleOpenURL仍然不会触发。

这是调试序列。 viewDidLoad在收到AppID并手动触发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

任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:0)

您确定此处只有一个UFViewController个实例吗?

-didRegisterForRemoteNotificationsWithDeviceToken在局部变量中初始化一个新的Web视图控制器,但我看不出它是如何显示给用户的 - 一旦创建了vc,你就没有做任何事情。

以下是我认为可能会发生的事情:

  1. 应用程序启动。您在故事板中有UFViewController的实例。它加载,调用-viewDidLoad,打印日志语句并正确加载webview。
  2. 稍后,调用-didRegisterForRemoteNotificationsWithDeviceToken:方法。这会实例化UFViewController,并在其上调用-handleOpenUrl方法。触发-handleOpenURL日志方法。但是,此控制器尚未加载到视图层次结构中,因此其视图从未实例化,并且永远不会调用其-viewDidLoad。 这意味着正在调用-loadRequest:的网页浏览量为nil。在Objective-C中,向nil发送消息是有效的 - 与大多数其他语言不同,不会抛出任何错误或异常。相反,绝对没有任何反应,因此没有网络负载。 UFViewController中的-handleOpenUrl仅由方法中的局部变量引用,因此当方法完成时,对它的最后一个强引用将消失并释放。
  3. 要检查这是否正确:

    你的vc方法中的

    - NSLog(@"%@",[self description]); - 这将记录对象的地址并告诉你它们是否相同。

    - NSLog网络控制器的视图,检查nil中的handleOpenURL是否为NSNotification

    要解决您的问题,我建议您使用AppDelegate发布的UFViewController,并由完全实例化的[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(handleRegistration:) name:@"HandleRegistrationNotification" object:nil]; 进行聆听。所以在你做的vc中:

    handleRegistration

    然后实现-(void)handleRegistration:(NSNotification*)notification { //your handleOpenUrl code } 方法:

    -(void)dealloc
    {
        [[NSNotificationCenter defaultCenter]removeObserver:self name:@"HandleRegistrationNotification" object:nil];
    }
    

    以及

    -didRegisterForRemoteNotifications:

    (这一点很重要,否则你可能会在vc被dealloc'd时崩溃)

    然后,在[[NSNotificationCenter defaultCenter]postNotificationName:@"HandleRegistrationNotification" object:nil]; 方法中:

    object

    如果您需要通过通知传递任何信息(例如网址),您可以使用object参数 - 这可以通过NSNotification theView属性在vc上调用的方法访问1}}参数。

    可以找到Objective-C中有关通知的完整文档here

    一些小问题 - 将视图控制器调用为theViewController而不是UIView通常是一个坏主意,因为其他人(或者您在6个月时间内)最终会认为他们是{{1}} {1}}。 webview属性也不应该以大写字母开头 - 通常只用于类名。

答案 1 :(得分:0)

这应该被称为“如何从appdelegate调用storyboard viewcontroller方法”。答案是:

AppDelegate.m中的

#import "UFViewController.h"
...
UFViewController *rootViewController = (UFViewController*)self.window.rootViewController;
[rootViewController handleOpenURL:url];

在上面的代码片段中,这意味着要替换这些行

UFViewController *theview = [[UFViewController alloc] init];
[theview handleOpenURL:url];

与上述。不同之处在于我的原始代码将新的UFViewController对象实例化为局部变量,而正确的代码只是获取已经在故事板中创建的视图控制器的句柄并调用其方法。