2014-12-03 5 views
5

나는이 오류를 완전히 조사해 왔으며 비슷한 문제가 있지만 해결할 수없는 몇 가지 게시물을 찾았습니다.정적 및 동적 UITableViewController 내용을 섞으면 NSRangeException이 발생합니다.

I는 섹션을 갖는다 (SB 정적으로 선언)가있는 UITableViewController 가지고 제 0 (레시피)을 104 개 세포와 정적 인, 제 1 단계 (풍미) 이것은

Storyboard Screenshot

동적이어야

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    rows = [[NSMutableArray alloc] initWithArray:@[@"test",@"test",@"test",@"test",@"test",@"test",@"test"]]; 
} 


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
// Return the number of sections. 
    return 2; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
// Return the number of rows in the section. 
    switch (section) { 
     case 0: 
     return 4; 
     break; 
     case 1: 
     return rows.count; 
     break; 

     default: 
     break; 
    } 

    return 1; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    UITableViewCell *cell; 

    switch (indexPath.section) { 
     case 0: 
     return [super tableView:tableView cellForRowAtIndexPath:indexPath]; 
     break; 

     case 1: 

     cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; 
     if (!cell) 
     { 
// create a cell 
      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"]; 
     } 
     cell.textLabel.text = [rows objectAtIndex:indexPath.row]; 
     return cell; 

     default: 
     break; 
    } 

    return cell; 
} 

이제 실행할 때 내가지고있어 오류는 다음과 같습니다 : 'NSRangeException', 이유 : 나는 시험에 사용하고 코드 '*** - [__ NSArrayI objectAtIndex :] : 인덱스 1 범위를 넘는 [0 .. 0] '

나는 작은 어딘가에 뭔가를 놓친다는 것을 알고 있는데, 누군가 나를 도울 수 있습니까? 나는이 오류가 발생하는 이유를 발견 같은

+0

내가 당신의 링크에 도움이되는 방법이 표시되지 않습니다이 http://stackoverflow.com/a/9428324/285190 – Flexicoder

+0

에서 살펴 이 문제는 거기에 설명 된 문제가 내 것과 같지 않다는 것을 제외하고는 UITableViewController와 UIViewController를 사용하지 않고 – CRE8IT

+0

numberOfRowsInSection 직후에 충돌이 발생하고 CellForRowAtIndexPath에도 적용되지 않는다. – CRE8IT

답변

6

실제 문제는 동적 및 정적 tableViewController가 작동하는 방식입니다.

동적 UITableViewController를 만드는 경우 대부분의 메서드는 nil 또는 0 또는 다른 기본값을 반환합니다. 따라서 UITableViewController 하위 클래스에서 덮어 쓰지 않으면 아무런 문제가 발생하지 않습니다.

정적 UITableViewController를 만드는 경우 대부분의 메서드는 스토리 보드에 반환 할 항목을 "묻습니다". 실제로 필요한 모든 데이터를 포함하는 보조 저장소와 같은 개인 배열과 같은 것이있을 것입니다. 그리고이 배킹 스토어에 질의하는 메소드를 덮어 쓰지 않으면 기본 구현은 배열에 존재하지 않는 인덱스의 객체를 요청할 것입니다.


문제는 tableView에 2 개의 섹션과 2 개의 행이 있다는 것입니다.그래서 tableView 두 번째 섹션에서 두 번째 행에있는 셀의 높이 같은 것들에 대해 정적 UITableViewController 묻습니다. 그러나이 indexPath는 정적 tableView에서 사용되는 보조 저장소에 존재하지 않습니다 (단 하나의 행만 두 번째 섹션에 배치하기 때문에).

그래서 tableView가 정적 테이블 저장소에없는 정보에 액세스하려는 경우 몇 가지 dataSource 및 delegate 메소드를 구현하고 사용자 고유의 값을 반환해야합니다.

예외 호출 스택을 보면 이러한 메소드를 볼 수 있습니다.

