1

我正在尝试使用 asinetworkqueue 下载 url 列表。它下载很好。但是当我滚动 uitableview 时,我的 uiprogressview 被隐藏了。

我的意思是如果进度显示在第 2 行中,并且如果我滚动它,那么进度视图将被隐藏。然后在完成第 2 行的下载后,它会在第 3 行显示进度视图。

简而言之,当滚动 uitableview 时,活动的 uiprogressview 被隐藏了。

更新

这里有一些更多的说明。当一行(例如第 1 行)的下载未完成时,现在如果我滚动 tableview 并查看第 1 行,即使尚未完成下载,progressview 也会被隐藏。一旦第 1 行的下载完成,它就会开始对第 2 行进行下载,现在显示进度视图。

 - (void)viewDidLoad
    {
        [super viewDidLoad];

        self.view.backgroundColor = [UIColor clearColor];

        self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"bg.jpg"]];

        CGRect tblViewFrame = CGRectMake(7 , 0 , self.view.bounds.size.width - 14, self.view.bounds.size.height - 90);
        self.tblViewDownload = [[[UITableView alloc]initWithFrame:tblViewFrame style:UITableViewStyleGrouped]autorelease];
        self.tblViewDownload.backgroundColor = [UIColor clearColor];
        self.tblViewDownload.showsVerticalScrollIndicator = FALSE;
        self.tblViewDownload.scrollEnabled = YES;
        self.tblViewDownload.delegate = self;
        self.tblViewDownload.dataSource = self;
        [self.view addSubview:self.tblViewDownload];

        index = 0;

        dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
            [self loadArray];
        }); // Do any additional setup after loading the view.
    }



    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    {
        // Return the number of sections.
        return 1;
    }


    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    {
        // Return the number of rows in the section.
        return [self.myUrlArray count];
    }


    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:
    (NSIndexPath *)indexPath

    {
        CGFloat rowHeight = 75.0;

        return rowHeight;  
    }

    // Customize the appearance of table view cells.
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
    (NSIndexPath *)indexPath

    {
        NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d", indexPath.row];

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

        UILabel *lblTitle, *lblAuthor;


        if (cell == nil)
        {
            cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero]autorelease];

            cell.selectionStyle = UITableViewCellSelectionStyleNone;

            lblTitle = [[[UILabel alloc]initWithFrame:CGRectMake(65, 10, 220, 25)]autorelease];
            lblTitle.backgroundColor = [UIColor clearColor];
            //lblTitle.font = [UIFont boldSystemFontOfSize:15.0];
            lblTitle.font = [UIFont fontWithName:@"Palatino-Bold" size:15.0];
            lblTitle.text = @"Sample title";
            [cell.contentView addSubview:lblTitle];

            lblAuthor = [[[UILabel alloc]initWithFrame:CGRectMake(65, 30, 220, 25)]autorelease];
            lblAuthor.backgroundColor = [UIColor clearColor];
            lblAuthor.font = [UIFont italicSystemFontOfSize:13.0];
            lblAuthor.textColor = [UIColor grayColor];
            lblAuthor.text = @"sample authior";
            [cell.contentView addSubview:lblAuthor];



        }

        return cell;
    }


    -(void)loadArray{

      NSString *urk = @"http://sample/iphone/video/video_2.mov";
      self.myUrlArray = [[NSMutableArray alloc]init];

      for( int i = 0;i<10;i++){
        [self.myUrlArray addObject:urk];
      }


      dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
        [self downLoadPoems];
      });

    }

    -(void)downLoadPoems{

        if( index < [myUrlArray count] )
        {
            NSLog(@"this is the index %d",index);

        NSIndexPath *myIP = [NSIndexPath indexPathForRow:index inSection:0];

        UITableViewCell *Cell = [self.tblViewDownload cellForRowAtIndexPath:myIP];

        progress = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];
        progress.frame = CGRectMake(65, 55, 210, 25);
        progress.progress = 0.0;
        progress.backgroundColor = [UIColor redColor];
        [Cell.contentView addSubview:progress];
        }


        if(!self.networkQueue)
            self.networkQueue = [[[ASINetworkQueue alloc] init] autorelease];

        [self.networkQueue cancelAllOperations];
        [self.networkQueue setQueueDidFinishSelector:@selector(queueCompleted:)];
        [self.networkQueue setShowAccurateProgress:YES];
        [self.networkQueue setDownloadProgressDelegate:progress];

        [self.networkQueue setDelegate:self];

        if( index < [myUrlArray count] )
        {        
            NSString *url = [myUrlArray objectAtIndex:index];

            NSArray *aPoemArrayUrls = [NSArray arrayWithObjects:url,nil];

            for(NSString* urlString in aPoemArrayUrls)
            {
                NSURL *url = [NSURL URLWithString:urlString];
                ASIHTTPRequest *downloadAFileRequest = [[ASIHTTPRequest requestWithURL:url]retain];
                NSString *Filename = [urlString lastPathComponent];
                NSLog(@"%@ filename",Filename);
                [downloadAFileRequest setUserInfo:[NSDictionary dictionaryWithObject:@"request1" forKey:@"name"]];
                [downloadAFileRequest setDownloadDestinationPath:[[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:Filename]];
                [downloadAFileRequest setShouldContinueWhenAppEntersBackground:YES];
                [downloadAFileRequest setDelegate:self];
                [downloadAFileRequest setDidFinishSelector:@selector(requestDone:)];
                [downloadAFileRequest setDidFailSelector:@selector(requestWentWrong:)];
                [downloadAFileRequest setShowAccurateProgress:YES];

                [self.networkQueue addOperation:downloadAFileRequest];
                //----
            }

            [self.networkQueue go];


        }





    }

    -(void)queueCompleted:(ASINetworkQueue*)queue{

        NSLog(@"queueCompleted");

       self.tblViewDownload.userInteractionEnabled = YES;

        UIProgressView *progressv = (UIProgressView*)queue.downloadProgressDelegate;

        if (progressv)
            [progressv removeFromSuperview];


        if ( index < [myUrlArray count] ){

            index++;

            [self downLoadPoems];
        }

    }


    - (void)requestDone:(ASIHTTPRequest *)request
    {
        NSLog(@"request done");
        NSString *response = [request responseString];
    }

    - (void)requestWentWrong:(ASIHTTPRequest *)request
    {
        NSLog(@"request went wrong");

        NSError *error = [request error];
    }

    - (void)viewDidUnload
    {
        [super viewDidUnload];
        // Release any retained subviews of the main view.
    }

    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    {
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
    }
