1

asinetworkqueue を使用して URL のリストをダウンロードしようとしています。正常にダウンロードされます。しかし、uitableview をスクロールすると、uiprogressview が非表示になります。

つまり、進行状況が行 2 に表示されていて、それをスクロールすると、進行状況ビューが非表示になります。次に、行番号 2 のダウンロードが完了すると、行番号 3 に進行状況ビューが表示されます。

つまり、uitableview をスクロールすると、アクティブな uiprogressview が非表示になります。

更新しました

ここにいくつかの説明があります。行 (行 1 など) のダウンロードが完了していない場合、テーブルビューをスクロールして行 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);
    }
4

3 に答える 3

1

tableView が上で新しいセルを作成するセルを要求するたびに、セルをリサイクルする必要があるのは正しくありません (これを行う方法については、Apple ドキュメントのここや他の場所にたくさんの例があります)。

現在、セル内の進行状況バーの更新には、対処していない複雑さがいくつかあります。まず、progressBar は、テーブルがスクロールするにつれてオブジェクトが変化します - それはあなたの下から変化します。手順を簡単にするために 1 つのセクションがあるとします (ただし、これらは複数のセクションでも機能します)。

したがって、次のようにしてのみ更新する必要があります。

  • あなたのダウンロードは進行状況を更新したいと考えています。そのプログレス バーがあるテーブル行を特定する必要があります (プログレス バーをセルに追加する場合、そのビューにタグを設定すると後で簡単に見つけることができます)。

  • 次に、上記のコードは UITableView に表示セルのリストを要求し、更新する必要があるセルが表示されているかどうかを判断します。表示されていない場合は何もしません。

  • セルが表示されていると仮定すると、セルにプログレスバー (つまり [cell.contentView viewWithTag:...]) を要求し、現在の値を更新します (このプログレスバーは、以前はリサイクルのために他のファイルを表示していた可能性があります)。

cellForRowAtIndexPath: で、セルをリサイクルしようとしますが、失敗した場合は新しいセルを作成します。そのコードの後、どのビューについても仮定を立てることはできません.progressBar maxを更新し、現在の値をダウンロードの現在の値に設定し、ラベルテキストを変更する必要があります.

于 2012-08-10T13:43:44.867 に答える
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 の更新をメイン キューにディスパッチすることを忘れないでください。

Row参考までに、以下のコード サンプルでは、​​テーブルビューに頻繁に使用するコード パターンを使用しています。特に、テーブルビューには、テーブルビューの各セルに必要なものを追跡するオブジェクトの NSArray で構成されるモデルがあります。

@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 に答える
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 に答える