滚动uitableview时,UIProgressView被隐藏

时间:2012-08-10 12:40:18

标签: iphone ios ios4 uitableview

我正在尝试使用asinetworkqueue下载网址列表。下载正常。但是当我滚动uitableview时,我的uiprogressview被隐藏了。

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

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

请帮助我克服这个问题。

非常感谢您的时间..

Upadated-实际问题:如果某行没有完成下载(例如第1行),现在如果我滚动tableview并看到第1行,则进度视图甚至会隐藏它还没有完成下载。一旦第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);
    }

3 个答案:

答案 0 :(得分:1)

每当tableView要求您创建一个上面的新单元格时 - 它是不正确的,您应该回收单元格(这里和Apple文档中有关如何执行此操作的大量示例。)

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

所以你应该只通过执行以下操作来更新它:

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

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

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

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

答案 1 :(得分:1)

有几点意见:

  1. 您在setDownloadProgressDelegate中设置了ASINetworkQueue,但如果您想跟踪各个下载的进度,可能需要在ASIHTTPRequest中执行此操作。这样你理论上可以相应地更新多次下载。

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

  3. 最大的问题是你的cellForRowAtIndexPath

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

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

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

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

  4. 您可能希望跟踪一系列“行”对象,例如,这些对象包含正在下载的内容的URL,但更重要的是,保留了UIProgressView个对象(因为,烦人地) ,downloadProgressDelegateassign属性,不会为您保留。因此,您需要跟踪当前正在进行的所有请求的进度条(无论是否为单元格)是否可见,是否已出列,而不仅仅是单一的UIProgressView。

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

  6. 仅供参考,在下面的代码示例中,我使用了经常用于tableviews的代码模式,特别是我的tableview有一个由Row对象的NSArray组成的模型,它跟踪我需要的内容对于tableview的每个单元格。

    @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等等),但我会留给你。

答案 2 :(得分: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;
}