4

UIImageView セルの UITableView を実装します。各セルは、NSTimer を介して 5 秒ごとに定期的に更新されます。各画像はバックグラウンド スレッドでサーバーから読み込まれ、そのバックグラウンド スレッドから を呼び出して新しい画像を表示する UI も更新しperformSelectorOnMainThreadます。ここまでは順調ですね。

現在、現在のセルに画像が読み込まれるまで待たずに、新しいセルにすばやくスクロールすると問題に直面します。ただし、その新しいセルには、新しいセルの画像ではなく、前のセルの画像が表示されます。NSTimer の次のラウンドでは画像が正しく表示されますが、最初はユーザーを混乱させる可能性があります。

UITableView のセルを再利用しないと問題はなくなりますが、アプリに表示されるセルの数を考えると、これはオプションではありません。

したがって、私が考えることができる唯一の解決策は、ユーザーがスクロール アクションを実行していることがわかっている場合、古い画像を表示しようとしているバックグラウンド スレッドをキャンセル (または強制終了) することです。

これはベストプラクティスではないのではないかと思うので、アドバイスを求めてください。

(私の要件は、サーバーからロードされたループ内の一連の画像を表示することであるため、SDWebImageも使用できません)

// In MyViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ...
    NSTimer* timer=[NSTimer scheduledTimerWithTimeInterval:ANIMATION_SCHEDULED_AT_TIME_INTERVAL 
                                                target:self 
                                              selector:@selector(updateImageInBackground:) 
                                              userInfo:cell.imageView 
                                               repeats:YES];
    ...
}

- (void) updateImageInBackground:(NSTimer*)aTimer
{  
    [self performSelectorInBackground:@selector(updateImage:)
                       withObject:[aTimer userInfo]];
}  

- (void) updateImage:(AnimatedImageView*)animatedImageView 
{      
    @autoreleasepool { 
        [animatedImageView refresh];
    }
}  

// In AnimatedImageView.m
-(void)refresh
{
    if(self.currentIndex>=self.urls.count)
        self.currentIndex=0;

    ASIHTTPRequest *request=[[ASIHTTPRequest alloc] initWithURL:[self.urls objectAtIndex:self.currentIndex]];
    [request startSynchronous];

    UIImage *image = [UIImage imageWithData:[request responseData]];

    // How do I cancel this operation if I know that a user performs a scrolling action, therefore departing from this cell.
    [self performSelectorOnMainThread:@selector(performTransition:)
                       withObject:image
                    waitUntilDone:YES];
}

-(void)performTransition:(UIImage*)anImage
{
    [UIView transitionWithView:self duration:1.0 options:(UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionAllowUserInteraction) animations:^{ 
        self.image=anImage;
        currentIndex++;
    } completion:^(BOOL finished) {
    }];
}
4

1 に答える 1

1

わかりました...これを行う別の方法は、「画像リクエストコード」をAnimatedImageViewに配置し、新しい画像URLを設定するたびに保留中のリクエストを無効にすることです。

// your controller
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    ...
    [cell.imageView setDistantImage:imageURL];
    ...    
    }

次に、Cellクラスで、「setDistantImage」がASIHttpRequestを作成し、前のリクエストを無効にします

//your ImageView class

@property (...) ASIHttpRequest *distantImageRequest;

- (void) setDistantImageUrl:(NSUrl *)imageUrl
{
    //clear previous request
    [distantImageRequest clearDelegatesAndCancel];
    //set a new request, with the callBack embedded directly in this ImageView class
    ... 
}

//animation and callBacks methods in this ImageView class too...
于 2012-07-23T10:26:55.457 に答える