0
votes

I'm finding it hard to run an alert in webViewDidFinishLoad once, the first time, when the app is opened and the webViewDidFinishLoad is finished loading. The problem being, I use a webview and it's updating frequently. I know how to make sure a command is run only once in an apps lifetime but I need the command to run specifically ONCE every time the app is loaded and it HAS TO BE in webViewDidFinishLoad. Any help would be greatly appreciated. Right now, this is the code I need to run once at the beginning of every app in the 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];


}
3

3 Answers

2
votes

You can use dispatch_once_t.

Executes a block object once and only once for the lifetime of an application

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

Example

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

1st APPROACH

Use a BOOL instance variable to check whether the alert has been shown already or not.

Example:

@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

2nd APPROACH

Use dispatch_once

Example:

- (void)webViewDidFinishLoad:(UIWebView *)webView {

    //your code here.......

    static dispatch_once_t once;
    dispatch_once(&once, ^{
        [self.parentViewController presentViewController:alert animated:YES completion:nil]; 
    });
}

Note: Although 2nd approach is an easy one but take care that it should ideally be used to avoid race condition between multiple threads.

So, if your code is being accessed by a single thread, then prefer 1st approach, else 2nd.

1
votes

You can make one BOOL property and comparing it inside 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