4

3 回答 3

1

几点观察:

  1. 您设置setDownloadProgressDelegate在 中ASINetworkQueue,但如果您想跟踪各个下载的进度,您可能希望改为在 中进行ASIHTTPRequest。这样,您理论上可以相应地更新多个下载。

  2. 我这么说的原因之一是您当前正在创建networkQueue添加单曲ASIHTTPRequest并将其启动。从理论上讲,您可以将一大堆排队ASIHTTPRequest并踢掉它们,每个更新自己的UIProgressView.

  3. 最大的问题是你的cellForRowAtIndexPath.

    • 首先,您不应该真正为每个使用唯一的单元格标识符。你失去了所有的内存优化;

    • 您应该检查是否dequeueReusableCellWithIdentifier返回nil(如果您使用带有原型单元的情节提要,这不是问题,但我假设您在这里没有这样做),如果这样做,则创建表格视图和您需要的任何控件;

    • dequeueReusableCellWithIdentifier但是,无论是否返回,您都应该设置标签并更新进度条nil;和

    • 就个人而言,使用进度条,如果进度条已经存在,我发现它更容易删除,然后再次添加它,无论是否dequeueReusableCellWithIdentifier成功。

  4. 您可能想要跟踪“行”对象的数组,例如,这些对象具有正在下载的 URL,但更重要的是,保留的UIProgressView对象(因为烦人的是,它downloadProgressDelegate是一个assign属性,不会被保留因此,您需要跟踪当前正在进行的所有请求的进度条(无论单元格是否可见,是否已出列),而不仅仅是一个 UIProgressView。

  5. 顺便说一句,看起来您正在将东西分派到后台队列。你真的不需要这样做,因为ASINetworkQueue所有这些东西都为你做。您可能想要这样做可能有技术原因,但我认为没有必要,因为我认为这些东西已经异步工作。如果您真的想在另一个队列中启动它,那很好,但请记住将您的 UI 更新分派回主队列,因为您永远不应该从后台进行 UI 更新。

仅供参考,在下面的代码示例中,我使用了我经常用于表格视图的代码模式,特别是我的表格视图有一个模型,该模型由一个 NSArrayRow对象组成,它跟踪我需要为表格视图的每个单元格做什么。

@interface Row : NSObject

@property (nonatomic, strong) NSString *author;
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) UIProgressView *progress;
@property (nonatomic, strong) NSString *urlString;

