programing

별도의 delegate / dataSource를 사용할 때 UITableView 문제

itsource 2021. 1. 16. 09:45
반응형

별도의 delegate / dataSource를 사용할 때 UITableView 문제


일반적인 설명:

작동하는 것으로 시작하기 위해 UITableViewInterface Builder를 사용하여 Xcode 생성 뷰에 배치되었습니다. 보기의 파일 소유자는 Xcode 생성 하위 클래스로 설정됩니다 UIViewController. 이 서브 클래스에 나는의 구현 작업 추가 numberOfSectionsInTableView: tableView:numberOfRowsInSection:tableView:cellForRowAtIndexPath:테이블보기의를 dataSource하고 delegate인터페이스 빌더의 파일 소유자를 통해이 클래스에 연결되어 있습니다.

위의 구성은 문제없이 작동합니다. 이 문제는이 테이블 뷰 dataSourcedelegate구현을 별도의 클래스 로 옮기고 싶을 때 발생합니다. 테이블 뷰 외에 다른 컨트롤이 뷰에 있고 테이블 뷰 관련 코드를 다른 클래스로 옮기고 싶기 때문입니다. 자신의 수업. 이를 위해 다음을 시도합니다.

  • UITableViewControllerXcode에서 의 새 하위 클래스 만들기
  • 의 알려진 좋은 구현을 이동 numberOfSectionsInTableView:, tableView:numberOfRowsInSection:그리고 tableView:cellForRowAtIndexPath:새로운 서브 클래스
  • InterfaceBuilder UITableViewController에서 기존 XIB 의 최상위 레벨로를 드래그하고 이에 대해 자동으로 생성 된 UIView/ UITableView삭제 UITableViewController한 다음 UITableViewController의 클래스를 새 하위 클래스와 일치하도록 설정합니다.
  • 이전에 작업 제거 UITableView의 기존 s의 dataSourcedelegate연결을하고 새에 연결UITableViewController

완료되면 작업중인 UITableView. 나는 겉보기에 무작위로 발생할 수있는 세 가지 결과 중 하나를 얻게됩니다.

  • UITableView로드 할 때 tableView:cellForRowAtIndexPath:인식하지 못하는 개체에 전송 중임 나타내는 런타임 오류가 발생 합니다.
  • UITableView로드 오류없이 디버거로 프로젝트 나누기
  • 오류 UITableView는 없지만 나타나지 않습니다.

일부 디버깅과이 문제를 재현하기 위해 기본 프로젝트를 만든 경우 일반적으로 위의 세 번째 옵션이 표시됩니다 (오류는 없지만 테이블보기는 표시되지 않음). 좀 NSLog 전화를 추가하고 있지만 것을 발견 numberOfSectionsInTableView:하고는 numberOfRowsInSection:모두가 호출지고, cellForRowAtIndexPath:아니다. 나는 정말 간단한 것을 놓치고 있다고 확신하고, 내가 가진 것보다 더 많은 경험을 가진 누군가에게 대답이 분명 할 수 있기를 바라고 있었다. 이것이 쉬운 대답이 아니라면 일부 코드 나 샘플 프로젝트로 업데이트 해 드리겠습니다. 시간 내 줘서 고마워!

재현 단계를 완료하십시오.

  • Xcode에서 새로운 iPhone OS, View-Based Application을 만들고 호출하십시오. TableTest
  • TableTestViewController.xibInterface Builder에서 열고 UITableView제공된 뷰 화면 으로을 끕니다 .
  • UITableViewdataSourcedelegate-outlet을 이미 TableTestViewController-class를 나타내는 파일의 소유자에 연결하십시오 . 변경 사항 저장
  • Xcode로 돌아가서 다음 코드를 추가하십시오. TableTestViewController.m:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    NSLog(@"Returning num sections");
    return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSLog(@"Returning num rows");
    return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"Trying to return cell");
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
    }
    cell.text = @"Hello";
    NSLog(@"Returning cell");
    return cell;
}
  • Build and Go, 그러면 단어 HelloUITableView

  • 이제이 UITableView논리를 별도의 클래스 로 이동 하려면 먼저 Xcode에서 새 파일을 만들고 UITableViewController하위 클래스를 선택하고 클래스를 호출합니다.TableTestTableViewController

  • 위의 코드 조각을에서 제거 TableTestViewController.m하고에 배치 TableTestTableViewController.m하여이 세 가지 메서드의 기본 구현을 우리의 것으로 바꿉니다.
  • 동일한 파일 내의 Interface Builder로 돌아가서 메인 IB 창으로 TableTestViewController.xib드래그하고 자동으로 제공된 UITableViewControllerUITableView객체를 삭제 합니다.
  • 이 새의 클래스를 설정 UITableViewController하는TableTestTableViewController
  • 이전에 작동하던 기존 바인딩에서 dataSourcedelegate바인딩을 제거하고 UITableView동일한 두 바인딩을 새로 TableTestTableViewController만든 바인딩에 다시 연결합니다 .
  • 변경 사항을 저장하고 Build and Go를 수행하고 내가 얻은 결과를 얻는 경우 UITableView더 이상 제대로 작동하지 않습니다.

