문제

내 코드는 이미지를 비동기 적으로 사용합니다 InternetImage 에서 tableview: cellForRowAtIndexPath: InitwithUrl로 의도를 초기화하고 DownloadImage를 호출하여 메소드. 이 코드는 UitableView의 새로운 셀 UitableViewCell으로 스크롤 한 후에 완벽하게 실행되지만 URL이 두 경우 모두 정확하더라도 이전은 아닙니다. InternetImage의 NSURLConnection Delegate 방법 중 어느 것도 연결의 성공 또는 실패에 대해 알리기 위해 요청되지 않습니다. 부름 reloadData:, setNeedsDisplay:, 그리고 setNeedsLayout: 이미지가 다운로드되지 않기 때문에 아무것도하지 않습니다.

다음은 uitableviewcontroller의 서브 클래스의 코드입니다.

   - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        Object *object = (Object *)[self.array objectAtIndex:indexPath.row];

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"] autorelease];
        }

        cell.textLabel.text = object.attribute;

        if (object.image == nil && object != nil) {
            NSString *URLString = [[MyAppDelegate imageURLFromLink:(object.link) withExtension:@".jpg"]absoluteString];

            InternetImage *asynchImage = [[InternetImage alloc] initWithUrl:URLString object:object];
            [asynchImage downloadImage:self];
        }

        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

        if (object.image != nil && object.thumbnailImage == nil) {

            UIImage *image= (UIImage *) object.image;
            UIImage *thumbnail = [image _imageScaledToSize:CGSizeMake(75.0, 50.0) interpolationQuality:20];
            object.thumbnailImage = thumbnail;
        }
        cell.imageView.image = object.thumbnailImage;

        return cell;
    }
도움이 되었습니까?

해결책

저를 위해 일한 솔루션은 객체로 다운로드하는 책임을 옮기고 이미지 새로 고침을 테이블 셀 자체로 처리 할 책임을 옮기는 것입니다. 객체가 화면에 표시되고 해당 테이블 셀이있는 경우 이미지가 다운로드되면 즉시 새로 고침됩니다.

이 접근법은 다음과 같은 변경이 필요합니다.

  • 이미지를 객체로 다운로드 할 책임을 옮깁니다.
  • 객체를 수정하여 이벤트를 보내기/호출 대의원/이미지가 변경되었을 때 속성이 변경되었음을 알립니다.
  • 서브 클래스 uitableviewcell이 표시 될 객체에 대해 알 수 있도록 할당 할 때 객체에 대한 변경 대의원으로 추가됩니다.

다음은 이것이 어떻게 작동하는지에 대한 스케치입니다.

// in the UITableViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  Object *object = (Object *)[self.array objectAtIndex:indexPath.row];

  ObjectTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"objectcell"];
  if (nil == cell) {
    cell = [[[ObjectTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"objectcell"] autorelease];
  }

  cell.object = object;

  return cell;
}

// in Object

- (void) downloadImageIfNeeded {
  if (nil == image && nil == internetImage) {
     NSString *URLString = [[MyAppDelegate imageURLFromLink:(object.link) withExtension:@".jpg"]absoluteString];

     internetImage = [[InternetImage alloc] initWithUrl:URLString object:object];
     [internetImage downloadImage:self];
  }
} 

- (void) internetImageReady:(InternetImage*)downloadedImage {
  self.image = downloadedImage.image;
  self.thumbnailImage = [image _imageScaledToSize:CGSizeMake(75.0, 50.0) interpolationQuality:20];

  // notify the delegate
  [imageDelegate imageChanged: self];
}

// in ObjectTableViewCell.h
@property (nonatomic, retain) Object *object;

// in ObjectTableViewCell.m
- (Object *) object {
  return object;
}