@end

我将按如下方式使用它:

@interface SampleViewController ()

@property (nonatomic, strong) NSArray *rows;
@property (nonatomic, strong) ASINetworkQueue *networkQueue;

@end

@implementation SampleViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.rows = [self loadImageUrls];

    [self downloadStuff];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return [self.rows count];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 75.0;
}

#define kTitleTag 1
#define kAuthorTag 2
#define kProgressViewTag 3

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *CellIdentifier = @"asi";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    UILabel *lblTitle, *lblAuthor;

    // if you could use storyboards, a lot of this silliness goes away

    if (cell == nil)
    {
        // but in the world of nibs, you have to create the custom controls when you create the cell

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        lblTitle = [[UILabel alloc]initWithFrame:CGRectMake(65, 10, 220, 25)];
        lblTitle.backgroundColor = [UIColor clearColor];
        lblTitle.font = [UIFont boldSystemFontOfSize:15.0];
        //lblTitle.font = [UIFont fontWithName:@"Palatino-Bold" size:15.0];
        lblTitle.tag  = kTitleTag;
        [cell.contentView addSubview:lblTitle];

        lblAuthor = [[UILabel alloc]initWithFrame:CGRectMake(65, 30, 220, 25)];
        lblAuthor.backgroundColor = [UIColor clearColor];
        lblAuthor.font = [UIFont italicSystemFontOfSize:13.0];
        lblAuthor.textColor = [UIColor grayColor];
        lblAuthor.tag = kAuthorTag;
        [cell.contentView addSubview:lblAuthor];
    }
    else
    {
        // if you're recycling a cell, then link up with it's controls

        cell.textLabel.backgroundColor = [UIColor clearColor];
        cell.detailTextLabel.backgroundColor = [UIColor clearColor];

        lblTitle = (UILabel *)[cell.contentView viewWithTag:kTitleTag];
        lblAuthor = (UILabel *)[cell.contentView viewWithTag:kAuthorTag];

        UIProgressView *oldProgressView = (UIProgressView *)[cell.contentView viewWithTag:kProgressViewTag];
        if (oldProgressView && [oldProgressView isKindOfClass:[UIProgressView class]])
        {
            [oldProgressView removeFromSuperview];
        }
    }

    Row *row = [self.rows objectAtIndex:indexPath.row];

    lblTitle.text = row.title;
    lblAuthor.text = row.author;

    if (row.progress)
    {
        row.progress.frame = CGRectMake(0, 55, 200, 25);
        [cell.contentView addSubview:row.progress];
    }

    return cell;
}

-(void)downloadStuff
{    
    ASINetworkQueue *networkQueue = [[ASINetworkQueue alloc] init];

    [networkQueue setQueueDidFinishSelector:@selector(queueCompleted:)];
    [networkQueue setDelegate:self];

    NSFileManager *fileManager = [NSFileManager defaultManager];
    [fileManager createDirectoryAtPath:[[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:@"ASIHTTP"]
           withIntermediateDirectories:NO
                            attributes:nil
                                 error:nil];

    for (NSUInteger i = 0; i < [self.rows count]; i++)
    {
        Row *row = [self.rows objectAtIndex:i];

        row.progress = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar];
        row.progress.tag = kProgressViewTag;

        NSIndexPath *myIP = [NSIndexPath indexPathForRow:i inSection:0];
        UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:myIP];
        if (cell)
        {
            // if the cell is visible, add the progress view to it

            row.progress.frame = CGRectMake(0, 55, 200, 25);
            [cell.contentView addSubview:row.progress];
        }

        NSString *urlString = row.urlString;

        ASIHTTPRequest *request;
        request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:urlString]];
        NSString *filename = [urlString lastPathComponent];
        [request setUserInfo:[NSDictionary dictionaryWithObject:@"request1" forKey:@"name"]];
        [request setDownloadDestinationPath:[[[[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:@"ASIHTTP"] stringByAppendingPathComponent:filename] stringByAppendingFormat:@"%1d", i]];
        [request setShouldContinueWhenAppEntersBackground:YES];
        [request setDelegate:self];
        [request setDidFinishSelector:@selector(requestDone:)];
        [request setDidFailSelector:@selector(requestWentWrong:)];
        [request setDownloadProgressDelegate:row.progress];
        [request setShowAccurateProgress:YES];

        [networkQueue addOperation:request];
    }

    [networkQueue go];
}

