1

Is there a way to get the estimated time of On Demand Resources download?

I'd like to show an alert until they are all downloaded.

[alertDownload showCustom:self image:[UIImage imageNamed:@"icon.jpg"] 
                               color:[UIColor blueColor] 
                               title:@"Download..." 
                               subTitle:@"Download in progress" 
                               closeButtonTitle:nil 
                               duration: ODR ETA];

Right now I have

if (request1.progress.fractionCompleted < 1) {
 // code above
}

but the alert will not automatically disappear when the download is completed, it will look at the duration of the alert.

fabdurso
  • 2,366
  • 5
  • 29
  • 55
  • What API are you using to do the download? Does it use HTTP and if so is the `contentLength` provided in the response? – trojanfoe Mar 23 '16 at 20:12
  • hey, I'm using On Demand Resources https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/On_Demand_Resources_Guide/Managing.html#//apple_ref/doc/uid/TP40015083-CH4-SW1 – fabdurso Mar 23 '16 at 20:14
  • OK so that page shows code that uses a notification to track download progress. Have you tried it? – trojanfoe Mar 23 '16 at 20:16
  • yes, I can access to progress (it is a float between o and 1), but I don't think there's a way to get the estimated time of download – fabdurso Mar 23 '16 at 20:17
  • Cool; you should be able to work it out from that. For example if it's at 0.2 after 10 seconds, that would mean there is an estimated 40 seconds left. `float timeLeft = (elapsedTime / fractionComplete) * (1.0 - fractionComplete);`. – trojanfoe Mar 23 '16 at 20:18
  • yes, can work on that! but I can I get the elapsed time after x seconds? – fabdurso Mar 23 '16 at 20:23
  • Using: `NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate];` and then within the notification handler: `NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate]; NSTimeInterval elapsed = now - startTime;`. – trojanfoe Mar 23 '16 at 20:25
  • you can write an answer if you want, sure it is gonna work! – fabdurso Mar 23 '16 at 20:26

2 Answers2

1

OK, if you can get the fraction complete value and you can measure time, then you know how long you have left.

When you start the download, record the start time in an instance variable:

@interface MyClass () {
    NSTimeInterval _downloadStartTime;
}

- (void)startDownload
{
    ...
    _downloadStartTime = [NSDate timeIntervalSinceReferenceDate];
    ...
}

and then in your notification handler, where you receive the fraction complete, use:

double fractionComplete = 0.2;    // For example
if (fractionComplete > 0.0) {     // Avoid divide-by-zero
    NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
    NSTimeInterval elapsed = now - _downloadStartTime;
    double timeLeft = (elapsedTime / fractionComplete) * (1.0 - fractionComplete);
}

Note: I have not tackled your displaying of the alert dialog and I don't think the logic you are using will work (you don't want to display a new alert every time you get an update). I am avoiding this whole area and concentrating on the ETA logic only.

trojanfoe
  • 120,358
  • 21
  • 212
  • 242
  • @fabersky Note: there was an error in my original `elapsed` calculation. – trojanfoe Mar 23 '16 at 20:30
  • ok ;) but one question: I have to show the alert and set its duration when the download starts, so how can I know the time left before the download starts? – fabdurso Mar 23 '16 at 20:33
  • 1
    @fabersky I don't know TBH. If there is some way to update the text within an already displayed alert view then that is the way to go. Otherwise avoid the alert view altogether and use some other view technology which you have full control over. – trojanfoe Mar 23 '16 at 20:34
  • well, I can work with this! just one more thing:don't you think it would be better to update the timeLeft every 0.2 of the fractionComplete for example? to have a more precise estimation – fabdurso Mar 23 '16 at 20:56
  • thanks @trojanfoe. what do you think about the answer? – fabdurso Mar 23 '16 at 22:05
  • btw, sorry if I ask: do you have any tip on this? http://stackoverflow.com/questions/36154516/nsbundleresourcerequest-bundlepath#comment60008585_36154516 – fabdurso Mar 23 '16 at 22:10
0

So, also thanks to the help of @trojanfoe, I achieved this way.

Basically, I'm not setting the alert duration when creating the alert, but I'm updating it depending on the download progress. Until the download finished, I'm repeatedly setting the duration to 20.0f . Then, when the download completed, I'm setting the duration to 1.0f (so the alert will disappear in 1 second).

NSTimeInterval _alertDuration;

- (void)viewDidLoad {
 [request1 conditionallyBeginAccessingResourcesWithCompletionHandler:^
                                           (BOOL resourcesAvailable) 
  {
    if (resourcesAvailable) {
     // use it
    } else {
       [request1 beginAccessingResourcesWithCompletionHandler:^
                                           (NSError * _Nullable error) 
     {
           if (error == nil) {
               [[NSOperationQueue mainQueue] addOperationWithBlock:^ {
                   [alertDownload showCustom:self image:[UIImage 
                           imageNamed:@"icon.jpg"] 
                           color:[UIColor blueColor] 
                           title:@"Download..." 
                           subTitle:@"Download in progress" 
                           closeButtonTitle:nil 
                           duration:_alertDuration];
                    }
                ];
            } else {
             // handle error
            }
       }];
    }
}];

.

- (void)observeValueForKeyPath:(nullable NSString *)keyPath 
                 ofObject:(nullable id)object 
                 change:(nullable NSDictionary *)change 
                 context:(nullable void *)context {
 if((object == request1.progress) && [keyPath 
                 isEqualToString:@"fractionCompleted"]) {
    [[NSOperationQueue mainQueue] addOperationWithBlock:^ {
     if(request1.progress.fractionCompleted == 1) {
         _alertDuration = 1.0f;
     } else {
         _alertDuration = 20.0f;
     }
    }];
 }
}
fabdurso
  • 2,366
  • 5
  • 29
  • 55