예컨대 :

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]' 
*** First throw call stack: 
(
    0 CoreFoundation 0x000000010ebaaf35 __exceptionPreprocess + 165 
    1 libobjc.A.dylib 0x000000010e843bb7 objc_exception_throw + 45 
    2 CoreFoundation 0x000000010eaa301e -[__NSArrayI objectAtIndex:] + 190 
    3 UIKit    0x000000010f4dc856 -[UITableViewDataSource tableView:heightForRowAtIndexPath:] + 109 
    4 UIKit    0x000000010f21026b __66-[UISectionRowData refreshWithSection:tableView:tableViewRowData:]_block_invoke + 302 
    5 UIKit    0x000000010f20f8fe -[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 4125 
    6 UIKit    0x000000010f214e45 -[UITableViewRowData rectForFooterInSection:heightCanBeGuessed:] + 320 
    7 UIKit    0x000000010f214f3a -[UITableViewRowData heightForTable] + 56 

호출 스택의 인덱스 3 당신이 -[UITableViewDataSource tableView:heightForRowAtIndexPath:] 예외를 제기 objectAtIndex: 코드라는 것을 볼 수 있습니다. 이 작업을 중단하지 않으면 백엔드 저장소로 호출을 중계하는 방법 중 하나입니다. 따라서이 메서드를 구현하고 유용한 것을 반환해야합니다. 그런 다음 더 이상 예외가 없을 때까지 계속합니다.

필요한 방법은 tableView의 구성에 따라 달라질 수 있습니다. 나는 보통 이러한 예외의 원인이 네 가지를 구현, 그래서 당신은 당신이하지 덮어 UITableViewDataSource/위임 방법에 의해 발생하는 많은 예외를 볼 경우 수행해야 할 패턴을 볼 수 있습니다 여기

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 
    CGFloat height = 0; 
    if (section == 0) { 
     // static section 
     height = [super tableView:tableView heightForHeaderInSection:section]; 
    } 
    return height; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { 
    CGFloat height = 0; 
    if (section == 0) { 
     // static section 
     height = [super tableView:tableView heightForFooterInSection:section]; 
    } 
    return height; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    CGFloat height = 44; 
    if (indexPath.section == 0) { 
     // static section 
     height = [super tableView:tableView heightForRowAtIndexPath:indexPath]; 
    } 
    return height; 
} 

- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSInteger indentationLevel = 0; 
    if (indexPath.section == 0) { 
     // static section 
     indentationLevel = [super tableView:tableView indentationLevelForRowAtIndexPath:indexPath]; 
    } 
    return indentationLevel; 
} 

과 조금입니다 코드에서 정적 콘텐츠를 더욱 독립적하기 위해 속임수 :

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    if (section == 0) { 
     // static section 
     return [super tableView:tableView numberOfRowsInSection:section]; 
    } 
    return self.objects.count; 
} 

당신이 super 매우 유용하게 호출, 동적 및 정적 세포를 혼합합니다.

+0

가능한 해결책을 제시하는 것 외에도, 이제는 설명을 통해 프로세스의 전체 복잡성을 이해합니다.나는 그것을 최대한 빨리 시도해보고 – CRE8IT

+0

이 솔루션은 매력처럼 작동했습니다. 예외 스택과 관련하여 프로세스의 배경을 설명하기 때문에이 대답을 가장 유용하게 선택했습니다 ... 정말 고마워요! – CRE8IT

0

너무 많은

덕분 그래서 보인다. 이제 문제를 올바르게 해결했는지 아니면 프로그래밍 방식으로 다른 방법이 있는지 ...

내 솔루션은 다음과 같습니다. SB에서 동적 인 섹션을 선택하고 포함될 최대 행 수를 제공합니다. 본질적으로, 제 경우에는 사용자가 30 가지 이상의 맛을 레서피에 추가 할 수 없으므로이 섹션에 30 행을 제공했습니다.

응용 프로그램을 실행하는 경우, 내 어레이는 단지 7 개체가 I는 섹션 (30)에 행을 설정하지만, 단지 어레이에 정의 7 렌더링하고 다른 23

표시되지 않는다 그 오류가 발생하는 이유는 정적 및 동적 섹션을 혼합하고 싶을 때 작동하도록 테이블을 정적으로 정의해야한다는 것입니다. 정적 모드와 SB에서는 코드에서 섹션에 대해 SB에있는 셀 수를 읽는 것처럼 보입니다. 이 숫자가 데이터 배열보다 작 ​​으면 NSRangeException이 발생합니다 ...

현재이 문제를 해결하는 방법을 알고 있다면 30 개 이상의 셀을 가질 수 없다는 것을 알기에 이것은 내 솔루션입니다. 보다 역동적 인 방법을 알려주십시오

1

이 동작은 사소한 것 같지 않습니다. 모든 메소드를 NSIndexPath으로 대체해야 할 수도 있습니다. 자세한 내용은 discussionthis one을 읽을 수 있습니다.

+0

Apple에서 하나의 스레드를 놓친 것이 도움이 될 것 같습니다 ... 최대한 빨리 시도해 보겠습니다. – CRE8IT

0

나는 행 높이에 대해 UITableViewAutomaticDimension을 super로 바꾸고 예상 행 높이에 대한 대리자 메서드를 추가했습니다. iOS 9에서는 iOS8에서 자동으로 확장되는 행이 확장되지 않는 문제가있었습니다. 내 정적 세포도 동적 높이 였고 동적 세포는 고정 된 높이였습니다. }

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { 
return 44; 

}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath { 
CGFloat height = 44; 
if (indexPath.section == 0) { 
    // static section 
    height = UITableViewAutomaticDimension; 
} 
return height;