2

Basicly, question header explains everything. I tried a lot of things, but it doesn't work.

I've got category that extends NSURLSession, that handles server and network errors

- (NSURLSessionDataTask *)
dataTaskHandlingErrorsWithRequest:(NSURLRequest *)request
                completionHandler:(void (^)(NSData *))completionHandler {
  return
      [self dataTaskWithRequest:request
              completionHandler:^(NSData *data, NSURLResponse *response,
                                  NSError *error) {
                if (!error && response &&
                    [response isKindOfClass:[NSHTTPURLResponse class]]) {
                  NSHTTPURLResponse *resp = (NSHTTPURLResponse *)response;
                  if (resp.statusCode / 100 == 2) {
                    completionHandler(data);
                  } else {
                    // Wrong status code from server.
                    NSNotificationCenter *center =
                        [NSNotificationCenter defaultCenter];
                    [center postNotificationName:kPANotifiNameServerStatusError
                                          object:self
                                        userInfo:@{
                                          @"response" : resp
                                        }];
                    NSLog(@"Wrong status code");
                    completionHandler(nil);
                  }
                } else {
                  // Something wrong with network.
                  NSNotificationCenter *center =
                      [NSNotificationCenter defaultCenter];
                  [center postNotificationName:kPANotifiNameNetworkError
                                        object:self
                                      userInfo:@{
                                        @"error" : error ? error : [NSNull null]
                                      }];
                  NSLog(@"Internet connection problem.");
                  completionHandler(nil);
                }
              }];
}

And here is where I'm calling it from:

- (void)authenticateWithHandler:(AuthHandler)handler {
  NSURLSession *session = [NSURLSession sharedSession];
  NSURLSessionTask *task =
      [session dataTaskHandlingErrorsWithRequest:self.request
                               completionHandler:^(NSData *data) {
                                 if (data) {
                                   BOOL suc = [self handleResponse:data];
                                   handler(suc);
                                 } else {
                                   handler(NO);
                                 }
                               }];
  [task resume];
}

So, on iOS 7.1, if I'm calling that method, it throws

2015-08-06 15:29:50.973 MyApp[2618:607] -[__NSCFURLSession dataTaskHandlingErrorsWithRequest:completionHandler:]: unrecognized selector sent to instance 0x7871bf40
2015-08-06 15:29:50.976 MyApp[2618:607] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFURLSession dataTaskHandlingErrorsWithRequest:completionHandler:]: unrecognized selector sent to instance 0x7871bf40'

But on iOS 8 it works. I checked compile sources, everything is ok there.

Alfred Zien
  • 1,025
  • 1
  • 11
  • 31
  • I do not see that method in references... – Julian Aug 06 '15 at 12:00
  • How is done the import of the category file? – Larme Aug 06 '15 at 12:13
  • @Larme simply like `#import "NSURLSession+ErrorHandlingAdditions.h"` – Alfred Zien Aug 06 '15 at 13:02
  • @JulianKról what method in which references? – Alfred Zien Aug 06 '15 at 13:04
  • @AlfredZien, missed the first part of the code – Julian Aug 06 '15 at 13:06
  • That may be a stupid question, but I don't have other idea.. Are you sure you don't have any `NS_AVAILABLE_IOS` flag set in that category? – Nat Aug 06 '15 at 14:01
  • @Vive no, nothing like this – Alfred Zien Aug 06 '15 at 14:18
  • 1
    Did you try to name it differently? Maybe the method is declared somewhere else (eg in a different category)? Just swallow one letter to check it ;). Can you also check in your category method `if ([self isKindOfClass:[NSURLSession class]]) NSLog(@"YES");`..? Maybe the object you're trying to run it on is just casted to NSURLSession while in fact it is not..? Just some guesses, as I still have no idea. – Nat Aug 06 '15 at 14:55
  • @Vive, you were right, it is not a NSURLSession object. It's object of class `__NSCFURLSession` and it is not subclass of NSURLSession. Very strange, as I get it from `[NSURLSession sharedSession]`. In iOS 8 `sharedSession` returns `__NSURLSessionLocal` and it is a subclass. So, how I can make it work in iOS 7? – Alfred Zien Aug 06 '15 at 15:19
  • I'll lead you to a comment of someone better than me: http://stackoverflow.com/a/26394751/849616. As matt wrote there, `__NSCFURLSession` is a valid subclass, but a private one. As a result, your code still should work. – Nat Aug 07 '15 at 07:09
  • 1
    @Vive why then `[[NSURLSession sharedSession] isKindOfClass:[NSURLSession class]]` returns false, if `__NSCFURLSession` is a valid subclass? Anyway, I think it is another question to ask, so if you write your comment as answer, I'll mark it as correct. – Alfred Zien Aug 07 '15 at 10:29

1 Answers1

1

Can you check in your category method:

if ([self isKindOfClass:[NSURLSession class]]) {
    NSLog(@"YES");
}

Maybe the object you're trying to run it on is just casted to NSURLSession while in fact it is not..? Just some guesses, as I still have no idea.

I'd like here to point Mattt answer, which can help to understand how does it work.

Community
  • 1
  • 1
Nat
  • 12,032
  • 9
  • 56
  • 103