-(void)queueCompleted:(ASINetworkQueue*)queue
{    
    NSLog(@"%s queueCompleted", __FUNCTION__);
}

- (void)requestDone:(ASIHTTPRequest *)request
{
    NSLog(@"%s request done: %@", __FUNCTION__, [request responseString]);

    [request.downloadProgressDelegate removeFromSuperview];

    // find which row it's on and remove it from that one

    for (Row *row in self.rows)
    {
        if (row.progress == request.downloadProgressDelegate)
            row.progress = nil;
    }

    // and let it go (obviously, non-ARC, release)

    request.downloadProgressDelegate = nil;
}

- (void)requestWentWrong:(ASIHTTPRequest *)request
{
    NSLog(@"%s request went wrong err = %@", __FUNCTION__, [request error]);
}

- (NSArray *)loadImageUrls
{
    NSMutableArray *results = [[NSMutableArray alloc] init];

    for (NSInteger i = 0; i < 100; i++)
    {
        Row *row = [[Row alloc] init];
        row.urlString = @"http://host/test/bigfile";
        row.title = [NSString stringWithFormat:@"Title %1d", i];
        row.author = [NSString stringWithFormat:@"Author %1d", i];

        [results addObject:row];
    }

    return results;
}

显然,您必须为自己的目的自定义它(例如,我为自己的目的进行了调整;生命太短了,我无法浪费时间编写非 ARC 代码;等等),但它向您展示了我个人如何解决我的问题视为您提供的代码示例的主要缺陷。我认为这需要相当大的扩展(ASINetworkQueue如果我们离开,请优雅地取消,也许只加载ASIHTTPRequests可见单元格等),但我会把它留给你。

于 2012-08-10T22:07:35.150 回答
1

每次 tableView 要求您提供一个单元格时,您都在上面创建一个新单元格 - 您应该回收单元格是不正确的(Apple 文档中的此处和其他地方有大量示例说明如何执行此操作。)

现在,更新单元格中的进度条有一些您没有处理的复杂性。首先,progressBar 的对象会随着表格的滚动而改变——它会从你的下方改变。假设您有一个部分可以使步骤更容易(但这些也适用于多个部分):

因此,您只能通过执行以下操作来更新它:

  • 您的下载想要更新进度。它必须确定具有该进度条的表格行(如果您将进度条添加到单元格,则在该视图上设置标签以便以后更容易找到它)

  • 然后上面的代码向 UITableView 询问可见单元格的列表,并确定它需要更新的单元格是否可见 - 如果不可见,则它什么也不做。

  • 假设单元格是可见的,它会向单元格询问其进度条(即 [cell.contentView viewWithTag:...]),然后更新当前值(此进度条可能以前由于回收而显示其他文件)。

在您的 cellForRowAtIndexPath: 中,您尝试回收一个单元格,如果失败,您将创建一个新单元格。在该代码之后,您不能对任何视图做出任何假设 - 您需要更新 progressBar 最大值,将当前值设置为下载的当前值,更改任何标签文本等。

于 2012-08-10T13:43:44.867 回答
0

使用此方法

  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
    (NSIndexPath *)indexPath

{
    NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d", indexPath.row];

    UITableViewCell *cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero]autorelease];

    UILabel *lblTitle, *lblAuthor;





        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        lblTitle = [[[UILabel alloc]initWithFrame:CGRectMake(65, 10, 220, 25)]autorelease];
        lblTitle.backgroundColor = [UIColor clearColor];
        //lblTitle.font = [UIFont boldSystemFontOfSize:15.0];
        lblTitle.font = [UIFont fontWithName:@"Palatino-Bold" size:15.0];
        lblTitle.text = @"Sample title";
        [cell.contentView addSubview:lblTitle];

        lblAuthor = [[[UILabel alloc]initWithFrame:CGRectMake(65, 30, 220, 25)]autorelease];
        lblAuthor.backgroundColor = [UIColor clearColor];
        lblAuthor.font = [UIFont italicSystemFontOfSize:13.0];
        lblAuthor.textColor = [UIColor grayColor];
        lblAuthor.text = @"sample authior";
        [cell.contentView addSubview:lblAuthor];





    return cell;
}
于 2012-08-10T13:20:38.360 回答