2012-07-05 4 views
0

사용자 지정 셀을 표시하는 표보기가 있고 셀에 문서 폴더에서로드하는 이미지가 들어 있습니다. 나는 테이블을 스크롤 할 때, 디스크로부터 이미지를로드하는 것으로부터 오는 것으로 가정하고있는 약간의 지연이 있다는 것을 알아 차렸다. 그러나 이미지가 이미 그 지점에로드되어 있으므로 약간 혼란 스럽습니다.사용자 지정 표 셀 스크롤

이 코드를 최적화하는 방법에 대한 의견을 보내 주시면 감사하겠습니다. 나는 게으른 로딩에 대해 읽었지만 이것이 나에게 적용되는지 확실하지 않다.

테이블을 재사용하고 있는지 확인했습니다.

편집 : 더 나은이 제대로 수행하는 방법을 설명 할 것이다이 두 링크

- (void)configureCell:(BeerCell *)cell 
      atIndexPath:(NSIndexPath *)indexPath 
{ 
    Beer *beer = (Beer *) [self.fetchedResultsController objectAtIndexPath:indexPath]; 
    cell.displayBeerName.text = beer.name; 

    // check to see if there is a cached image already. Use a dictionary. 
    // make sure this is one of your ivars 
    __block UIImage *theImage = [self.imagesCache objectForKey: beer.imagePath]; 

    // If the image is not in your cache, you need to retrieve it. 
    if (!theImage){ 
     // The image doesn't exist, we need to load it from disk, web or render it 

     // First put a placeholder image in place. Shouldn't be any penalties after the 
     // first load because it is cached. 
     cell.beerImage.image = [UIImage imageNamed:@"beer-pic.png"]; 

     // check to see if your image cache dictionary has been created, if not do so now 
     if (_imagesCache == nil) { 
      _imagesCache= [[NSMutableDictionary alloc] initWithCapacity:1]; 
     } 

     // get a weak reference to UITableViewController subclass for use in the block 
     // we do this to avoid retain cycles 
     __weak BeerListViewController *weakSelf = self; 

     // do the heavy lifting on a background queue so the UI looks fast 
     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); 
     dispatch_async(queue,^{ 

      theImage = [UIImage imageWithContentsOfFile:beer.imagePath]; 

      // I added this in because I create the new core data object in this class, and pass 
      // it to the class where I fill out the information about the beer 
      if (theImage) { 

       // Add the image to the cache 
       [weakSelf.imagesCache setObject:theImage forKey:beer.imagePath]; 
       //[weakSelf.imagesCache addObject:theImage forKey:beer.imagePath]; 

       // Check to see if the cell for the specified index path is still being used 
       BeerCell *theCell = (BeerCell *)[weakSelf.tableView cellForRowAtIndexPath:indexPath]; 
       // Per the docs. An object representing a cell of the table 
       // or nil if the cell is not visible or indexPath is out of range. 
       if (theCell){ 
        // dispatch onto the main queue because we are doing work on the UI 
        dispatch_async(dispatch_get_main_queue(),^{ 
         theCell.beerImage.image = theImage; 
         [theCell setNeedsLayout]; 
        }); 
       } 
      } 
     }); 
    }   
    else 
    { 
     // Image already exists, use it. 
     cell.beerImage.image = theImage; 
    } 
} 

답변

1

디스크, 서버에서로드하거나 테이블 뷰의 이미지를 렌더링 할 때마다이를 백그라운드 큐에 넣을 수 있습니다. 그렇게하는 것은 쉽지 않으며 3GS에서도 뛰어난 성능을 얻을 수 있습니다.

매우 큰 이미지에서 테이블 뷰 및 스크롤 뷰의 축소판을 생성하는 데 비슷한 방법을 사용하므로 성능이 매우 좋습니다.

