Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delegate methods for NSURLSessionTaskDelegate not getting called? #40

Closed
Goles opened this issue Oct 17, 2013 · 18 comments
Closed

Delegate methods for NSURLSessionTaskDelegate not getting called? #40

Goles opened this issue Oct 17, 2013 · 18 comments

Comments

@Goles
Copy link
Contributor

Goles commented Oct 17, 2013

Should they be getting called ?

I would like to be able to get the 'upload progress' of an image, but not sure if OHHTTPStubs can do that.

This is what I'm trying to do, it's crazy that none of the delegate methods are getting called though, we should at least hit the completion handler.

// Upload Image

- (void)uploadImage:(UIImage *)image
    completionBlock:(operationCompletionBlock)completionBlock
      progressBlock:(operationProgressBlock)progressBlock
{
    NSData *imageData = UIImageJPEGRepresentation(image, 0.80);
    NSURLRequest *request = [NSURLRequest requestWithURLString:@"/image_upload"];
    NSURLSessionUploadTask *uploadTask = [_session uploadTaskWithRequest:request
                                                                fromData:imageData
                                                       completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                           if (completionBlock) {
                                                               NSError *err;
                                                               NSDictionary *d = [NSJSONSerialization JSONObjectWithData:data options:0 error:&err];
                                                               completionBlock([HIImageData imageDataFromJSONRepresentation:d], error);
                                                           }
                                                       }];

    [_progressTable setObject:progressBlock forKey:uploadTask];
    [uploadTask resume];
}


// From <NSURLSessionTaskDelegate>  (Not Getting Called)
- (void)URLSession:(NSURLSession *)session
              task:(NSURLSessionTask *)task
   didSendBodyData:(int64_t)bytesSent
    totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
    operationProgressBlock completionBlock = [_progressTable objectForKey:task];

    if (completionBlock) {
        completionBlock(totalBytesSent/totalBytesExpectedToSend);
    }
}

// From <NSURLSessionTaskDelegate>  (Not Getting Called)
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    [_progressTable removeObjectForKey:task];
}
@AliSoftware
Copy link
Owner

What is your _session and more especially how is it created and configured?

@Goles
Copy link
Contributor Author

Goles commented Oct 17, 2013

@AliSoftware Hey there,

    // Session property
   @property (nonatomic, strong) NSURLSession *session;

   - (void) setup {
         NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        _session = [NSURLSession sessionWithConfiguration:config];
    }

The uploadTasks are being stubbed, since I can actually see:

Request to https://website.com/image_upload has been stubbed with Image Upload OK

And my stub looks like:

    /** Mock Image upload WS response */
    [OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {
        return [request.URL.path isEqualToString:@"/image_upload"];
    } withStubResponse:^OHHTTPStubsResponse *(NSURLRequest *request) {
        return [[OHHTTPStubsResponse responseWithFileAtPath:OHPathForFileInBundle(@"image_upload_ws_response.json", nil)
                                                 statusCode:201
                                                    headers:@{@"Content-Type":@"text/json"}] responseTime:OHHTTPStubsDownloadSpeed3G];
    }].name = @"Image Upload OK";

I could even send you the project since it's still in early-stage, should the delegates be getting called?

@Goles
Copy link
Contributor Author

Goles commented Oct 17, 2013

@AliSoftware if you want to take a look to the code, you can check it out here.

The delegate methods are in HIAPIRequests.m , Line 104 and Line 116. You can set breakpoints there.

You could try to run the test case located in HIAPIOperatorTests.m Line 70, this test case will eventually try to upload images in the following method:

// HIAPIRequests.m line 37
- (void)uploadImage:(UIImage *)image
    completionBlock:(operationCompletionBlock)completionBlock
      progressBlock:(operationProgressBlock)progressBlock

The delegate methods for NSURLSessionTaskDelegate are also located in HIAPIRequests.m

#pragma mark - NSURLSessionTaskDelegate

- (void)URLSession:(NSURLSession *)session
              task:(NSURLSessionTask *)task
   didSendBodyData:(int64_t)bytesSent
    totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
    operationProgressBlock completionBlock = [_progressTable objectForKey:task];

    if (completionBlock) {
        completionBlock(totalBytesSent/totalBytesExpectedToSend);
    }
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    [_progressTable removeObjectForKey:task];
}

@AliSoftware
Copy link
Owner

I don't understand where in your code do you set the NSURLSession's delegate property?
Of course if you don't tell which object is your delegate and has the implementation of those methods to be called, this will never happen.

This is not related to OHHTTPStubs at all (given your code, even without the stubs installed and even if you let your requests hit the real world, your delegate methods would never have been called anyway…), so I'm closing the issue.

@Goles
Copy link
Contributor Author

Goles commented Oct 17, 2013

You're correct. Sorry for the hassle,

_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];

@Goles
Copy link
Contributor Author

Goles commented Oct 17, 2013

@AliSoftware

I may be missing something here, but I added the above line in HIAPIRequests.m & Line 99

- (void)configureURLSession
{
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
}

The delegate methods are still not being called, is this expected behavior?

PS: Another strange thing is that even though my upload speed is stated to be 3G, the 'image upload' seems to be instant.

@AliSoftware
Copy link
Owner

