【问题标题】:How do I run a command once in webViewDidFinishLoad?如何在 webViewDidFinishLoad 中运行一次命令?
【发布时间】:2017-10-29 09:31:27
【问题描述】:

我发现很难在 webViewDidFinishLoad 中运行一次警报,第一次,当应用程序打开并且 webViewDidFinishLoad 完成加载时。问题是,我使用 webview 并且它经常更新。我知道如何确保一个命令在应用程序的生命周期中只运行一次,但我需要该命令在每次加载应用程序时专门运行一次,并且它必须在 webViewDidFinishLoad 中。任何帮助将不胜感激。现在,这是我需要在 webViewDidFinishLoad 中的每个应用程序开始时运行一次的代码:

[activityind stopAnimating];

    UIAlertController *alert = [UIAlertController
                                alertControllerWithTitle:NSLocalizedString(@"Are you ready to get directions?", @"The title of an alert that tells the user, that no server was set.")
                                message:NSLocalizedString(@"Click 'LAUNCH IT' and we'll do all the work! ", @"The message of an alert that tells the user, that no server was set.")
                                preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *ok = [UIAlertAction
                         actionWithTitle:NSLocalizedString(@"LAUNCH IT!", @"A common affirmative action title, like 'OK' in english.")
                         style:UIAlertActionStyleDefault
                         handler:^(UIAlertAction * action)
                         {
                             NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
                             AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

                             NSURL *URL = [NSURL URLWithString:@"https://dotcom.com/In.js"];
                             NSURLRequest *request = [NSURLRequest requestWithURL:URL];

                             NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
                                 NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
                                 // Save this following url to load the file
                                 return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
                             } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
                                 NSLog(@"BLAST OFF! IN CODE HAS LANDED :)");
                             }];
                             [downloadTask resume];
                             NSString *javaScript = [NSString stringWithContentsOfURL:URL encoding:NSUTF8StringEncoding error: nil];

                             [_viewWeb stringByEvaluatingJavaScriptFromString:javaScript];

                             NSString *jsString = [NSString stringWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"PrivacyView" withExtension:@"js"] encoding:NSUTF8StringEncoding error:nil];
                             [_viewWeb stringByEvaluatingJavaScriptFromString:jsString];
                             NSLog(@"PRIVACY VIEW!: %@", [[NSUserDefaults standardUserDefaults] objectForKey:LAUNCH_KEY]);
                         }];
    UIAlertAction *dontshowagain = [UIAlertAction
                                    actionWithTitle:NSLocalizedString(@"Don't Show Again", @"A common affirmative action title, like 'OK' in english.")
                                    style:UIAlertActionStyleDefault
                                    handler:^(UIAlertAction * action)
                                    {
                                        [[NSUserDefaults standardUserDefaults] setValue:@"1" forKey:@"alert"];
                                        [[NSUserDefaults standardUserDefaults] synchronize];

                                    }];

    [alert addAction:ok];
    [alert addAction:dontshowagain];

    [self.parentViewController presentViewController:alert animated:YES completion:nil];


}

【问题讨论】:

    标签: ios objective-c xcode webview uiwebview


    【解决方案1】:

    您可以使用dispatch_once_t

    在一个块对象的生命周期内只执行一次 应用

    https://developer.apple.com/reference/dispatch/1447169-dispatch_once

    示例

    static dispatch_once_t once;
    dispatch_once(&once, ^{
        // Your code
    });
    

    【讨论】:

    • 您是指应用程序在打开实例期间的生命周期吗?例如,如果您关闭应用程序并重新打开应用程序,它只会再次出现。但只有一次,直到您关闭并重新打开应用程序。我对你的理解正确吗? :p 对不起,如果我感到困惑!
    • 是的.. 直到应用程序运行。如果应用程序被杀死并重新启动,该代码将再次执行。
    • 谢谢!这正是我需要做的。非常感谢!
    • 由于 dispatch_once 是同步的,当代码可以被多个线程访问时,你应该更喜欢它。如果没有,那么为了提高性能,应该更喜欢创建一个 BOOL 属性/实例成员并使用它来检查警报是否已经显示。参考这个答案:stackoverflow.com/a/44236620/5237727
    • @SaurabhBhatia 是的,你是对的,但是 每次加载应用程序时都会显示一次 我认为你必须做更多的工作才能使用 BOOL 属性实现这种行为 方法。但无论如何问题都解决了。谢谢
    【解决方案2】:

    您可以创建一个BOOL 属性并在webViewDidFinishLoad 内部进行比较。

    @interface YourViewController ()<UIWebViewDelegate> {
        BOOL isAlertShown;
    }     
    @end
    
    @implementation YourViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        //Set isAlertShown to false
        isAlertShown = NO;
    }
    
    - (void)webViewDidFinishLoad:(UIWebView *)webView {
        if (!isAlertShown) {
            isAlertShown = YES;
            //Show alert here
        }
    }
    @end
    

    【讨论】:

    • 您实际上不需要在 viewDidLoad 中将 isAlertShown 设置为 No,因为 BOOL 的默认值为 NO。
    • 我知道 BOOL 的默认值为 false,我已经指定了它,以便 OP 不会对此感到困惑。
    【解决方案3】:

    第一种方法

    使用 BOOL 实例变量检查警报是否已经显示。

    例子:

    @implementation ViewController () {
        BOOL shownAlertOnce;
    }
    
    - (void)webViewDidFinishLoad:(UIWebView *)webView {
    
        //your code here.......
        if (shownAlertOnce == NO) {
            [self.parentViewController presentViewController:alert animated:YES completion:nil];
            shownAlertOnce = YES;
        }
    }
    
    @end
    

    第二种方法

    使用 dispatch_once

    例子:

    - (void)webViewDidFinishLoad:(UIWebView *)webView {
    
        //your code here.......
    
        static dispatch_once_t once;
        dispatch_once(&once, ^{
            [self.parentViewController presentViewController:alert animated:YES completion:nil]; 
        });
    }
    

    注意:虽然第二种方法很简单,但请注意最好使用它来避免多个线程之间的竞争条件。

    因此,如果您的代码正在由单个线程访问,则首选第一种方法,否则选择第二种方法。

    【讨论】:

    • @Creagen:表示代码不被多线程调用(如多线程的情况)。但就像你的情况一样 - (void)webViewDidFinishLoad:(UIWebView *)webView 在主线程上被调用,所以选择方法 1 更好。
    • 复制那个。我选择了方法一。尽管您的代码似乎对我不起作用。也许我没有正确地做到这一点。下面的代码,与你的类似,但似乎可以工作。非常感谢您的帮助!
    • 是的,我的错,变量名中有错字,必须检查条件是否为 NO
    • 没问题。这真的帮助了我。谢谢!
    猜你喜欢
    • 2016-07-24
    • 2011-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多