Reputation: 11
I am somewhat new to Objective-C. I have some PERL scripts that download files from a site that requires client certificate authentication. I would like to port those scripts from PERL to Objective-C command line tools that I can then run from Terminal. Based on my research I have concluded that NSURLSession should work for what I need to do. However, I have been unable to get NSURLSession to work in my command line tool. It seems to build fine with no errors, but does not return anything from the completionHandler. Further, I have put this same code into a Mac OS X App tool and it seems to work fine.
Here is my main.m file:
#import <Foundation/Foundation.h>
#import "RBC_ConnectDelegate.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
// insert code here...
NSURL *myURL =[NSURL URLWithString:@"http://google.com"];
//[[[RBC_Connect alloc] init] connectGetURLSynch];
RBC_ConnectDelegate *myConnect = [[RBC_ConnectDelegate alloc] init];
[myConnect GetURL2: myURL];
}
return 0;
}
Here is my Implementation File:
#import <Foundation/Foundation.h>
@interface RBC_ConnectDelegate : NSObject
- (void)GetURL2:(NSURL *)myURL;
@property(nonatomic,assign) NSMutableData *receivedData;
//<==== note use assign, not retain
//do not release receivedData in a the dealloc method!
@end
And here is my implementation file:
#import "RBC_ConnectDelegate.h"
@implementation RBC_ConnectDelegate
- (void)GetURL2:(NSURL *)myURL2{
//create semaphore
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
// Create the request.
NSLog(@"Creating Request");
NSURLRequest *theRequest =
[NSURLRequest requestWithURL:myURL2
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:10.0];
NSLog(@"Creating Session");
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];
NSLog(@"Initializing Data Task");
NSURLSessionDataTask * dataTask = [defaultSession dataTaskWithRequest:theRequest
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"CompletionHandler");
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger myStatusCode = [(NSHTTPURLResponse *) response statusCode];
NSLog(@"Status Code: %ld", (long)myStatusCode);
}
if(error == nil)
{
NSString * text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(@"Data = %@",text);
}
else
{
NSLog(@"Error");
}
dispatch_semaphore_signal(semaphore);
}];
NSLog(@"Resuming Data Task");
[dataTask resume];
}
@end
As you can see, I am trying to get something very simple working here first, with the idea that I can then build on it. Everything I have looked at suggests this may be related to the fact that NSURLSession runs asynchronously but I have been unable to find a solution that speaks specifically to how to address this issue when building a command-line tool. Any direction anyone can provide would be appreciated.
cheers,
Upvotes: 1
Views: 673
Reputation: 2097
NSOperationQueue's reference says that for +mainQueue
, the main thread's run loop controls the execution of operations, so you need a run loop. Add this to the end of your main
:
while (1)
{
SInt32 res = 0;
@autoreleasepool
{
res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, DBL_MAX, false);
}
if (kCFRunLoopRunStopped == res || kCFRunLoopRunFinished == res)
break;
}
To call -GetURL2:
, use -[NSOperationQueue addOperation:]
or dispatch_async
. You can stop execution with CFRunLoopStop
. I tested with GCD instead of NSOperations but this should work anyway.
Also, you need to call dispatch_semaphore_wait
if you want to synchronize after the URL session is complete.
Upvotes: 1