作为命令行工具运行时,如何让 NSURLSession 处理 completionHandler

Posted

技术标签:

【中文标题】作为命令行工具运行时,如何让 NSURLSession 处理 completionHandler【英文标题】:How can I get NSURLSession to process completionHandler when running as a command-line tool 【发布时间】:2014-07-08 23:10:09 【问题描述】:

我对 Objective-C 有点陌生。我有一些 PERL 脚本从需要客户端证书身份验证的站点下载文件。我想将这些脚本从 PERL 移植到 Objective-C 命令行工具,然后我可以从终端运行这些工具。根据我的研究,我得出的结论是 NSURLSession 应该可以满足我的需要。但是,我无法让 NSURLSession 在我的命令行工具中工作。它似乎构建良好,没有错误,但没有从 completionHandler 中返回任何内容。此外,我已将相同的代码放入 Mac OS X App 工具中,它似乎工作正常。

这是我的 main.m 文件:

#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;

这是我的实现文件:

#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

这是我的实现文件:

#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

如您所见,我试图先在这里做一些非常简单的工作,然后我可以在此基础上进行构建。我所看到的一切都表明这可能与 NSURLSession 异步运行的事实有关,但我一直无法找到专门针对如何在构建命令行工具时解决此问题的解决方案。任何人都可以提供任何方向将不胜感激。

干杯,

【问题讨论】:

【参考方案1】:

NSOperationQueue 的参考说对于+mainQueue,主线程的run loop 控制着操作的执行,所以你需要一个run loop。将此添加到 main 的末尾:

while (1)

    SInt32 res = 0;
    @autoreleasepool
    
        res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, DBL_MAX, false);
    

    if (kCFRunLoopRunStopped == res || kCFRunLoopRunFinished == res)
        break;

要致电-GetURL2:,请使用-[NSOperationQueue addOperation:]dispatch_async。您可以使用CFRunLoopStop 停止执行。我使用 GCD 而不是 NSOperations 进行了测试,但这应该可以工作。

另外,如果您想在 URL 会话完成后进行同步,则需要调用 dispatch_semaphore_wait

【讨论】:

以上是关于作为命令行工具运行时,如何让 NSURLSession 处理 completionHandler的主要内容,如果未能解决你的问题,请参考以下文章

如何让 MySQL 命令行工具默认显示存储为 BIT 的布尔值

命令行完成时发出声音[重复]

我想让一个java程序(已打成jar包)开机自动启动,不启用命令行,该如何实现?

无法让 sublime text 3 命令行工具工作

如何在命令行上将运行时参数传递给 dotnet test?

如何在命令行中运行 ZAP 扫描?