0

Here is the thing, I got some code, that does not execute (the compiler run the code but does not do anything)... Here is the code... Using NSURLSessionDelegate and [NSOperationQueue mainQueue] addOperationWithBlock

@interface tablaPosViewController : UIViewController  <NSURLSessionDelegate>

@end

@implementation tablaPosViewController ()

- (void)viewDidLoad
{
//some code to set the view, labels and stuff

[self downloadTheHTMLdata] // this code download some data from WWW

}

- (void)downloadTheHMTLdata
{
//some code to set the session using an object

[object.downloadTask resume]; //Begins the download

}

- (void)toFixTablaPosiciones
{
//some code to do with the downloaded data from WWW (and HTML sheet)
//here, parse the HTML Sheet, and put some data into an Arrays, and another public vars

//call another method
[self PutTheDataInLabel];

}

- (void)PutTheDataInLabel
{
//some code to put all the data in every label
//take the public vars that was set in the previous method, and do some code with it
//and put the info into the labels

//call another method
[self MoreStuff];

}

- (void)MoreStuff
{

//some code..

}


-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
    //When the download finish this method fire up!

    //this is to copy file from tmp folder to Docs folder
    if ([fileManager fileExistsAtPath:[destinationURL path]])
    {
        [fileManager removeItemAtURL:destinationURL error:nil];
    }
    BOOL success = [fileManager copyItemAtURL:location       //TMP download folder
                                        toURL:destinationURL //Documents folder 
                                        error:&error];
     //HERES COMES THE TROUBLE!!!
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [self toFixTablaPosiciones]; //Call this method, that has other method calls!
         }];

}
@end

UPDATE

This another code put methods in the queue...

-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{
    AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
    [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
        if ([downloadTasks count] == 0) {
            if (appDelegate.backgroundTransferCompletionHandler != nil) {
                void(^completionHandler)() = appDelegate.backgroundTransferCompletionHandler;
                appDelegate.backgroundTransferCompletionHandler = nil;
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                    completionHandler();
                }];
            }
        }
    }];
}

The issue is when the download file ends, calls -(void)URLSession:(NSURLSession *)session downloadTask:... method and I wait to [[NSOperationQueue mainQueue] addOperationWithBlock:^{... runs everything... but it does not execute anythig of [self toFixTablaPosiciones]!!.

I ran the code step by step, and I see how the compiler runs all the code, method over method... but the view never updates, runs but not executes, simply does do anything, and I have an Activity Indicator, and want to stop it, but the lablels stills with de dummie data and the Activity Indicator never stops and never disappears. In a previous view, I download another file using a similiar class, and downloads very quickly. Going to this view/class try to perform the download and this is the thing...

Hoping any body can help me and send me any advice. Thanks!

David H
  • 40,852
  • 12
  • 92
  • 138
Elbert Villarreal
  • 1,696
  • 1
  • 11
  • 22
  • 1
    Are you updating your UI on the main thread? – Joel Sep 01 '14 at 15:56
  • Yes, this is the complete class that work's with the view and I use the viewDidLoad to set the view with dummie data and after the download finish update all the labels with the right data on the main thread (what the user is seeing) – Elbert Villarreal Sep 01 '14 at 16:03
  • The main operation queue is a serial queue. There can only be one operation running on it at one time. Is this the only place that you add an operation to that queue? Or do you add other operations? Do any of them run for a long time or block waiting for something else to complete? – Ken Thomases Sep 01 '14 at 16:54
  • @KenThomases Yes, this is the only place that I can put that code, because, I need to run it when the HTML file is downloaded, and I need to do it in background to avoid any blocking of the app. – Elbert Villarreal Sep 01 '14 at 17:17
  • @Joel Yes, I need to update the UI from background, and in the `viewDidLoad` (that I guess is in the main thread, and assuming Im right) set all the labels, and using `[NSOperationQueue mainQueue] addOperationWithBlock:` in `-(void)URLSession:(NSURLSession *)session downloadTask:` I try to update the labels from background. – Elbert Villarreal Sep 01 '14 at 17:20
  • I didn't ask if there was someplace else you could put this code. I asked if there was some other part of your code which also adds operations to the main operation queue and if some such operation could still be running. – Ken Thomases Sep 01 '14 at 18:35
  • @KenThomases I will update the post answer your question... and there is another class that control another view, its almost the same, but in this other class, the App just download an Info sheet that does not need any action, just download, and this class (that one above) make all the hard work, and this is the first because will be another class after this... – Elbert Villarreal Sep 01 '14 at 20:26
  • OK, so now the question is: what does that completion handler do? Is it doing something like running a modal dialog? Or anything else long-running? – Ken Thomases Sep 01 '14 at 23:06
  • Judy parse some data from the html file downloaded. Set viewDidLoad, end to finish and when the download finish URLSession : downloadTask notifies it finish downloading and comes the method who parade the data could last 2 or 10 seconds doing that meanwhile the user sees an Activity Indicator on the view... When finish parsing the data, stops the activity indicator and reload the labels with the info – Elbert Villarreal Sep 01 '14 at 23:13
  • @KenThomases "Judy" is for "Just" sorry the typo... – Elbert Villarreal Sep 02 '14 at 16:09
  • @KenThomases Hi... just checking... I'm stuck in this code... – Elbert Villarreal Sep 08 '14 at 02:09

1 Answers1

1

One technique I use, as do most experienced developers, is to use asserts and also NSLog (which you can comment on and off) to verify that assumptions you are making about your code are in fact true. Try cutting and pasting the below code and see what happens - it should help. In the future, don't bang your head on a wall - start adding asserts and logs. At some point you will find that some assumption is untrue.

-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
    NSLog(@"Received URLSessionDidFinishEventsForBackgroundURLSession: application state is %d", [UIApplication sharedApplication] applicationState];
    AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;

    [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
        NSLog(@"Download task count %d", [downloadTasks count]);
#warning "This looks like incorrect logic, but I don't know this background code. Wouldn't you see "1", or more? Won't you get an array of the tasks you submitted???
        if ([downloadTasks count] == 0) {
            assert(appDelegate.backgroundTransferCompletionHandler); // if this is nil, your app will be stuck in some odd state forever, so treat this like a fatal error
            void(^completionHandler)() = appDelegate.backgroundTransferCompletionHandler;
            appDelegate.backgroundTransferCompletionHandler = nil;

            assert([NSOperationQueue mainQueue]);   // why not?
            assert(![NSOperationQueue mainQueue].isSuspended);  // I looked at the class description, the queue **could** be suspended
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                NSLog(@"Completion Operation called!");
                assert(completionHandler);  // perhaps an ARC bug, unlikely, but then you cannot get this code to work, right?
                completionHandler();
            }];
        }
    }];
}
David H
  • 40,852
  • 12
  • 92
  • 138
  • You can also use the build system to disable asserts (and NSAsserts) in release builds, something I do but some people like to leave them in. – David H Sep 08 '14 at 13:41