- (void)configureCell:(CustomCell *)cell 
      atIndexPath:(NSIndexPath *)indexPath 
{ 
    CoreDateObject *object = (CoreDateObject *)[self.fetchedResultsController objectAtIndexPath:indexPath]; 
    cell.displayName.text = object.name; 

    // check to see if there is a cached image already. Use a dictionary. 
    // make sure this is one of your ivars 
    UIImage *theImage=[self.imagesCache objectForKey: object.imagePath]; 

    // If the image is not in your cache, you need to retrieve it. 
    if (!theImage){ 
     // The image doesn't exist, we need to load it from disk, web or render it 

     // First put a placeholder image in place. Shouldn't be any penalties after the 
     // first load because it is cached. 
     cell.selectedImage.image=[UIImage imageNamed:@"yourPlaceHolderImage"]; 

     // check to see if your image cache dictionary has been created, if not do so now 
     if (_imagesCache==nil){ 
      _imagesCache=[NSMutableDictionary alloc] initWithCapacity:1]; 
     } 

     // get a weak reference to UITableViewController subclass for use in the block 
     // we do this to avoid retain cycles 
     __weak YourTableViewControllerSubclass *weakSelf=self; 

     // do the heavy lifting on a background queue so the UI looks fast 
     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); 
     dispatch_async(queue, ^{ 

       theImage=[UIImage imageWithContentOfFile:object.imagePath]; 

       // Add the image to the cache 
       [weakSelf.imagesCache addObject:theImage forKey:object.imagePath]; 

       // Check to see if the cell for the specified index path is still being used 
       CustomCell *theCell=(CustomCell *)[weakSelf.tableView cellForRowAtIndexPath:indexPath]; 
       // Per the docs. An object representing a cell of the table 
       // or nil if the cell is not visible or indexPath is out of range. 
       if (theCell){ 
       // dispatch onto the main queue because we are doing work on the UI 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        theCell.selectedImage.image=theImage 
        [theCell setNeedsLayout]; 
       }); 
       } 

    }else{ 
      // Image already exists, use it. 
      cell.selectedImage.image=theImage; 
    } 

    cell.rating.rate = object.rating.doubleValue; 
} 
+0

나는이 솔루션을 좋아하지만 한 가지 문제가있다. 앱을 시작할 때 테이블을 처음로드 할 때 테이블을 스크롤하고 올바른 이미지가 나타나면 아이디어 나 제안이 표시 될 때까지 자리 표시 자 이미지 만 표시됩니다. 내가 사용한 코드로 내 대답을 편집했습니다. – Vikings

+0

솔루션에 도움이되는 자습서를 찾았다면 링크를 크게 평가할 것입니다. – Vikings

+0

앱이로드 될 때 자리 표시자를 얻고 스크롤 할 때 테이블 셀만 업데이트되면 잘못된 결과가 발생하거나 그렇지 않은 경우 특정 상황에 맞게 코드를 수정하십시오. 지금까지 튜토리얼, 체크 아웃 사과의 wwdc 2011 비디오를 사용하여 gcd. – timthetoolman

0
+0

내가 게으른 로딩 보았다,하지만 난 그냥이이었다 설계 한 이유 원래 방법입니다 디스크 – Vikings

+1

에서 읽기, 웹에서 이미지를받지 못했습니다 .. :

이 시도 하지만 이미지 로딩 프로세스를 다른 스레드에 배치해야합니다. 이렇게하면로드 속도가 빨라지고 스크롤 속도가 빨라집니다. – DJPlayer

+0

덕분에 지금은 총을 쏘 겠어 – Vikings

0

cellForRowAtIndexPath:은 테이블 뷰를 스크롤 할 때마다 호출됩니다 ... 그래서 쓰는다면 스크롤 할 수 있습니다. 이 메소드에서 큰 처리 코드. 따라서 가능한 경우 이미지의 배열을 만든 다음 축소판 이미지를 사용합니다. 그런 다음 해당 이미지를 배열의 셀에 추가합니다. 귀하의 스크롤이 원활해질 것이라고 확신합니다.