更改视图控制器后更新ProgressView

时间:2014-06-28 18:54:14

标签: ios objective-c multithreading

我目前有一个进度视图,显示目前已下载文件的当前数量。当用户单击下载按钮时,进度会成功更新,当他们离开视图控制器并返回时,仍在下载,进度仍会成功更新。但是我的问题是当下载完成并且用户离开并返回到视图时,进度视图不再响应任何更新。我已经对多线程做过一些研究,并且看到许多人建议在主线程中进行任何UI更新,如下所示:

[self performSelectorOnMainThread:@selector(progressUpdate) withObject:nil waitUntilDone:NO]; 

所以我在我的代码中尝试了它并且仍然得到相同的结果(一旦用户离开并在下载完成后返回视图控制器,进度视图不响应任何更新)。然后我添加了一个NSLog来查看是否正在调用该方法并且调试器输出了NSLog。那么发生了什么?以下是视图控制器的代码:

VideoTest.m

#import "VideoTest.h"
#import "AppDelegate.h"
#import "FileDownloadInfo.h"


@interface VideoTest ()

@property (nonatomic, strong) NSURLSession *session;
@property (nonatomic, strong) NSMutableArray *arrFileDownloadData;
@property (nonatomic, strong) NSURL *docDirectoryURL;

-(void)initializeFileDownloadDataArray;
-(int)getFileDownloadInfoIndexWithTaskIdentifier:(unsigned long)taskIdentifier;

@end

@implementation VideoTest{

NSString *url;

}

@synthesize moviePlayer;
@synthesize download;
@synthesize videoAlreadyPlaying, progressView;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {

    // Custom initialization

}
return self;

}


- (void)viewDidLoad

{

[super viewDidLoad];
//Setting video URl
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
url = @"http://therosary.info/AppVideos/TheChaplet/Information%20on%20Divine%20Mercy.mp4";

//selectors set
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(MPMoviePlayerPlaybackStateDidChange:)
                                             name:MPMoviePlayerPlaybackStateDidChangeNotification
                                           object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterFullscreen:) name:MPMoviePlayerWillEnterFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willExitFullscreen:) name:MPMoviePlayerWillExitFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(enteredFullscreen:) name:MPMoviePlayerDidEnterFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(exitedFullscreen:) name:MPMoviePlayerDidExitFullscreenNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];


//Play the movie
videoAlreadyPlaying=@"TRUE";
self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:url]];
[self.view addSubview:moviePlayer.view];
self.moviePlayer.view.frame = CGRectMake(0,64,320,220);
[moviePlayer play];

[self initializeFileDownloadDataArray];

NSArray *URLs = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
self.docDirectoryURL = [URLs objectAtIndex:0];

NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.jjdoherty98.Marion_s_Net"];
sessionConfiguration.HTTPMaximumConnectionsPerHost = 5;


self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration
                                             delegate:self
                                        delegateQueue:nil];


if([appDelegate.isAlreadyDownloading isEqual:@"FALSE"] || appDelegate.isAlreadyDownloading==nil){
    self.progressView.hidden = YES;
    progressView.progress=0;
}
if([appDelegate.isAlreadyDownloading isEqual:@"TRUE"]){
    [self performSelectorOnMainThread:@selector(progressUpdate) withObject:nil waitUntilDone:NO];


}

}

- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];

if (self.isMovingFromParentViewController || self.isBeingDismissed) {
    NSLog(@"Left View");
    [moviePlayer stop];

}
}

- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];

}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.

}



- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationPortrait | UIInterfaceOrientationPortraitUpsideDown;
}

- (BOOL)shouldAutorotate{

AppDelegate *mainDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
mainDelegate.fullScreenVideoIsPlaying = @"TRUE";
return YES;

}


