- objective-c - iOS 5 : Can you override UIAppearance customisations in specific classes?
- iphone - 如何将 CGFontRef 转换为 UIFont?
- ios - 以编程方式关闭标记的信息窗口 google maps iOS
- ios - Xcode 5 - 尝试验证存档时出现 "No application records were found"
所以我在主线程上创建我的下载
NSURLRequest *request = [NSURLRequest requestWithURL:download.URL];
NSURLSessionDownloadTask *downloadTask = [self.downloadSession downloadTaskWithRequest:request];
[downloadTask resume];
并将与下载关联的 NSManagedContextID 添加到 NSMutableDictionary,所以我可以稍后在委托(delegate)回调中检索它
[self.downloads setObject:[download objectID] forKey:[NSNumber numberWithInteger:downloadTask.taskIdentifier]];
我上面的self.downloadSession
是这样配置的
- (NSURLSession *)backgroundSession
{
static NSURLSession *session = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.test.backgroundSession"];
configuration.discretionary = YES;
session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
});
return session;
}
我的问题是委托(delegate)回调似乎在不同的线程上调用
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
NSManagedObjectID *downloadID = [self.downloads objectForKey:[NSNumber numberWithInteger:downloadTask.taskIdentifier]];
double progress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:downloadID,@"download",[NSNumber numberWithDouble:progress],@"progress", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"DownloadProgress" object:nil userInfo:userInfo];
}
因此,当我访问 self.downloads 以获取正确的 objectID 时,我实际上是从与创建它的线程不同的线程访问 NSMutableDictionary,并且我相信 NSMutableDictionary 不是线程安全的。那么最好的解决方案是什么,我可以使用这样的东西
session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
在声明 session 时,将委托(delegate)队列设置为 mainQueue,这会导致在主线程上调用所有委托(delegate),但如果可能的话,我想将所有回调保留在后台线程上
最佳答案
在您的示例中,这不是问题,因为您的字典已移交给通知系统,操作队列线程不再使用它。只有当一个对象可能同时被多个线程访问时,线程安全才会成为问题。
如果您的字典是 iVar,您应该这样做:
像这样创建你自己的队列
myQueue = [[NSOperationQueue alloc] init];
// This creates basically a serial queue, since there is just on operation running at any time.
[myQueue setMaxConcurrentOperationCount:1];
然后在这个队列上安排对字典的每次访问,例如:
[myQueue addOperationWithBlock:^
{
// Access your dictionary
}];
当然,将此队列用于您的 URLSesson 委托(delegate):
session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:myQueue];
由于这个队列被设置为一个串行队列,所以总是只有一个线程在后台访问字典。
使用字典信息进行计算时要小心。您也必须在该队列上执行此操作。但是,您可以将计算结果放在任何其他队列/线程上,例如在主线程上更新 UI。
[myQueue addOperationWithBlock:^
{
// Calculate with your dictionary
// Maybe the progress calcualtion
NSString* progress = [self calculateProgress: iVarDict];
dispatch_async(dispatch_get_main_queue(), ^
{
// use progress to update UI
});
}];
我认为对于发布通知您不必使用该模式,因为系统会正确处理线程。但为了安全起见,您应该检查一下。
关于ios - NSURLSession 线程 : Tracking multiple background downloads,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18942178/
我编写了一个提供一些数据的 REST 服务。它受密码保护。 我正在尝试编写一个后台进程来获取数据并将其填充到我在应用程序中拥有的 sqlLite 数据库中。 我最初是在没有身份验证的情况下使用的: -
我想要一个 API key 并验证用户身份。我在控制台中看到消息“ session URL 任务成功:HTTP 200”。不幸的是,我总是收到页面“{”消息“:”的消息。此请求“}”的授权已被拒绝。我
我为 NSURLSession 创建了类别,然后我遇到了一个问题。在 iOS 7 中,[[NSURLSession sharedSession] isKindOfClass:[NSURLSession
如何从 NSHTTPCookieStorage.sharedHTTPCookieStorage 中删除所有 cookie?我知道删除单个指定 cookie 的唯一方法,但是,这些 cookie 是由
我正在尝试在应用程序进入后台(例如从主页按钮按下)的情况下正确处理进程内 NSURLSessionTasks。我目前正在采用将进程中的任务复制到后台队列的方法(请参见下面的代码)。然而,我发现后台任务
我是 objective-c 中的新手,使用 iOS 9 Xcode 7.2 并收到此警告“'initWithRequest:delegate:'已弃用:在 iOS 9.0 中首次弃用 - 使用 NS
当我导入 Gmail API 的 GTL.xcodeproj 并运行它时出现上述错误。我正在使用 Xcode 7.1 beta 并且在 Gmail API 二进制文件的头文件中出现了很多错误我们不推荐
我在我的 iOS 应用程序中使用 Alamofire 进行网络连接。我需要在 iOS 7+ 中运行这个应用程序。我要在状态栏中指示网络事件 ,所以我创建了这个结构: struct ActivityMa
我需要从服务器下载视频并保存视频以供稍后观看。 所以我需要下载视频并将其使用自定义名称保存在应用程序的文件系统中,到目前为止我可以下载数据(我猜)但无法存储它。 不,我不想使用额外的扩展框架或其他什么
在一个小型 iOS 应用程序中,我需要从服务器检索一些 JSON(类似于 DNS 请求),并使用此响应来发起进一步的连接。为此,我有一个使用 NSURLSession 处理 JSON 请求的对象。该对
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve th
当我尝试在网络离线(飞行模式)时启动基本的 NSURLSession 传输时,使用 NSURLSessionConfiguration defaultSessionConfiguration 和 ep
我曾经用 NSURLConnection 做我想做的事. 我会创建一个新的自定义 NSOperation对象 设置我的 NSMutalbeRequest当准备好触发operation女巫会排队操作..
我创建了一个下载任务。我已经使用cancelByProducingResumeData在应用程序中取消了任务,并将其保存到磁盘。当用户重新启动应用程序并单击“恢复”按钮时,我再次通过self.down
即使在使 NSURLSession 无效后,使用 Instruments 运行配置文件,一些名为 TubeManager、HTTPConnectionCache 和 HTTPConnectionCac
我有一段普通的代码,我几乎在我的代码中到处使用: let configuration = URLSessionConfiguration.default let session = URLSessio
我希望有人能够帮助我理解在我的 WatchOS 2 应用程序中尝试实现 NSURLSession 时遇到的问题。 无论出于何种原因,我收到错误; Error Domain=NSCocoaErrorDo
我正在尝试使用 NSURLSession 从 URL 获取 ID,但是 let task = NSURLSession.... 和 task.resume 之间的代码 永远不会执行(我在里面放置了一个
我正在尝试使用 NSURLSession 发出 HTTPRequest。当我设置完整的 url 时,请求返回正确的数据,但是当使用参数时 (NSJSONSerialization.dataWithJS
我是这方面的新手,但过去常常在这里搜索特定的东西,并且由于我找不到特定的答案,也许这里有人可以提供帮助。 我基本上是在学习和构建一个应用程序。 目前我已经构建登录、注册 View Controller
我是一名优秀的程序员,十分优秀!