在我的应用程序中,我有一个带有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
答案 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。我对你将指标放在哪个视图(和框架)做了很多假设。相应调整。
干杯