問題描述
我正在嘗試在分組表格視圖中混合動態和靜態單元格:我想在頂部獲得 兩個帶有靜態單元格的部分,然后是 動態單元格部分(請參考下面的截圖).我已將表格視圖內容設置為靜態單元格.
編輯
根據 AppleFreak 的建議,我將代碼更改如下:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{靜態 NSString *CellIdentifier = @"Cell";UITableViewCell *cell;if (indexPath.section <= 1) {//section <= 1 表示靜態單元格單元格 = [超級 tableView:tableView cellForRowAtIndexPath:indexPath];} else {//部分 >1 表示動態單元格CellIdentifier = [NSString stringWithFormat:@"section%idynamic",indexPath.section];單元格 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];}返回單元格;}
但是,我的應用程序崩潰并顯示錯誤消息
<塊引用>由于未捕獲的異常而終止應用程序'NSInternalInconsistencyException',原因:'UITableView 數據源必須從 tableView 返回一個單元格:cellForRowAtIndexPath:'
對于第 0 行和第 0 行.對于第 0 行和第 0 行,從 cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]
返回的單元格為 nil
.p>
我的代碼有什么問題?我的網點有什么問題嗎?我沒有設置任何插座,因為我正在繼承 UITableViewController
并且據說沒有任何用于設置 tableview 的插座(?).有關如何更好地做到這一點的任何建議?
編輯二
我在故事板中重新創建了我的場景(請參閱上面更新的屏幕截圖)并重寫了視圖控制器,以便從一個新的基礎開始.我還按照 applefreak 的建議閱讀了 Apple 論壇中的描述.但是,我使用 numberOfSectionsInTableView:tableView
方法解決了我的第一個問題,其中我將靜態部分的數量(兩個)增加了一個.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {返回 [super numberOfSectionsInTableView:tableView] + 1 ;}
應用程序崩潰并顯示錯誤消息:
<塊引用>由于未捕獲的異常NSRangeException"而終止應用程序,原因:'*** -[__NSArrayI objectAtIndex:]: 索引 2 超出范圍 [0 .. 1]'
即使我遵循了 Apple 和 applefreak 的建議,為什么這段代碼對我不起作用?在 iOS 6 中 tableView 可能發生了一些變化?
解決方案:我現在在下面的答案中使用 AppleFreaks 代碼示例來解決這個問題.謝謝你,AppleFreak!
編輯 III:單元格選擇:
如何在混合(動態和靜態單元格)單元格表格視圖中處理單元格選擇?什么時候調用super
,什么時候調用self tableView
?當我使用
[[super tableView] selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone]
并嘗試使用以下命令檢查選定的索引路徑:
UITableView *tableView = [super tableView];if ( [[tableView indexPathForSelectedRow] isEqual:customGrowthIndexPath] ) { .. }
我得到 nil
的返回值.
由于我找不到錯誤的根源,非常感謝您的幫助
靜態單元格需要調用 super 方法.我假設您將擴展 UITableViewController.見下文
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{靜態 NSString *CellIdentifier = @"Cell";UITableViewCell *cell;/* 根據索引路徑和您的設置檢測單元格是靜態的還是動態的(原型) */if ("Cell 是原型")單元格 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];else if ("單元格是靜態的")單元格 = [超級 tableView:tableView cellForRowAtIndexPath:indexPath];//如果需要,修改單元格屬性返回單元格;}
有關混合單元格的更多信息,請參閱混合靜態和動態表格視圖內容討論在蘋果論壇上.
如果您還沒有閱讀上面的蘋果鏈接,請仔細閱讀.對于動態內容,您將首次使用代碼本身中的給定標識符構建單元格.下次在病房中,您將出列單元而不是構建它!還是老樣子.
此外,請記住靜態數據源認為只有 2 個部分(例如).你不能問它關于第 2 節的問題,因為它認為只有第 0 節和第 1 節.如果你要在表格末尾以外的任何地方插入動態內容,你需要在轉發數據時對 super 撒謊源方法.例如,您的 numberOfRowsInSection: 方法應如下所示:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{如果(部分 == 1){返回 1;}否則如果(部分> 1){部分 - ;//基本上你正在形成動態內容的部分}return [super tableView:tableView numberOfRowsInSection:section];}
關鍵是對你的動態內容進行調整,以便靜態數據源仍然獲得它期望的值
這是完整的工作示例并經過測試.只需復制代碼中的所有以下方法,它應該可以直接工作.當您有混合單元格時,您必須覆蓋所有 tableview 方法.根據您的要求返回numberOfSectionsInTableView"中靜態和動態部分的總數,然后在其余的每個方法中返回;如果有問題的部分或行是靜態的,只需調用 super,如果它是動態的,則像在普通 UITableViewController 子類中那樣傳回相關細節.在此示例中,我只是返回 nil 或硬編碼值.
如需更多信息,請查看蘋果論壇上的 此主題.
- (int)numberOfSectionsInTableView:(UITableView *)tableView{返回 3;}- (NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{返回零;}- (NSString*)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{返回零;}- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{返回否;}- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{返回否;}-(float)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{返回 44.0f;}- (float)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{返回 44.0f;}- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{返回 44.0f;}- (UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{返回零;}-(UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{返回零;}-(int)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath{返回 5;}- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{如果(部分 == 0)返回 2;如果(部分 == 1)返回 2;返回 5;}- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{if(indexPath.section <= 1)return [super tableView:tableView cellForRowAtIndexPath:indexPath];靜態 NSString *CellIdentifier = @"Cell";UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];如果(單元格 == 零)單元格 = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];cell.textLabel.text = @"動態行";返回單元格;}
您不會在 didSelectRowAtIndexPath 中調用 super.這是直截了當的.請參閱下面的代碼.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{int 行 = indexPath.row;[tableView deselectRowAtIndexPath:indexPath 動畫:YES];UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];//處理單元格}
I am trying to mix dynamic and static cells in a grouped table view: I would like to get two sections with static cells at the top followed by a section of dynamic cells (please refer to the screenshot below). I have set the table view contents to static cells.
Edit
Based on AppleFreak's advice I have changed my code as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell;
if (indexPath.section <= 1) { // section <= 1 indicates static cells
cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
} else { // section > 1 indicates dynamic cells
CellIdentifier = [NSString stringWithFormat:@"section%idynamic",indexPath.section];
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
}
return cell;
}
However, my app crashes with error message
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
for section 0 and row 0. The cell returned from cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]
for section 0 and row 0 is nil
.
What is wrong with my code? Could there be any problems with my outlets? I haven't set any outlets because I am subclassing UITableViewController
and supposedly do not any outlets for tableview to be set (?). Any suggestions on how to better do it?
Edit II
I have recreated my scene in storyboard (please refer to my updated screen shot above) and rewritten the view controller in order to start from a new base. I have also read the description in Apple's forum as applefreak suggested. However, I run in my first problem with the method numberOfSectionsInTableView:tableView
, in which I increment the number of static sections (two) by one.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [super numberOfSectionsInTableView:tableView] + 1 ; }
The app crashed with the error message:
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1]'
Why is this code not working for me even though I followed Apple's and applefreak recommendations? It is possible that the tableView has changed a bit in iOS 6?
Solution: I got this to work now using AppleFreaks code sample in his answer below. Thank you, AppleFreak!
Edit III: Cell Selection:
How can I handle cell selection in a mixed (dynamic and static cells) cell table view?
When do I call super
and when do I call self tableView
?
When I use
[[super tableView] selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone]
and try to check for the selected index paths with:
UITableView *tableView = [super tableView];
if ( [[tableView indexPathForSelectedRow] isEqual:customGrowthIndexPath] ) { .. }
I get an return value of nil
.
As I can't find the source of my error, I really would appreciate your help
For static cells you need to call super method. I presume that you will be extending UITableViewController. See below
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell;
/* Detect cell is static or dynamic(prototype) based on the index path and your settings */
if ("Cell is prototype")
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
else if ("Cell is static")
cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
// Modify cell properties if you want
return cell;
}
Also for more information on mixing cells see Mixing static and dynamic table view content discussion on apple forums.
[EDIT]
If you haven't read apple link above then please do so carefully. For dynamic content you will build the cell first time with the given identifier in the code itself. Next time on wards you will dequeue the cell rather than building it! It's the same old way.
Moreover, remember that the static data source thinks there are only 2 sections(for example). You can't ask it about section 2, because it thinks there are only sections 0 and 1. If you're going to be inserting dynamic content anywhere but the end of the table, you need to lie to super when you forward the data source methods. Your numberOfRowsInSection: method, for example, should look something like this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 1) {
return 1;
}
else if (section > 1){
section--; // Basically you are forming sections for dynamic content
}
return [super tableView:tableView numberOfRowsInSection:section];
}
The key is making the adjustment for your dynamic content so that the static data source still gets the values it expects
[EDIT]
Here is the complete working example and tested. Just copy past all of following methods in your code and it should work straight way. You have to override all the tableview methods when you have mixed cells. Return the total number of static and dynamic sections in "numberOfSectionsInTableView" as per your requirements, and then in each of the remaining methods; if the section or row in question is static just call through to super, if it's dynamic pass back the relevant details as you would in a normal UITableViewController subclass. In this example, I am simply returning nil or hard coded values.
For more information check this thread on apple forums.
- (int)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
}
- (NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return nil;
}
- (NSString*)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
return nil;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
-(float)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 44.0f;
}
- (float)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 44.0f;
}
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 44.0f;
}
- (UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
return nil;
}
-(UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
return nil;
}
-(int)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 5;
}
- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(section == 0)
return 2;
if(section == 1)
return 2;
return 5;
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.section <= 1)
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.textLabel.text = @"dynamic row";
return cell;
}
[EDIT]
You don't call super in didSelectRowAtIndexPath. It's straight forward. See below code.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int row = indexPath.row;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
//process the cell
}
這篇關于UITableView:在混合單元格表視圖靜態和動態單元格中處理單元格選擇的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!