-1

我是在 iOS 上编程的新手,我需要构建将从 Web 服务器下载一些文件的应用程序,并在执行此操作时更新状态栏,但我不希望我的应用程序冻结,所以用户仍然可以在应用程序上执行其他操作。任何想法 ?。

4

3 回答 3

2

iOS 有一个内置的异步(即非阻塞)HTTP 客户端类。

构造一个NSURLConnection对象。提供请求参数,提供委托,调用[start]。该文件将开始下载,但应用程序和手机的其余部分不会被冻结。随心所欲地更新您的状态栏。

委托类方法必须收集传入数据并处理完成。

于 2013-09-18T01:34:01.897 回答
0

大多数常见的网络任务(包括图像请求、JSON 拉取等)实际上可以通过出色的AFNetworking 库非常轻松地异步实现。

一个示例请求:

-(void) startDownloadOfSomeFiles
{
    NSURLRequest* request = [NSURLRequest requestWithURL: [NSURL URLWithString:@"http://example.com/a_file.zip"]];
    AFHTTPRequestOperation* operation = [[AFHTTPRequestOperation alloc] initWithRequest: request];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        // Request was successful.
        NSString* path = ....
        operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        // Network request failed. Bummer.
    }];

    [operation start];
}

至于更新进度条,您必须在主线程上执行此操作,例如:

[NSOperationQueue mainQueue] addOperationWithBlock:^{
    aProgressBar.progress++; // or whatever
}];

例如,这可以在您的请求成功块内完成。

所有与 UI 相关的东西都必须发生在 iOS 的主线程上。[NSOperationQueue mainQueue] 允许您向队列添加操作。稍后会详细介绍。如果您尝试从后台 NSOperation 更新 UI 元素,您的应用很可能会崩溃。

如果您对一般线程感兴趣,使用后台线程的最简单方法是使用您自己的 NSOperationQueue(这也是 AFNetworking 在幕后的方式)。您可以使用标准的 alloc/init 创建自己的 NSOperationQueue,并且可以在其上设置以下属性:

NSOperationQueue* myOperationQueue = [[NSOperationQueue alloc] init];
myOperationQueue.maxConcurrentOperationCount = 1; //or 2, 3, whatever

这使您可以灵活地使用addOperation方法将任务排入队列。您可以继承 NSOperation,或者,对于较轻的任务,您可以使用

[myOperationQueue addWithBlock:^{
    NSLog(@"I'm running in a background thread!");
}];

NSOperationQueue 将根据您分配的最大线程数将您放入其中的操作排队并按顺序在它管理的工作线程上执行它们。如果没有线程在等待,它会在你入队后立即开始执行操作;如果有线程在等待,它将排队并在工作线程空闲时立即启动。

[NSOperationQueue mainQueue]遵循与上述相同的准则。您真正要做的是访问 iOS 用于您的 UI 的操作队列(这就是为什么在其上添加长时间运行的东西是一个非常糟糕的主意 - 您将冻结您的应用程序,因为您正在有效地运行您的代码同步)。您无法更改主队列上的并发操作数,但您可以将 UI 相关的任务排入其中,如上所述。

希望这能让您对基本原理有所了解。

于 2013-09-18T01:43:06.553 回答
0

使用多线程。您还可以使用调度队列。比我见过的其他一切都容易得多。如果您听说过目标 c 块,它会将其用作基本 c api。

dispatch_queue_t myCustomQueue;
myCustomQueue = dispatch_queue_create("com.example.MyCustomQueue", NULL);

// put work here for separate thread
dispatch_async(myCustomQueue, ^{
    printf("Do some work here.\n");
    dispatch_async(dispatch_get_main_queue(), ^{
      // do stuff in the main thread
    }
});

请注意,所有 UI Kit 函数都必须在主线程中调用。所有其他队列中的所有后台工作。

祝你好运,这也是开发者并发指南。 https: //developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/ OperationQueues.html`

于 2013-09-18T02:27:12.073 回答