NSOperationQueue mainQueue不更新​​UICollectionViewCell

时间:2015-12-30 04:04:25

标签: objective-c navigation uicollectionview nsurlsessiondownloadtask

使用NSURLSession下载文件并在UICollectionView中显示文件时,我发现问题是细胞无法从NSOperationQueue块正确更新。下载零件和文件存储每次都能正常工作。但更新单元格进度或图像仅适用于控制器的初始加载。如果我导航到root,然后再转到我的Collection控制器下载工作,但单元格不再更新。我发现这个有趣discussion,但在我的情况下没有用。

更多细节,启动URL会话和处理任务的控制器从storyboard segue加载。我注意到app每次都在创建新的控制器实例。在第二个导航访问单元格不显示进度或更新,但正确下载任务/文件。看来我的下载任务是从其他控制器实例获取单元格的副本。但是我从调试器中看到的内容没有意义,代理工作正常,任务完成成功。

以下是无法在第二次访问控制器时更新单元格的代码方法:

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{

    if (totalBytesExpectedToWrite == NSURLSessionTransferSizeUnknown) {
        NSLog(@"Unknown transfer size");
    }
    else{

    // Locate the FileDownloadInfo object in array based on my unique key in URL.
     int index = [self getFileDownloadInfoIndexWithTaskURL:downloadTask.originalRequest.URL.lastPathComponent];
        // Get singleton download object list from app delegate
        NSMutableArray *globalFileDownloadData = [self getGlobalDownloadFileList];
        FileDownloadInfo *fdi = [globalFileDownloadData objectAtIndex:index];
        // Get the progress view of the appropriate cell and update its progress.
        NSArray *arr = [self.fileDispCollection visibleCells];
        for(FileItemCell* cell in arr){
                if ([fdi.contentId isEqualToString:cell.testLbl.text]){

                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{

                     // This code works when app start initial visit to controller
                     // but does not work on2nd 3rd or other revisit
                     // even cells found correctly, files also loaded saved
                     // the progress does not show and no update

                        cell.downloadProgress.hidden = NO;
                        cell.downloadProgress.progress = fdi.downloadProgress;
                    }];   
                }
            }
    }
}

我使用这种方法初始化我的单身会话:

- (NSURLSession *)backgroundSession {
     //disptach_once ensure that multiple background sessions are not 
     //created in this instance of the application. 

    static NSURLSession *session = nil;
    static dispatch_once_t onceToken;

    NSArray *URLs = [[NSFileManager defaultManager]     URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
    self.docDirectoryURL = [URLs objectAtIndex:0];
    dispatch_once(&onceToken, ^{

    NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.Transport.demo"];
    sessionConfiguration.HTTPMaximumConnectionsPerHost = 3;
    sessionConfiguration.discretionary = NO;
    session = [NSURLSession sessionWithConfiguration:sessionConfiguration
                                                 delegate:self
                                            delegateQueue:nil];
    });
    return session;
}

什么可能导致第二个单元格或简单的收集单元不响应第二轮导航中的调用或数据重新加载?希望有人能解决这个问题。

2 个答案:

答案 0 :(得分:1)

尝试让你在主线程中更新UI代码,如下所示:

dispatch_async(dispatch_get_main_queue(), ^{
            //your update UI code
        });

答案 1 :(得分:1)

答案在我的问题中得出。故事板segue正在创建新的控制器,它是URLSession下载任务的创建者和处理者。 Session是单例,保持初始控制器堆栈和委托。因此,新的控制器实例将开始下载,但所有响应都将转到旧的控制器实例。

修复很简单,不使用performSegueWithIdentifier,而是创建单个控制器实例,在这种情况下实际上是更好的解决方案。

if (!self.library){
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle: nil];
        self.library = [storyboard instantiateViewControllerWithIdentifier:@"libraryScene"];
    }
    self.library.model = self.selectNode;
    [self.navigationController pushViewController:self.library animated:YES];