- (void)MPMoviePlayerPlaybackStateDidChange:(NSNotification *)notification
{
if (moviePlayer.playbackState == MPMoviePlaybackStatePlaying)
{ //playing
    videoAlreadyPlaying = @"TRUE";
}
if (moviePlayer.playbackState == MPMoviePlaybackStateStopped)
{ //stopped
}if (moviePlayer.playbackState == MPMoviePlaybackStatePaused)
{ //paused
}if (moviePlayer.playbackState == MPMoviePlaybackStateInterrupted)
{ //interrupted
}if (moviePlayer.playbackState == MPMoviePlaybackStateSeekingForward)
{ //seeking forward

}if (moviePlayer.playbackState == MPMoviePlaybackStateSeekingBackward)
{ //seeking backward
}

}



- (void)willEnterFullscreen:(NSNotification*)notification {

NSLog(@"willEnterFullscreen");
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
appDelegate.fullScreenVideoIsPlaying = @"TRUE";
}

- (void)enteredFullscreen:(NSNotification*)notification {

NSLog(@"enteredFullscreen");


}

- (void)willExitFullscreen:(NSNotification*)notification {

NSLog(@"willExitFullscreen");
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
appDelegate.fullScreenVideoIsPlaying = @"FALSE";

}

- (void)exitedFullscreen:(NSNotification*)notification {
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];

NSLog(@"exitedFullscreen");
if(appDelegate.CurrentProgress==0){
    progressView.hidden=TRUE;
}else{
    [self performSelectorOnMainThread:@selector(progressUpdate) withObject:nil waitUntilDone:NO];
}
}

- (void)playbackFinished:(NSNotification*)notification {

NSNumber* reason = [[notification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
switch ([reason intValue]) {
    case MPMovieFinishReasonPlaybackEnded:
        NSLog(@"playbackFinished. Reason: Playback Ended");
        videoAlreadyPlaying=@"FALSE";
        [moviePlayer stop];
        [moviePlayer play];
        break;

    case MPMovieFinishReasonPlaybackError:
        NSLog(@"playbackFinished. Reason: Playback Error");
        videoAlreadyPlaying=@"FALSE";
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Video Failed To Load!"
                                                        message:@"Unable to connect to server, please try again later!"
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];

        break;

    case MPMovieFinishReasonUserExited:
        NSLog(@"playbackFinished. Reason: User Exited");
        videoAlreadyPlaying=@"FALSE";

        break;

    default:
        break;

}

[self.moviePlayer setFullscreen:NO animated:YES];

}


-(IBAction)buttonPressed:(id)sender{

AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
if([appDelegate.isThereInternet isEqual:@"TRUE"]){
if([appDelegate.isAlreadyDownloading  isEqual: @"FALSE"]){
//If there is internet and not already downloading
    progressView.hidden=FALSE;
    progressView.progress=0;
    FileDownloadInfo *fdi = [self.arrFileDownloadData objectAtIndex:0];
    fdi.downloadTask = [self.session downloadTaskWithURL:[NSURL URLWithString:fdi.downloadSource]];
    fdi.taskIdentifier = fdi.downloadTask.taskIdentifier;
    // Start the task.
    [fdi.downloadTask resume];

}}
if ([appDelegate.isThereInternet isEqual:@"FALSE"]) {
    //No internet available
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Unable to connect to server"
                                                    message:@"Internet connection appears to be offline, please try again later!"
                                                   delegate:nil
                                          cancelButtonTitle:@"OK"
                                          otherButtonTitles:nil];
    [alert show];
    [alert release];

}
    if([appDelegate.isAlreadyDownloading isEqual:@"TRUE"]){
    //Is already downloaing
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"File Already Downloading"
                                                    message:@"Multiple files can not be downloaded at the same time!"
                                                   delegate:nil
                                          cancelButtonTitle:@"OK"
                                          otherButtonTitles:nil];
    [alert show];
    [alert release];

}

}

-(void)initializeFileDownloadDataArray{
self.arrFileDownloadData = [[NSMutableArray alloc] init];
[self.arrFileDownloadData addObject:[[FileDownloadInfo alloc] initWithFileTitle:nil andDownloadSource:url]];
}


