重新打开视图后AFNetworking恢复进度条

时间:2014-06-17 21:59:26

标签: ios objective-c uiviewcontroller afnetworking

在我的应用程序中,我有一个带有UIProgressView的UIViewController和一个用AFNetworking库开始下载的按钮。 在关闭viewController然后重新打开后,如何恢复下载进度条?

这是我的代码:

ViewController.m

    [...]
- (void) updateProgress:(float)progress forOperation:(AFHTTPRequestOperation *)operation {
    self.downloadprogress.progress = progress;
}


- (void)downloadTest:(NSString *)cid
{
    NSString *string = [NSString stringWithFormat:@"%@get_new.php?c=%@", BaseURLString, cid];
    NSURL *url = [NSURL URLWithString:string];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.zip", cid]];

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];


    __weak typeof(operation)weakOperation = operation;
    [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
        __strong __typeof(weakOperation)strongOperation = weakOperation;
        //NSLog(@"Progress = %f", (float)totalBytesRead / totalBytesExpectedToRead );
        float progressValue = (float)totalBytesRead / totalBytesExpectedToRead;
        [self updateProgress:progressValue forOperation:strongOperation];
    }];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        // DOWNLOAD OK

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

        // DOWNLOAD ERROR
    }];

    [operation start];
}
        [...]

ViewController.h

@interface InfoViewController : UIViewController{
    IBOutlet UITextView *txtinfo;

    IBOutlet UIBarButtonItem *btnDown;
}

@property (weak, nonatomic) IBOutlet UIProgressView *downloadprogress;

- (IBAction)downloadBtn:(id)sender;

@end

2 个答案:

答案 0 :(得分:2)

我还没有使用AFNetworking,所以也许我错了;但是对我来说,由于downloadTest:对象的释放,在退出operation方法后,代码下载将停止。

要解决此问题,请使用属性或某些非本地范围变量。但是,如果您想要在销毁视图控制器之后继续下载,那么您需要使用在应用程序生命周期内存在的对象。

例如,它可能是您AppDelegate的属性。在这种情况下,当前的下载进度也将是AppDelegate的属性。使用此方法,您可以在InfoViewController viewDidLoad:方法中请求当前下载大小并使用相应值更新进度条。此外,要在显示视图控制器时更新当前下载进度,您可以订阅代表当前下载进度的AppDelegate属性值的更新(使用KVO)。

请参阅下面这种方法的示例。

<强> AppDelegate.h

extern NSString* const kStartDownloadNotificationName;
extern NSString* const kStartDownloadNotificationParamCid;

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@property (nonatomic) float currentDownloadProgressValue;

@end

<强> AppDelegate.m

NSString* const kStartDownloadNotificationName = @"StartDownloadNotificationName";
NSString* const kStartDownloadNotificationParamCid = @"StartDownloadNotificationParamCid";

@interface AppDelegate ()

@property (strong, nonatomic) AFHTTPRequestOperation* downloadOperation;

- (void)startDownloadOperationWithNotification:(NSNotification*)notification;

@end

@implementation AppDelegate

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(startDownloadOperationWithNotification:)
                                                 name:kStartDownloadNotificationName
                                               object:nil];
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:kStartDownloadNotificationName
                                                  object:nil];
}

- (void)startDownloadOperationWithNotification:(NSNotification*)notification
{
    NSString* cid = notification.userInfo[kStartDownloadNotificationParamCid];

    if (cid == nil) {
        return;
    }

    NSString *string = [NSString stringWithFormat:@"%@get_new.php?c=%@", BaseURLString, cid];
    NSURL *url = [NSURL URLWithString:string];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.zip", cid]];

    self.downloadOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    self.downloadOperation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];


    __weak typeof(self.downloadOperation)weakOperation = self.downloadOperation;
    [self.downloadOperation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
        __strong __typeof(weakOperation)strongOperation = weakOperation;
        //NSLog(@"Progress = %f", (float)totalBytesRead / totalBytesExpectedToRead );
        self.currentDownloadProgressValue = (float)totalBytesRead / totalBytesExpectedToRead;
    }];

    [self.downloadOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
                                                                // DOWNLOAD OK
                                                            } 
                                                  failure:^(AFHTTPRequestOperation *operation, NSError *error) {

                                                                // DOWNLOAD ERROR
                                                            }
    ];

    [self.downloadOperation start];
}

@end

<强> ViewController.h

@interface InfoViewController : UIViewController{
    IBOutlet UITextView *txtinfo;

    IBOutlet UIBarButtonItem *btnDown;
}

@property (weak, nonatomic) IBOutlet UIProgressView *downloadprogress;

- (IBAction)downloadBtn:(id)sender;

@end

<强> ViewController.m         [...]

- (void)viewDidLoad
{
    [super viewDidLoad];

    // ...

    AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
    [self updateProgress:appDelegate.currentDownloadProgressValue];
}

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

    // ...

    AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
    [appDelegate addObserver:self
                  forKeyPath:@"currentDownloadProgressValue"
                     options:NSKeyValueObservingOptionNew
                     context:NULL];
}

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

    // ...

    AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
    [appDelegate removeObserver:self
                     forKeyPath:@"currentDownloadProgressValue"];
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context 
{

    if ([keyPath isEqual:@"currentDownloadProgressValue"]) {
        NSNumber* currentProgressObj = [change objectForKey:NSKeyValueChangeNewKey];
        [self updateProgress:[currentProgressObj floatValue]];
    }
}


- (void)updateProgress:(float)progress
{
    self.downloadprogress.progress = progress;
}


- (void)downloadTest:(NSString *)cid
{
    [[NSNotificationCenter defaultCenter] postNotificationName:kStartDownloadNotificationName
                                                        object:nil
                                                      userInfo:@{ kStartDownloadNotificationParamCid : cid }];
}
    [...]

P.S。抱歉,我没有检查此代码是否存在构建错误或运行时错误。

答案 1 :(得分:0)

尝试这样的事情:

- (void)downloadTest:(NSString *)cid
{
    NSString *string = [NSString stringWithFormat:@"%@get_new.php?c=%@", BaseURLString, cid];
    NSURL *url = [NSURL URLWithString:string];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.zip", cid]];

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];

    UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    activityIndicatorView.hidesWhenStopped = YES;
    [activityIndicatorView startAnimating];
    activityIndicatorView.center = self.view.center;
    [self.view addSubview:activityIndicatorView];


    __weak typeof(operation)weakOperation = operation;
    [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
        __strong __typeof(weakOperation)strongOperation = weakOperation;
        //NSLog(@"Progress = %f", (float)totalBytesRead / totalBytesExpectedToRead );
        float progressValue = (float)totalBytesRead / totalBytesExpectedToRead;
        [self updateProgress:progressValue forOperation:strongOperation];
    }];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        // DOWNLOAD OK
        [activityIndicatorView stopAnimating];
        [activityIndicatorView removeFromSuperview];

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

        // DOWNLOAD ERROR
        if (!error)
        {

        }

        [activityIndicatorView stopAnimating];
        [activityIndicatorView removeFromSuperview];
    }];

    [operation start];
}

作为一个额外的好处,我建议你在其他地方(-init)分配活动指标,这样你就不必继续重新分配。此外,分配一次更脆弱(以一种好的方式)和更好的内存管理实践。

P.S。我对你将指标放在哪个视图(和框架)做了很多假设。相应调整。

干杯