솔루션 : iPhone 개발자 포럼 의 추가 문제 해결 및 지원을 통해 솔루션을 문서화했습니다! UIViewController프로젝트 의 주요 하위 클래스에는 UITableViewController인스턴스를 가리키는 콘센트가 필요 합니다. 이를 수행하려면 기본보기의 헤더 ( TableTestViewController.h)에 다음을 추가하면됩니다 .

#import "TableTestTableViewController.h"

IBOutlet TableTestTableViewController *myTableViewController;

Then, in Interface Builder, connect the new outlet from File's Owner to TableTestTableViewController in the main IB window. No changes are necessary in the UI part of the XIB. Simply having this outlet in place, even though no user code directly uses it, resolves the problem completely. Thanks to those who've helped and credit goes to BaldEagle on the iPhone Developer Forums for finding the solution.


I followed your steps, recreated the project and ran into the same problem. Basically you are almost there. There are 2 things missing (once fixed it works):

  • You need to connect the tableView of the TableTestTableViewController to the UITableView you have on the screen. As I said before because it is not IBOutlet you can override the tableView property and make it and IBOutlet:

    @interface TableTestTableViewController : UITableViewController {
        UITableView *tableView;
    }
    
    @property (nonatomic, retain) IBOutlet UITableView *tableView;
    
  • Next thing is to add a reference to the TableTestTableViewController and retain it in the TableTestViewController. Otherwise your TableTestTableViewController may be released (after loading the nib with nothing hanging on to it.) and that is why you are seeing the erratic results, crashes or nothing showing. To do that add:

    @interface TableTestViewController : UIViewController {
        TableTestTableViewController *tableViewController;
    }
    
    @property (nonatomic, retain) IBOutlet TableTestTableViewController  *tableViewController;
    

    and connect that in the Interface Builder to the TableTestTableViewController instance.

With the above this worked fine on my machine.

Also I think it would be good to state the motivation behind all this (instead of just using the UITableViewController with its own UITableView). In my case it was to use other views that just the UITableView on the same screenful of content. So I can add other UILabels or UIImages under UIView and show the UITableView under them or above them.


I just spent many hours pulling my hair out trying to figure out why a UITableView wouldn't show up when when I had it embedded in a separate nib instead of in the main nib. I finally found your discussion above and realized that it was because my UITableViewController wasn't being retained! Apparently the delegate and datasource properties of UITableView are not marked "retain" and so my nib was loading but the controller was getting tossed... And due to the wonders of objective-c I got no error messages at all from this... I still don't understand why it didn't crash. I know that I've seen "message sent to released xxx" before... why wasn't it giving me one of those?!?

I think most developers would assume that structure that they build in an interface builder would be held in some larger context (the Nib) and not subject to release. I guess I know why they do this.. so that the iPhone can drop and reload parts of the nib on low memory. But man, that was hard to figure out.

Can someone tell me where I should have read about that behavior in the docs?

Also - about hooking up the view. First, if you drag one in from the UI builder you'll see that they hook up the view property (which is an IBOutlet) to the table view. It's not necessary to expose the tableView, that seems to get set internally. In fact it doesn't even seem to be necessary to set the view unless you want viewDidLoad notification. I've just broken the view connection between my uitableview and uitableviewcontroller (only delegate and datasource set) and it's apparently working fine.


Yes for some reason (please chime in if anybody knows why...) tableView property of the UITableViewController is not exposed as an IBOutlet even though it is a public property. So when you use Interface Builder, you can't see that property to connect to your other UITableView. So in your subclass, you can create a tableView property marked as an IBOutlet and connect that.

This all seems hacky and a workaround to me, but it seems to be the only way to separate a UITableViewController's UITableView and put it somewhere else in UI hierarchy. I ran into the same issue when I tried to design view where there are things other than the UITableView and that was the way I solved it... Is this the right approach???


I was able to make this work. I built a really nice dashboard with 4 TableViews and a webview with video. The key is having the separate tableView controllers and the IBOutlets to the other tableview controllers defined in the view controller. In UIB you just need to connect the other tableview controllers to the file owner of the view controller. Then connect the tables to the corresponding view controllers for the datasource and delegate.

ReferenceURL : https://stackoverflow.com/questions/254354/uitableview-issue-when-using-separate-delegate-datasource

반응형