iOS指南系列:程序运行非我所设想:tableview
2012-04-14 23:33
429 查看
这个题目实在吧:)我们接上篇讲,fix那么多问题后,出来的table居然是没有内容的!
Getting Started: When What’s Supposed to Happen, Doesn’t
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ return @"States"; } - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { return @"USA"; } //可以用来显示一些当前更新时间,网络连接状态等信息
using
insertRowsAtIndexPaths:withRowAnimation:and
deleteRowsAtIndexPaths: withRowAnimation:
[/code]
我们完成之前的步骤后,经过大量的调试工作后应用程序运行没有崩溃。但它显示了出人意料的空表,像这样:
当你期待一些事情发生,但它没有发生,这类问题一般比较困难,它没有错误提示的!但也有一些技巧,你可以使用来解决。先来看看本教程将使用NSLog()/或者断点来处理这个问题。
为表视图控制器类是listViewController的 Segue identity进行后,应用程序应该载入ListViewController,并显示在屏幕上的view。确保视图控制器的方法实际是被调用到了是可以测试这个假设的。一般而言我们会在 viewDidLoad中,似乎像是一个很好的地方。
在ListViewController.m,
增加 NSLog() 在函数 viewDidLoad 中:
- (void)viewDidLoad { [super viewDidLoad]; NSLog(@"viewDidLoad is called"); } |
me按钮。尝试一下。调试信息没有出现在Debug窗格。这意味着在ListViewController类没有被使用到,否则肯定会进入到viewdidload!
这通常意味着,你可能忘了告诉storyboard要使用该表的视图控制器ListViewController类;也许就直接使用了默认的tableviewcontroller的控制器。
Yep, the Class field in the Identity Inspector is set to the default value, UITableViewController. Change it to ListViewController and run the app again. Now the “viewDidLoad is called” text will appear
in the Debug output:
没错,在身份检查的类字段发现其设置为默认值,UITableViewController。改变它为ListViewController,并再次运行该应用程序。现在“viewDidLoad中添加的”文字会出现在调试窗口中,但是!
Problems[18375:f803] You tapped on: <UIRoundedRectButton: 0x6894800; frame = (119 189; 82 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x68948f0>> Problems[18375:f803] viewDidLoad is called |
Note: Whenever
your code doesn’t appear to do anything, place a few NSLog() statements
in strategic places, to see whether certain methods are actually being called and which path the CPU takes through these methods. Use NSLog() to test your assumptions about what the code does.
关于断言:
Assertion Failures
新的crash有点意思,是 SIGABRT 类型, Debug 输出窗口显示内容:
Problems[18375:f803] *** Assertion failure in -[UITableView _createPreparedCellForGlobalRow: withIndexPath:], /SourceCache/UIKit_Sim/UIKit-1912.3/UITableView.m:6072 |
- (void)doSomethingWithAString:(NSString *)theString { NSAssert(string != nil, @"String cannot be nil"); NSAssert([string length] >= 3, @"String is too short"); . . . } |
您可以使用断言作为一个防御性编程技术,使你总是确保代码的行为预期。通常只在调试版本中断言才会启用,所以他们没有最终发布在App
Store上的应用程序中,不会影响运行的。
在这个例子中,uitableviw的断言出发了问题,你不能确性在什么地方,程序最后因为 内存访问问题,停在main,同时call stack也没有具体的内容帮助我们
按照之前的说法,我们尽力寻找接近的我们能理解的函数,例如其中的layoutSubviews 以及_updateVisibleCellsNow:.
看起来和cell有关
Continue running the app to see if you’re going to get a better error message – remember, you’re currently paused just before the exception will be thrown. Press the Continue Program Execution button, or type the following into the Debug Pane:
继续运行应用程序,看看你会得到更多的错误消息 - 要记得,你目前已暂停的位置在引发二次异常(导致崩溃的)之前。按继续执行程序“按钮,或进入调试窗格中键入以下内容:
(lldb) c |
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:' *** First throw call stack: (0x13ba052 0x154bd0a 0x1362a78 0x99a2db 0xaaee3 0xab589 0x96dfd 0xa5851 0x50301 0x13bbe72 0x1d6492d 0x1d6e827 0x1cf4fa7 0x1cf6ea6 0x1cf6580 0x138e9ce 0x1325670 0x12f14f6 0x12f0db4 0x12f0ccb 0x12a3879 0x12a393e 0x11a9b 0x2722 0x2695) terminate called throwing an exception |
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; NSLog(@"the cell is %@", cell); cell.textLabel.text = [list objectAtIndex:indexPath.row]; return cell; }
你要是了解tabledatasource,肯定能想起来少了什么代码。。。
Problems[18420:f803] the cell is (null) |
nil, something that only happens when the cell with the identifier “Cell” could not be found (because the app uses a storyboard with prototype cells).
假如不是可视化定义cell,一般的代码如下:
UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"Cell"];
if (cell == nil)
cell = [[UITableViewCellalloc]
initWithStyle:UITableViewCellStyleSubtitlereuseIdentifier:@"Cell"];
当然,这是一个愚蠢的错误,你毫无疑问应该在很长一段时间前解决了它,因为Xcode中对此已警告通过方便的编译器警告:“原型细胞必须有重用标识符。”我告诉你不要忽略这些警告! :P
打开storyboard, 选中cell (the single cell at the top of the table view that says “Title”,要注意的是,在缩略图下,无法选中的,先放大), 设置 identifier 为 Cell:
这个修改完成后,程序告警全消失了,运行程序,debug输出如下:但是还是没有内容可见
Problems[7880:f803] the cell is <UITableViewCell: 0x6a6d120; frame = (0 0; 320 44); text = 'Title'; layer = <CALayer: 0x6a6d240>> Problems[7880:f803] the cell is <UITableViewCell: 0x6877620; frame = (0 0; 320 44); text = 'Title'; layer = <CALayer: 0x6867140>> Problems[7880:f803] the cell is <UITableViewCell: 0x6da1e80; frame = (0 0; 320 44); text = 'Title'; layer = <CALayer: 0x6d9fae0>> Problems[7880:f803] the cell is <UITableViewCell: 0x6878c40; frame = (0 0; 320 44); text = 'Title'; layer = <CALayer: 0x6878f60>> Problems[7880:f803] the cell is <UITableViewCell: 0x6da10c0; frame = (0 0; 320 44); text = 'Title'; layer = <CALayer: 0x6d9f240>> Problems[7880:f803] the cell is <UITableViewCell: 0x6879640; frame = (0 0; 320 44); text = 'Title'; layer = <CALayer: 0x6878380>> |
Verify Your Assumptions
你通过NSLog显示,6个表单元被创建,但仍然没有在表中可见。怎么办?好吧,如果你点选位模拟器,你会发现,现在实际上可以选择在表视图上半个cell。显然,cell是有,但他们只是空白:Time for some more debug logging. Change your previous NSLog() statement to:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; cell.textLabel.text = [list objectAtIndex:indexPath.row]; NSLog(@"the text is %@", [list objectAtIndex:indexPath.row]); return cell; }
现在你记录你的数据模型的内容。运行程序,看看它说的:
Problems[7914:f803] the text is (null) Problems[7914:f803] the text is (null) Problems[7914:f803] the text is (null) Problems[7914:f803] the text is (null) Problems[7914:f803] the text is (null) Problems[7914:f803] the text is (null) |
definitely putting strings into the list array:
[list addObject:@"One"]; [list addObject:@"Two"]; [list addObject:@"Three"]; [list addObject:@"Four"]; [list addObject:@"Five"]; |
NSLog(@"array contents: %@", list); |
Problems[7942:f803] array contents: (null) Problems[7942:f803] array contents: (null) Problems[7942:f803] array contents: (null) Problems[7942:f803] array contents: (null) Problems[7942:f803] array contents: (null) Problems[7942:f803] array contents: (null) |
你应该分配列表中的对象,当您的视图控制器加载内initWithStyle,似乎是一个不错的地方。改变这种状况的方法:
list = [NSMutableArray arrayWithCapacity:10]; |
- (id)initWithStyle:(UITableViewStyle)style { if (self == [super initWithStyle:style]) { list = [NSMutableArray arrayWithCapacity:10]; [list addObject:@"One"]; [list addObject:@"Two"]; [list addObject:@"Three"]; [list addObject:@"Four"]; [list addObject:@"Five"]; } return self; } [/code] |
Problems[7971:f803] array contents: (null) . . . and so on . . . |
=======》
如果你设置断点,也可以清楚地看到initwithsyle没有被调用到,理由是 :
As you may have expected, no such thing happens. initWithStyle: 一般在代码初始化viewctroller用到,而目前是
从nib加载的, initWithCoder:会被调用到。
运行程序,还是crash这次绝对是memory问题了:
cell.textLabel.text = [listobjectAtIndex:indexPath.row];
总结:
1.要了解lifecycle,包括events
2.nslog能帮助验证,但解决问题靠大脑 和知识
相关文章推荐
- iOS开发系列----UI(简单TableView的使用)
- 在ios程序中自动滚动TableView到某行的方法
- [IOS]包含增删改查移动的tableView展示+plist文件保存+程序意外退出保存Demo
- 微信小程序 IOS tableview
- iOS开发-OC之知识树,知识点(包括对象、Block、消息转发、GCD、运行时、runloop、动画、Push、KVO、tableview,UIViewController、提交AppStore)
- 【转来的精】iOS知识树,知识目录(包括对象、Block、消息转发、GCD、运行时、runloop、动画、Push、KVO、tableview,UIViewController、提交AppStore)
- iOS知识树,知识目录(包括对象、Block、消息转发、GCD、运行时、runloop、动画、Push、KVO、tableview,UIViewController、提交AppStore)
- 《iOS 高级编程》之Tableview进阶指南
- [IOS]包含增删改查移动的tableView展示+plist文件保存+程序意外退出保存Demo
- iOS开发系列 ---- UI (TableView的编辑和多项删除操作)
- iOS 使用tableview 代码布局时,tableViewCell宽度问题,运行在iPhone 6plus 仍然显示320
- 在ios程序中自动滚动TableView到某行的方法
- 《iOS 高级编程》之Tableview进阶指南
- IOS开发系列--TableView、多个TableViewCell、自定义Cell、Cell上画画(故事板+代码方式),ios7tableview索引
- [Object-c] 在ios程序中自动滚动TableView到某行的方法
- iOS程序中自动滚动TableView到某行的方法
- IOS每天15个注意点系列之UI-tableView
- IOS开发系列之阿堂教程:tableView的下拉涮新功能实践
- 【iOS系列】-程序开启后台运行
- SAP企业移动平台开发探索系列3 – 苹果手机程序TableView