When you try to access a web service, it will sometimes respond with an authentication challenge, which means “Who the heck are you?” You then need to send a username and password (a credential) before the server will send its genuine response.
When the challenge is received, the NSURLSession delegate is asked to authenticate that challenge, and the delegate will respond by supplying a username and password.
Open BNRCoursesViewController.m and update fetchFeed to hit a secure Big Nerd Ranch courses web service. (Do not forget to use https instead of http.)
- (void)fetchFeed { NSString *requestString = @"http://bookapi.bignerdranch.com/courses.json"; NSString *requestString = @"https://bookapi.bignerdranch.com/private/courses.json"; NSURL *url = [NSURL URLWithString:requestString]; NSURLRequest *req = [NSURLRequest requestWithURL:url];
The NSURLSession now needs its delegate to be set upon creation. Update initWithStyle: to set the delegate of the session.
- (instancetype)initWithStyle:(UITableViewStyle)style { self = [super initWithStyle:style]; if (self) { self.navigationItem.title = @"BNR Courses"; NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; _session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:nil]; _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil]; [self fetchFeed]; } return self; }
Then update the class extension in BNRCoursesViewController.m to conform to the NSURLSessionDataDelegate protocol.
@interface BNRCoursesViewController () <NSURLSessionDataDelegate> @property (nonatomic) NSURLSession *session; @property (nonatomic, copy) NSArray *courses; @end
Build and run the application. The web service will complete with an error (unauthorized access), and no data will be returned. Because of this, the BNRCoursesViewController will not have an array of courses to display, and so the table view will remain empty.
To authorize this request, you will need to implement the authentication challenge delegate method. This method will supply a block that you can call, passing in the credentials as an argument.
In BNRCoursesViewController.m implement the NSURLSessionDataDelegate method to handle the authentication challenge.
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler: (void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler { NSURLCredential *cred = [NSURLCredential credentialWithUser:@"BigNerdRanch" password:@"AchieveNerdvana" persistence:NSURLCredentialPersistenceForSession]; completionHandler(NSURLSessionAuthChallengeUseCredential, cred); }
The completion handler takes in two arguments. The first argument is the type of credentials you are supplying. Since you are supplying a username and password, the type of authentication is NSURLSessionAuthChallengeUseCredential. The second argument is the credentials themselves, an instance of NSURLCredential, which is created with the username, password, and an enumeration specifying how long these credentials should be valid for.
Build and run the application and it will behave as it did before you changed to the secure web service, but it is now fetching the courses securely over SSL.