2017-01-31 6 views
0

カテゴリ(電子、車、商品など)に基づいてサービスからデータを取得するcollectionView(productCollectionView)があります。ロード中にコレクションビューを停止して準備する

ユーザーが電子カテゴリでデータをプルすることを決めたとしましょう。データが読み込まれている間に、ユーザーがカテゴリを変更して新しいデータセットをフェッチしたとしましょう。

私は以下のロジックを実装しましたが、少し遅いです。より良いアプローチがありますか?

-(void) refreshProducts 
{ 
    if([self.pElements count]){ 
     [self.pElements removeAllObjects]; 
     [self.productCollectionView reloadData]; 
    } 
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); 
    dispatch_async(queue, ^(void) { 
     [self loadFromURL]; // fetch new data 
     dispatch_async(dispatch_get_main_queue(), ^{ 
     }); 
    }); 
} 

-(void)loadFromURL { 

    NSMutableDictionary * params = [[NSMutableDictionary alloc]init]; 
    NSString * category = [[NSUserDefaults standardUserDefaults]objectForKey:@"category"]; 
    if (category != NULL && ![category isEqualToString: @""]) { 
     params[@"category"] = category; 
    } 

    // offset increments based on scrolling down, +20 
    params[@"offset"] = [NSString stringWithFormat:@"%d",offset]; 

    [self.manager POST:PRODUCT_URL parameters:params success:^(AFHTTPRequestOperation * _Nonnull operation, id responseObject) { 
      // getting only 20 data every time, and append to the existing array 
      [self.pElements addObjectsFromArray:responseObject]; 
      [self.productCollectionView reloadData]; 
    } failure:^(AFHTTPRequestOperation * _Nullable operation, NSError * _Nonnull error) { 
    }]; 
} 

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    __weak ProductCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];   
    cell.productImage.image = [cell.productImage.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; 
    NSString *URL =[NSString stringWithFormat:@"http://www.xxxx.com/xxxx/images/%@", [[[[pElements objectAtIndex:indexPath.row]objectForKey:@"pdetail"] objectForKey:@"images"]objectForKey:@"pimagePath"]]; 
    cell.productImage.layer.cornerRadius = 10;   
    NSURL *url = [NSURL URLWithString:URL]; 
    NSURLRequest *request = [NSURLRequest requestWithURL:url]; 
    [cell.productImage setImageWithURLRequest:request 
          placeholderImage:nil 
            success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { 

             cell.productImage.image = image; 
             [cell setNeedsLayout]; 

            } failure:nil]; 

    return cell; 
} 

答えて

0

あなたが投稿したコードはあまりにも援助するためにあまりにも曖昧です。

loadFromURLメソッドはすべての商品を読み込んだ後、完了したらコレクションビューに再読み込みを指示します。

trueの場合、ロードが完了するまで何も起こらないため、遅延が発生します。 1つのアイテムを一度にcollectionView(_:cellForItemAt:)にリクエストし、その内容をディスク上のファイルに保存して、そのコンテンツをそのインデックスパスのセルにインストールすることをお勧めします。セルがロードされる前に画面外にスクロールされると、ディスク上のファイルからデータをロードし、再ダウンロードしないことができます。

このアプローチでは、表示されているセルだけがロードされ、コンテンツの読み込みが完了するたびに表示され、画面の更新が早く開始されます。

+0

実際には 'loadFromURL'には' offset'というパラメータがあります。このメソッドを呼び出すたびに、項目のすべてではなく、一度に20項目しか持ちません。私は 'loadURL'で全ての画像を取得せず、imageURLを保存してから' cellForItemAtIndexPath'を使用します。 – hotspring

+0

私は質問を更新しました。もっと明確にするためにコードを追加しました。 – hotspring

+0

しかしレコードをフェッチした後にreloadDataを呼び出すと、コレクションビュー全体が強制的にリロードされます。 –

0

サーバーの高速化やクエリの絞り込みを除いて、計算量を節約する他の手段は、ユーザーがカテゴリを変更したときに現在の飛行中の要求をキャンセルすることだけです。そして、向こう

...新しいものを開始する前に(存在する場合)

[self.productTask cancel]; 
self.productTask = [self.manager POST:PRODUCT_URL parameters:params success:^(AFHTTPRequestOperation * _Nonnull operation, id responseObject) { 
    // etc. 
を最後のポストを取り消し、これを行うプロパティでタスクを保つ...

@property(strong,nonatomic) NSURLSessionDataTask *productTask; 

する

ユーザーの時間知覚をより迅速にするUIトリックがあります。 (@DuncanCは目に見える行だけをロードし、読み込んだときにリロードするのは良い考えですが、小さなバッチで取得することはできません)。そのilkの他のアイデアのいくつかは、プログレスバー、アクティビティインジケータ、またはkitten videosです。

関連する問題