我一直在使用NSURLConnection来执行一些异步下载。基本上我从Parse后端检索PFFile并在Web视图中显示它。我提供了下载到设备的选项。一切都很好,所有任务都按要求执行,但是,最近我注意到,如果我以高速执行下载,其中一些不会出现在下载VC中。我不知道如何测试它,但我的理论是它因为优先级设置为高,即使而被切断,用户无法做任何事情直到下载完成。您必须退出当前UIWebView
以选择其他文档。这不是一种组合行为,这使我更难以缩小范围。它只发生在我下载>退出>打开> &安培;立即下载另一个文档>退出>重复完成,没有特定的文件。
问题 :下载执行,我创建了一个NSLog文件,但是,当我转到下载VC时,文档没有显示出来在NSFRC中,但仍显示为目录中的有效文件。
过程 如何下载,
UIWebView加载从Parse.com查询的PDF。这里没问题。 ProgressHUD显示
加载后,progressHUD就会消失。
如果他们想要下载PDF,只需点击操作表索引进行下载,即可开始下载。
您可以在NSURL didReceiveData显示中看到另一个进度HUD。在下载完成之前,此HUD不允许用户交互。因此,您无法退出View Controller以选择其他pdf,直到完成下载完成为止。所以 NO 我没有同时进行大量下载,一次只下载一次。
然后用户可以在下载完成后退出,选择另一个加载相应PDF的UITableViewCell并重复该过程。
加载PDF:
PFQuery *EGQuery = [PFQuery queryWithClassName:@"Classname"];
[EGQuery whereKey:@"KeyName" equalTo:self.title];
[EGQuery getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (!error) {
if ([object objectForKey:@"EGFile"]) {
PFFile *file = [object objectForKey:@"EGFile"];
self.pdfURL = [file url];
self.pdfName = [file name]; //Ends up as EG_2014_04 this is what I append to the filePath where it's stored so the filePath will be /PDFs/EG_2014_04
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.pdfURL]]];
} else {
}
下载方法:
NSManagedObjectContext *context = [self managedObjectContext];
NSError *error = nil;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Downloads"];
[request setPredicate:[NSPredicate predicateWithFormat:@"pubnumber = %@", self.title]];
[request setFetchLimit:1];
NSUInteger count = [context countForFetchRequest:request error:&error];
if (count == NSNotFound) {
} else if (count == 0) {
NSURL *url = [NSURL URLWithString:pdfURL]; //pdfURL is PFFile url
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[connection start];
NSLog(@"Background time remaining = %.1f seconds", [UIApplication sharedApplication].backgroundTimeRemaining);
}];
NSData *pdfData = [[NSData alloc]
initWithContentsOfURL:[NSURL URLWithString:self.pdfURL]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"PDFs"];
NSString *filePath = [path stringByAppendingPathComponent:self.pdfName];
NSFileManager *fm = [NSFileManager defaultManager];
[fm createFileAtPath:filePath contents:pdfData attributes:nil];
if ([fm createFileAtPath:filePath contents:pdfData attributes:nil])
{
dispatch_async(dispatch_get_main_queue(), ^{
NSManagedObject *newDWNLD = [NSEntityDescription insertNewObjectForEntityForName:@"Downloads" inManagedObjectContext:context];
[newDWNLD setValue:self.title forKey:@"pubnumber"];
[newDWNLD setValue:self.pubTitle forKey:@"pubtitle"];
[newDWNLD setValue:self.pdfName forKey:@"puburl"]; // this is what I use for the file path name in the PDF directory and this is how I call it in my NSFRC
});
NSLog(@"File was created");
} else {
NSLog(@"File not created");
}
});
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
expectedLength = MAX([response expectedContentLength], 1);
currentLength = 0;
HUD.dimBackground = YES;
HUD.mode = MBProgressHUDModeAnnularDeterminate;
HUD.labelText = @"Downloading...";
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
currentLength += [data length];
HUD.progress = currentLength / (float)expectedLength;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"success.png"]];
HUD.mode = MBProgressHUDModeCustomView;
HUD.labelText = @"Success!";
HUD.detailsLabelText = @"Added to Downloads";
HUD.dimBackground = YES;
[HUD hide:YES afterDelay:1.6];
//Cancel Background task if completed
//[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
//self.backgroundTask = UIBackgroundTaskInvalid;
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"Error %@", error);
[HUD hide:YES];
}
下载VC
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Downloads" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:50];
NSSortDescriptor *azSort = [[NSSortDescriptor alloc] initWithKey:@"pubnumber" ascending:YES];
NSArray *azSortArray = @[azSort];
[fetchRequest setSortDescriptors:azSortArray];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"pubnumber" cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return fetchedResultsController;
}
cellForRowAtIndexPath:
NSString *title = [NSString stringWithFormat:@"%@", [context valueForKey:@"pubnumber"]];
cell.textLabel.text = title;
etc etc
编辑它似乎下载了所有这些内容,并且'创建'一个文件,但它不会在VC中显示所有文件。
application DidFinishLaunchingWithOptions:
NSString *createPaths;
NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
createPaths = [[documents objectAtIndex:0] stringByAppendingPathComponent:@"PDFs"];
NSLog(@"PDFs directory: %@", [[NSFileManager defaultManager] contentsOfDirectoryAtPath:createPaths error:&error]);
上面记录了我下载的所有文件,但它们不是从UIWebView中被识别为完全下载的,或者在下载过程中以某种方式创建文件路径是错误的,所以它是不显示在下载视图控制器中,但其他文档确实显示。每次会议一直缺1-2次,但就像我之前说过的那样,它从来没有丢失过相同的文件,所以缺少任何感觉缺失的东西。假设我下载10然后关闭应用程序然后重新打开它9只会在下载VC中有时8,但它会在目录中记录为有效的filePath。
答案 0 :(得分:1)
问题似乎是您的托管对象上下文线程限制,特别是您没有限制。你得到原始线程的上下文,可能是主线程,但是你在后台块中捕获它并直接访问它。
您应该保存文件并将其发送回主线程,然后在那里创建并保存新的托管对象。