- (void) setObject: (Object *) obj {
  if (obj != object) {
    object.imageDelegate = nil;
    [object release];
    object = nil;

    if (nil != object) {
      object = [obj retain];
      object.imageDelegate = self;

      [object downloadImageIfNeeded];
      self.textLabel.text = object.attribute;
      self.imageView.image = object.thumbnailImage;

      self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
   }
}

- (void) imageChanged: (Object *) o {
  self.imageView.image = object.thumbnailImage;
}

다른 팁

테이블이로드되면 이미지가 백그라운드에서 다운로드되지 않은 이유를 묻는 경우 tableView:cellForRowAtIndexPath: 만 호출됩니다 indexPaths 화면 셀의.

셀이 화면에 롤을 굴릴 때가 아닌 한 번에 모든 이미지를 다운로드하려면 array 재산 및 미지급 InternetImage 거기에 물체. 이것에 대한 가능성이있는 곳이있을 수 있습니다 viewDidLoad.

그런 다음 구현하십시오 tableView:willDisplayCell:forRowAtIndexPath: UitableView 대의원에서 올바른 지정에 대한 책임을지게합니다. InternetImage 각 셀에 반대하십시오 imageView 재산.

실제로 테이블이 스크롤하는 한 NSURLConnections는 데이터를 검색하지 않는 것 같습니다. 스크롤이 중지되면 즉시 데이터를 계속 검색합니다. 그러나이 동작은 모든 iPhone 응용 프로그램에서 볼 수 있으며 (테이블이 스크롤하는 한 이미지가로드되지 않음) 결국에는 내 응용 프로그램에서도 살기로 결정했습니다. 애플은 의도적으로 이것을했다. 사용자가 매우 빠르게 스크롤하는 경우 장치가 수많은 이미지 요청으로 서버를 망치지 않도록 할 수 있습니다. 또는 언제든지 사용자를 위해 스크롤을 계속 스크롤 할 수도 있습니다.

그러나 천천히 스크롤하는 동안 최소한 작동하고 빠르게 스크롤하는 동안 다운로드를 차단하는 경우가 좋을 경우는 좋을 것입니다.

좋아, 먼저, 여기에 게시 한 내용은 당신이 사용하고있는 내용이 아니거나, InternetImage가 initwithUrl에 응답하지 않기 때문에 언급하지 않은 InternetImage를 수정했습니다 : object :. 또한 Code를 대의원 방법 InternetImagerEady에 포함시키지 않았습니다. 나는 무언가 잘못 될 때 그것이 호출되지 않았다는 것을 이해하지만, 스크롤을 시작하면 호출되며 올바른 경우에서 일어나는 일을 대비하면 사람들이 문제를 진단하는 데 도움이됩니다.

또한 설명에서 스크롤 할 때 발생하는 일은 전적으로 명확하지 않습니다. 분명히 후속 통화는 작동하지만 이전에 시도 된 모든 연결이 그 시점에서 갑자기 시작되거나 완전히 잃어 버렸습니까?

무슨 일이 일어나고 있는지에 관해서는, 위의 이유 때문에 나는 누군가가 당신에게 약간의 추측을 줄 수 있다고 생각하지 않습니다. 내가 마지막 단락에서 말한 일이 일어나고 있다면, 당신의 문제는 (어떤 이유로 든) 메인 스레드 런 루프가 펌프를 소환 할 때까지 nsurlconnections 이벤트를 처리하지 않는다는 것입니다. 이것은 여러 가지 이유, 예를 들어 런 루프가 잘못된 모드에있을 수 있습니다. NSRUNLOOP를 수동으로 실행하거나 InternetImage로 변경하여 Runloop를 명시 적으로 설정하거나 수동으로 다운로드를 시작할 수 있습니다.

두 가지 간단한 두 가지

  1. InternetImage는 일반적인 코코아 프로그래밍 컨벤션과 일치하지 않는 많은 일을하는 것으로 보입니다. 적어도 나를 위해 빨리 읽기가 더 어려워지고 그것이 올바르게 일을하고 있다고 확신하지 못합니다.
  2. _ImagesCaledTosize를 사용하지 마십시오 :. 그것은 개인 애플 방법이며 그들이 당신이 그것을 사용하고 있음을 알면 거부 할 수 있습니다.

답이 없지만 같은 종류의 문제를보고 있다고 말할 수 있습니다.

나는 약간 수정 된 Mark Johnson의 버전을 사용하고 있습니다. AsyncimageView 수업. 이미지에 대한 비동기 요청은 테이블 뷰를 스크롤 할 때까지 대표자 호출을 유발하지 않습니다. 셀을보기에서 벗어나 뒤로 스크롤하자마자 호출이 다시 발생하여 데이터를 올바르게 가져옵니다.

NSURLConnection은 런 루프에 특정 모드에 의존한다는 것을 다른 곳에서 읽었습니다. TableView : CellForIndexPath에서 URLConnection 요청이 시작되는 상황에서 해당 수치가 있는지 모르겠습니다.

nsurlconnection 내부를 디버깅하는 방법은 무엇입니까?

업데이트

좋아, 그래서 나는 메인 스레드의 연결을 명시 적으로 시작 하여이 문제의 특정 인스턴스를 해결했습니다. 연결 설정 코드를 다른 선택기에 넣고 PerformSectorOnMainThread를 통해 호출했으며 모든 것이 다시 좋았습니다.

연결을 시작하는 셀렉터에서 현재 런 루프 모드를 로깅해야합니다. NSURLConnection이 필요로하는 기본 런 루프 모드가 아니라는 것을 알았습니다.

나는 실제로 코드를보고 시간을 보냈다.

~ 안에 InternetImage 이 기능이 있음을 알았습니다. 당신이해야 할 일은이 기능을 얻는 것입니다. TableView "새로 고침". 당신은 나중에 부름을받는 수업에 대의원 기능을 전달함으로써 이것을 할 수 있지만, 이제는 상황이 까다로워집니다. 보기를 떠날 때 다운로드하려는 모든 이미지에 대해 대의원 함수를 "NIL"으로 설정해야합니다.

-(void) internetImageReady:(InternetImage*)downloadedImage
{   
    // The image has been downloaded. Put the image into the UIImageView
    [imageView setImage:downloadedImage.Image];
}

당신이 그것을 얻었을 때 여기에 답을 게시하십시오. 나는 이것이 해결되었는지 여부를보고 싶습니다.

좋은 접근법? 먼저 ImageView를 할당하는 곳을 확인하십시오. 두 번째 이미지가 고정되어있는 경우 전체 코드가 단지 특정 평균을 의미합니다.

if(cell == nil)
{

}

그 상태 측면. 나는 같은 문제에 직면하고 이와 같이 해결되었습니다. 이것이 효과가 있는지 알려주세요.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top