Home > Software design >  Getting date from web, returns nil
Getting date from web, returns nil

Time:09-16

Doing a check to get the current time and date from Google. The first option works although not the best way to do this as it's using a depreciated method and waiting for everything to finish with the synchronous method is not good UX.

-(NSDate*)timeAndDateFromWeb{
    

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
                                    initWithURL:[NSURL URLWithString:@"https://google.co.uk"]];
    [request setHTTPMethod:@"GET"];
    NSHTTPURLResponse *httpResponse = nil;
    [NSURLConnection sendSynchronousRequest:request returningResponse:&httpResponse error:nil];
    NSString *dateString = [[httpResponse allHeaderFields] objectForKey:@"Date"];
    DebugLog(@" *** GOOGLE DATE:  %@ ****",dateString);
    if (httpResponse){
        hasDataConnection = YES;
       
    }
    else{
        hasDataConnection = NO;
       
    }
    
    // Convert string to date object
    NSDateFormatter *dateformatted = [NSDateFormatter new];
    [dateformatted setDateFormat:@"E, d MMM yyyy HH:mm:ss zzz"];
    NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en"];
    [dateformatted setLocale:locale];
    
    return [dateformatted dateFromString:dateString];
}

Trying to adapt it is almost there although I'm returning nil for my date string: [dateformatted dateFromString:dateString];

    NSURL *url = [NSURL URLWithString:@"https://google.co.uk"];
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    NSHTTPURLResponse *httpResponse = nil;
    NSString *dateString = [[httpResponse allHeaderFields] objectForKey:@"Date"];
    [NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
      if (error) {
          hasDataConnection = NO;
          //NSLog(@"\n\n ----> Not connected Error,%@", [error localizedDescription]);
      }
      else {
          //NSLog(@"\n\n -----> connected:  %@", [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]);
          hasDataConnection = YES;
       
          
      }
    }];
    
    
    // Convert string to date object
    NSDateFormatter *dateformatted = [NSDateFormatter new];
    [dateformatted setDateFormat:@"E, d MMM yyyy HH:mm:ss zzz"];
    NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en"];
    [dateformatted setLocale:locale];

    DebugLog(@" *** GOOGLE DATE:  %@ ****",[dateformatted dateFromString:dateString]);
    
    return [dateformatted dateFromString:dateString];

CodePudding user response:

When you're switching from sync to async, can't return value the same way as before.

When you call sendAsynchronousRequest method, it starts a background task, but your thread continues work instantly. That's why both httpResponse and dateString are null.

So instead of that you should change your return type to void, because you can't return result instantly, and add a callback, which will be run when the job is done. And process your formatting in the completion of the task too:

- (void)timeAndDateFromWeb:(void (^)(NSDate *))completion {
    NSURL *url = [NSURL URLWithString:@"https://google.co.uk"];
    NSURLSessionTask *task = [NSURLSession.sharedSession
     dataTaskWithURL:url
     completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
//            hasDataConnection = NO;
            //NSLog(@"\n\n ----> Not connected Error,%@", [error localizedDescription]);
        }
        else if ([response isKindOfClass:NSHTTPURLResponse.class] ) {
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            NSString *dateString = [[httpResponse allHeaderFields] objectForKey:@"Date"];
            
            // Convert string to date object
            NSDateFormatter *dateformatted = [NSDateFormatter new];
            [dateformatted setDateFormat:@"E, d MMM yyyy HH:mm:ss zzz"];
            NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en"];
            [dateformatted setLocale:locale];
            
//            DebugLog(@" *** GOOGLE DATE:  %@ ****",[dateformatted dateFromString:dateString]);
            
            completion([dateformatted dateFromString:dateString]);
            //NSLog(@"\n\n -----> connected:  %@", [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]);
//            hasDataConnection = YES;
            
            
        }
    }];
    [task resume];
}

And so the result of this method will be returned to the block, same as result of the background task.

Don't forget, that it will be called on the background thread, same as the download task completion block. So if you wanna change some UI you need to move back to the main thread:

[self timeAndDateFromWeb:^(NSDate *date) {
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"%@", date);
        // UI changes
    });
}];

Alternatively you can move it to the main thread inside your function, right before returning the result:

NSDate *date = [dateformatted dateFromString:dateString];
dispatch_async(dispatch_get_main_queue(), ^{
    completion(date);
});
  • Related