-(int)getFileDownloadInfoIndexWithTaskIdentifier:(unsigned long)taskIdentifier{
int index = 0;
for (int i=0; i<[self.arrFileDownloadData count]; i++) {
    FileDownloadInfo *fdi = [self.arrFileDownloadData objectAtIndex:i];
    if (fdi.taskIdentifier == taskIdentifier) {
        index = i;
        break;
    }
 }

return index;
}

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{

NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];

NSString *destinationFilename = downloadTask.originalRequest.URL.lastPathComponent;
NSURL *destinationURL = [self.docDirectoryURL URLByAppendingPathComponent:destinationFilename];
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];

if ([fileManager fileExistsAtPath:[destinationURL path]]) {
    [fileManager removeItemAtURL:destinationURL error:nil];
}

BOOL success = [fileManager copyItemAtURL:location
                                    toURL:destinationURL
                                    error:&error];

if (success) {
    int index = [self getFileDownloadInfoIndexWithTaskIdentifier:downloadTask.taskIdentifier];
    FileDownloadInfo *fdi = [self.arrFileDownloadData objectAtIndex:index];

    fdi.isDownloading = NO;
    fdi.downloadComplete = YES;

    // Set the initial value to the taskIdentifier property of the fdi object,
    // so when the start button gets tapped again to start over the file download.
    fdi.taskIdentifier = -1;

    // In case there is any resume data stored in the fdi object, just make it nil.
    fdi.taskResumeData = nil;


}
else{
    NSLog(@"Unable to copy temp file. Error: %@", [error localizedDescription]);
}
}


-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];

if (error != nil) {
    NSLog(@"Download completed with error: %@", [error localizedDescription]);
    appDelegate.isAlreadyDownloading=@"FALSE";
    dispatch_async(dispatch_get_main_queue(), ^{

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Failed to download!"
                                                    message:@"Unable to connect to the server!"
                                                   delegate:nil
                                          cancelButtonTitle:@"OK"
                                          otherButtonTitles:nil];
    [alert show];
    [alert release];
    });

}
else{
    appDelegate.isAlreadyDownloading=@"FALSE";
    NSLog(@"Download finished successfully.");
    dispatch_async(dispatch_get_main_queue(), ^{

        FileDownloadInfo *fdi = [self.arrFileDownloadData objectAtIndex:0];
        fdi.isDownloading = NO;
        fdi.downloadComplete = YES;
        fdi.taskIdentifier = -1;
        fdi.taskResumeData = nil;
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Download Complete!"
                                                        message:@"Go to downloads section to view the file now!"
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];

    });


}
}



-(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{
    int index = [self getFileDownloadInfoIndexWithTaskIdentifier:downloadTask.taskIdentifier];
    FileDownloadInfo *fdi = [self.arrFileDownloadData objectAtIndex:index];
    AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
    appDelegate.isAlreadyDownloading=@"TRUE";
        fdi.downloadProgress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
        appDelegate.CurrentProgress = fdi.downloadProgress;
         [self performSelectorOnMainThread:@selector(progressUpdate) withObject:nil waitUntilDone:NO];

}
}


-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;

[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {

    if ([downloadTasks count] == 0) {
        if (appDelegate.backgroundTransferCompletionHandler != nil) {

            // Make nil the backgroundTransferCompletionHandler.
            appDelegate.backgroundTransferCompletionHandler = nil;
            progressView.hidden=TRUE;

                // Show a local notification when all downloads are over.
                UILocalNotification *localNotification = [[UILocalNotification alloc] init];
                localNotification.alertBody = @"All files have been downloaded!";
                [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];

        }
    }
}];
}

-(void)progressUpdate{
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];

if ([appDelegate.isAlreadyDownloading isEqual:@"TRUE"]) {
    progressView.progress = appDelegate.CurrentProgress;
    [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(progressUpdate) userInfo:nil repeats:NO];
    NSLog(@"Is this method being called");
    if (appDelegate.CurrentProgress==1) {
        progressView.hidden=TRUE;
    }
}

}
@end

任何帮助将不胜感激!

0 个答案:

没有答案