我的UITableView每个部分最多有50行,由plist字典填充,其中包含包含两个字符串(行标题/文件名和文件扩展名)的数组(行对象)的数组(部分)。
选择第1 - 25行(第0-24项),一切正常。但是选择大于26的行(第25项)并且应用程序崩溃。我是一个新手,我尝试研究答案,但我对如何研究这个问题感到茫然。表格每个部分只能有25行吗?
有什么想法吗?谢谢!
乔恩
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSMutableString *key = [categories objectAtIndex:section];
NSMutableArray *sound = [categoriesSounds objectForKey:key];
NSMutableString *soundName = [[sound objectAtIndex: row] objectAtIndex: 0];
NSMutableString *soundOfType = [[sound objectAtIndex: row] objectAtIndex: 1];
if (leftSwitch.on == YES) {
showLeft.text = soundName;
left = [[NSBundle mainBundle] pathForResource:(@"%@", soundName) ofType:(@"%@", soundOfType)];
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL
fileURLWithPath:left], &soundNegZ);
AudioServicesPlaySystemSound (soundNegZ);
if (indexPath != leftOldIndexPath) {
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:leftOldIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
leftOldIndexPath = indexPath;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
if (downSwitch.on == YES) {
showDown.text = soundName;
down = [[NSBundle mainBundle] pathForResource:(@"%@", soundName) ofType:(@"%@", soundOfType)];
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL
fileURLWithPath:down], &soundNegX);
AudioServicesPlaySystemSound (soundNegX);
if (indexPath != downOldIndexPath) {
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:downOldIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
downOldIndexPath = indexPath;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
if (rightSwitch.on == YES) {
showRight.text = soundName;
right = [[NSBundle mainBundle] pathForResource:(@"%@", soundName) ofType:(@"%@", soundOfType)];
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL
fileURLWithPath:right], &soundPosX);
AudioServicesPlaySystemSound (soundPosX);
if (indexPath != rightOldIndexPath) {
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:rightOldIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
rightOldIndexPath = indexPath;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}
对于控制台中的“EXC_BAD_ACCESS”,这是调试器输出(错误跟踪标有星号):
0x91a6cec0 <+0000> mov 0x8(%esp),%ecx
0x91a6cec4 <+0004> mov 0x4(%esp),%eax
0x91a6cec8 <+0008> cmp $0xfffeb010,%ecx
0x91a6cece <+0014> je 0x91a6cf35 <objc_msgSend+117>
0x91a6ced0 <+0016> test %eax,%eax
0x91a6ced2 <+0018> je 0x91a6cf1a <objc_msgSend+90>
0x91a6ced4 <+0020> mov (%eax),%edx
0x91a6ced6 <+0022> push %edi
**0x91a6ced7 <+0023> mov 0x20(%edx),%edi**
0x91a6ceda <+0026> push %esi
0x91a6cedb <+0027> mov (%edi),%esi
0x91a6cedd <+0029> mov %ecx,%edx
0x91a6cedf <+0031> shr $0x2,%edx
0x91a6cee2 <+0034> and %esi,%edx
0x91a6cee4 <+0036> mov 0x8(%edi,%edx,4),%eax
0x91a6cee8 <+0040> test %eax,%eax
0x91a6ceea <+0042> je 0x91a6cef5 <objc_msgSend+53>
0x91a6ceec <+0044> cmp (%eax),%ecx
0x91a6ceee <+0046> je 0x91a6cf00 <objc_msgSend+64>
0x91a6cef0 <+0048> add $0x1,%edx
0x91a6cef3 <+0051> jmp 0x91a6cee2 <objc_msgSend+34>
0x91a6cef5 <+0053> pop %esi
0x91a6cef6 <+0054> pop %edi
0x91a6cef7 <+0055> mov 0x4(%esp),%eax
0x91a6cefb <+0059> mov (%eax),%eax
0x91a6cefd <+0061> jmp 0x91a6cf09 <objc_msgSend+73>
0x91a6ceff <+0063> nop
0x91a6cf00 <+0064> mov 0x8(%eax),%eax
0x91a6cf03 <+0067> pop %esi
0x91a6cf04 <+0068> pop %edi
0x91a6cf05 <+0069> xor %edx,%edx
0x91a6cf07 <+0071> jmp *%eax
0x91a6cf09 <+0073> sub $0x4,%esp
0x91a6cf0c <+0076> push %ecx
0x91a6cf0d <+0077> push %eax
0x91a6cf0e <+0078> call 0x91a6d33f <_class_lookupMethodAndLoadCache>
0x91a6cf13 <+0083> add $0xc,%esp
0x91a6cf16 <+0086> xor %edx,%edx
0x91a6cf18 <+0088> jmp *%eax
0x91a6cf1a <+0090> call 0x91a6cf1f <objc_msgSend+95>
0x91a6cf1f <+0095> pop %edx
0x91a6cf20 <+0096> mov 0xe79d961(%edx),%eax
0x91a6cf26 <+0102> test %eax,%eax
0x91a6cf28 <+0104> je 0x91a6cf30 <objc_msgSend+112>
0x91a6cf2a <+0106> mov %eax,0x4(%esp)
0x91a6cf2e <+0110> jmp 0x91a6ced4 <objc_msgSend+20>
0x91a6cf30 <+0112> mov $0x0,%edx
0x91a6cf35 <+0117> ret
0x91a6cf36 <+0118> nopw %cs:0x0(%eax,%eax,1)
我的cellForRowAtIndexPath方法:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [categories objectAtIndex:section];
NSArray *nameSection = [categoriesSounds objectForKey:key];
static NSString *SectionsTableIdentifier = @"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
SectionsTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SectionsTableIdentifier] autorelease];
}
cell.textLabel.text = [[nameSection objectAtIndex:row] objectAtIndex: 0];
if (leftSwitch.on == YES){
NSUInteger leftRow = [leftOldIndexPath row];
NSUInteger leftSection = [leftOldIndexPath section];
cell.accessoryType = (row == leftRow && section == leftSection && leftOldIndexPath !=nil) ?
UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
}
if (downSwitch.on == YES){
NSUInteger downRow = [downOldIndexPath row];
NSUInteger downSection = [downOldIndexPath section];
cell.accessoryType = (row == downRow && section == downSection && downOldIndexPath !=nil) ?
UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
}
if (rightSwitch.on == YES){
NSUInteger rightRow = [rightOldIndexPath row];
NSUInteger rightSection = [rightOldIndexPath section];
cell.accessoryType = (row == rightRow && section == rightSection && rightOldIndexPath !=nil) ?
UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
}
return cell;
}
答案 0 :(得分:2)
通过分析您的代码,我可以看到一些您可能失败的地方。
首先:
NSMutableString *soundName = [[sound objectAtIndex: row] objectAtIndex: 0];
NSMutableString *soundOfType = [[sound objectAtIndex: row] objectAtIndex: 1];
声音数组中是否有超过25个元素?
其次:
if (indexPath != downOldIndexPath) {
什么是downOldIndexPath?你确定如果你把它传递给这个方法
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:downOldIndexPath];
这是一条正确的索引路径吗?
答案 1 :(得分:0)
当您的应用程序崩溃时,您是否看到调试器控制台中记录的任何错误消息? (如果在调试应用程序时无法查看,请选择“运行”菜单 - &gt; XCode中的“控制台”菜单选项)。你应该在这里看到一些日志条目,这将有助于指明你正确的方向。
答案 2 :(得分:0)
我当前项目中有101行。据我所知,没有限制。
至于崩溃,你能告诉我们更多信息吗?像堆栈跟踪?控制台输出?
答案 3 :(得分:0)
如果您访问的元素多于所持有的数组,则会出现超出范围的异常 - 而不是EX_BAD_ACCESS崩溃。
这意味着您正在尝试访问已发布的内存。有两种可能性:
1)您从阵列中拉出的项目已被释放。这是不太可能的,因为你不得不做额外的发布以摆脱数组中的东西。
2)(最有可能)你已经发布了一个你试图从中获取数据的数组 - 或者更确切地说,你从某个地方获得数组然后忘记保留它(因为大多数事情都是通过其他方法提供给你的)是自动发布的。)
答案 4 :(得分:0)
我遇到同样的问题,我发现你已经通过以下方式解决了这个问题:
感谢Eddie,NSZombieEnabled指出了我正确的方向,我能够解决问题。原来我的索引路径保留计数需要在cellForRowAtIndexPath中增加1。 - Jonathan Cohen 1月25日18:00
对不起,我对iPhone编程有点新鲜,这究竟是什么意思?
我尝试了一些事情,但它们似乎都在工作我只是想知道哪种方法正确!?
我试过这个:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CheckMarkCellIdentifier = @"CheckMarkCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CheckMarkCellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CheckMarkCellIdentifier] autorelease];
}
// need to retain to stop this crashing with rows > ~26
[indexPath retain];
NSUInteger row = [indexPath row];
NSUInteger oldRow = [lastIndexPath row];
// Print the text
cell.textLabel.text = [itemTextList objectAtIndex:row];
// Print the detail text
cell.detailTextLabel.text = [itemDetailTextList objectAtIndex:row];
cell.accessoryType = (row == oldRow && lastIndexPath != nil) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
return cell;
}
另外(另外)我尝试了这两个:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger newRow = [indexPath row];
NSUInteger oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1;
if (newRow != oldRow) {
UITableViewCell *newCell = [tableView cellForRowAtIndexPath: indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath: lastIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
// retain indexPath to use as last index path
lastIndexPath = [indexPath retain];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
和
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger newRow = [indexPath row];
NSUInteger oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1;
if (newRow != oldRow) {
UITableViewCell *newCell = [tableView cellForRowAtIndexPath: indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath: lastIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
// get a copy to use as last index path
lastIndexPath = [indexPath copy];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
现在我正在向最后一个[indexPath copy]摇摆不定,这是从内存管理的角度来看这是正确的方法吗?或者我保留或复制它并不重要吗?
谢谢,
太