Please try making your code work even without OHHTTPStubs before filing a new issue to ensure that this is related to my component and not related to your own code.

Please then try to reduce the scope of your test to isolate the problem by using the simplest possible code to reproduce the issue. I'm sure that you can understand I won't have time to review all your own thousand LOC of your own project, especially if it's only to discover at the end that this is still not related to my component at all 😉

So you should try and manage to create a simple Unit Test (that test unitary cases not involving a whole bunch of custom classes not relevant to the issue) that triggers the issue, and then I will consider it as a potential real issue from my component and not from your code, and have a real Unit Test case to resolve. But if you have the same issue w/o OHHTTPStubs or can't reproduce it in a simple independant Test Case, then it's probably a bug in your own code.

@Goles
Copy link
Contributor Author

Goles commented Oct 17, 2013

Sure, will wrap it and submit a test project for you to review.

Cheers!

@AliSoftware
Copy link
Owner

submit a test project for you to review.

Please don't; I won't probably have time to review a whole project.
Provide a Unit Test instead; the better way being to add the Unit Test directly in my project along with the other existing Unit Tests, and then propose a Pull Request (like the OP did in #39), so I can isolate and resolve the issue faster.

@Goles
Copy link
Contributor Author

Goles commented Oct 17, 2013

Ok, will do that!

AliSoftware added a commit that referenced this issue Oct 18, 2013
@AliSoftware
Copy link
Owner

Hi @Goles

I don't know if you managed to debug your own code, but I did some tests on my own and added a Unit Test to my own OHHTTPStubs project to test the use of NSURLSession delegates. And as you can see if you checkout my latest Unit Test and run it on your Xcode5, the test is passing without any problem and the delegate methods are called as expected.

This should confirm that the issue you were having with your code was not related to OHHTTPStubs at all.


(Note: the test is not executed by Travis-CI yet because Travis-CI still uses Xcode4/iOS6 SDK which does not support NSURLSession)

@Goles
Copy link
Contributor Author

Goles commented Oct 18, 2013

Hey there!

Haven't managed to debug my own code and write the test case yet!

Will take a look at your test by Sunday and if I can write a non-passing test for OHHTTPStubs I'll do so!

Cheers and thanks for the heads-up!

Sent from my iPhone

On Oct 18, 2013, at 1:47 PM, AliSoftware notifications@github.com wrote:

Hi @Goles

I don't know if you managed to debug your own code, but did some tests on my own and I also added a Unit Test to my own OHHTTPStubs project to test the use of NSURLSession delegates.

And as you can see, the test is passing without any problem and the delegate methods are called as expected.

This should confirm that the issue you were having with your code was not related to OHHTTPStubs at all.


Reply to this email directly or view it on GitHub.

@Goles
Copy link
Contributor Author

Goles commented Oct 20, 2013

@AliSoftware

Hey there, wrote a small test case that shows that the progress delegate method is not getting called for an upload task, you can check it out here. Note that the test passes but the delegate method is not called.

Maybe I'm missing something?

@AliSoftware
Copy link
Owner

I understand you didn't manage to find a failing test for any other delegate methods and download task, but only for upload?

That's an issue alright, but this is quite understandable: OHHTTPStubs is designed to stub network responses. Its aim is to mimic a response from a server. OHHTTPStubs was never designed to handle uploads until now.
Anyway, that's true that it could be a great addition for OHHTTPStubs to make it handle data uploads too, simulating network speed and latency during upload too; but IMHO this is then a Feature Request more than a real bug as I never stated to handle data upload until now (the general principle of a stub is to return data, not to eat some). This is not even related to NSURLSession and was true even before its existence.

Please create a Pull Request with your Unit Test — describing in your request that you would like to OHHTTPStubs to support upload too — so I can follow this feature request and merge it properly.

Note this would mean some refactoring of the startLoading method and handing NSOutputSteam in addition to the NSInputStream in place to upload data in addition to downstream the stubbed one, so that could be tricky and take some time

@AliSoftware
Copy link
Owner

Actually, I'm not even sure it's possible to simulate upload, as NSURLProtocolClient does not allow us to signal the client that we sent data.

So except if you find something in the URL Loading System Programming Guide that describes a way to do this, I'm unfortunately quite sure this can't be done with a custom NSURLProtocolClient

I'll keep searching but maybe Apple did forget to provide a way to implement our custom upload protocol…

AliSoftware referenced this issue Oct 20, 2013
(+ Static Analyzer now analyzes code in Unit Tests too)
@Goles
Copy link
Contributor Author

Goles commented Oct 21, 2013

@AliSoftware Do you think it's still worthy to refactor and update my test?

I could ask around, maybe there's another way we could do this.

Cheers!

@AliSoftware
Copy link
Owner

No I don't think it's still worthy to refactor your test as if you do it will fail and will never pass until we find a way to implement upload… which is probably not possible at all.

So it's still worthy to ask around in case someone finds a way to do this, but until then the Unit Test won't be useful as it would test a feature that is not implemented at all… and will probably never be if we don't find a way to.

Thx anyway and don't hesitate if you have any news about a way to do this feature.

@milosj
Copy link

milosj commented Oct 29, 2014

You are creating a task with a completion handler, so the delegate will not be called.

AliSoftware added a commit that referenced this issue Nov 3, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants