开发者

Problem with UITableView as subview in a NIB

The executive summary: I'm trying to use a UITableView as a subview of my window's "main" view; it appears, but when I scroll the window I get the following error message:

2010-11-20 17:17:51.958 xwtf[6997:207] -[NSCFString tableView:cellForRowAtIndexPath:]: unrecognized selector sent to instance 0x5f46550

I have a subclass of ViewController with corresponding NIB file that is loaded by my application delegate. It's your typical New Project template. In that NIB file, I add a UITableView as a subview of view. In Interface Builder, I size it to take up the entire window (i.e. it completely overlaps its parent view).

Now I need to specify a data source and delegate. I create a class named DumbTableHelper like so:

@interface DumbTableHelper : NSObject<UITableViewDelegate, UITableViewDataSource> {
}

So, it's not a subclass of UIViewController, but I'm trying to keep this simple -- all I need is a delegate and data source it can call out to, right? Aside from dealloc, my methods in its .m file are:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  return 1;
}

- (NSInteger)tableView:(UITableView *)tableView
 numberOfRowsInSection:(NSInteger)section {
  return 10;
}

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  static NSString *CellIdentifier = @"DumbTableCell";
  UITableViewCell *cell = [tableView
                           dequeueReusableCellWithIdentifier:CellIdentifier];
  if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                                     reuseIdentifier:CellIdentifier]
            autorelease];
  }
  return cell;
}

As you can see, I'm not even configuring any cell; I just specify 10 rows, which is enough to force scrolling. Anyway, in Interface Builder I drag an object from the library into my NIB. I then change its class name to DumbTableHelper and specify it as the data source and delegate of the UITableView already there. When I run 开发者_如何转开发it, the table appears. When I try to scroll down in the table, I get:

010-11-20 18:19:54.673 xwtf[6997:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFString tableView:cellForRowAtIndexPath:]: unrecognized selector sent to instance 0x5f46550'
*** Call stack at first throw:
(
0   CoreFoundation                      0x0259eb99 __exceptionPreprocess + 185
1   libobjc.A.dylib                     0x0239340e objc_exception_throw + 47
2   CoreFoundation                      0x025a06ab -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3   CoreFoundation                      0x025102b6 ___forwarding___ + 966
4   CoreFoundation                      0x0250fe72 _CF_forwarding_prep_0 + 50
5   UIKit                               0x00321d6f -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:withIndexPath:] + 619
6   UIKit                               0x00317e02 -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:] + 75
7   UIKit                               0x0032c69f -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow:] + 1348
8   UIKit                               0x003247ec -[UITableView layoutSubviews] + 242
9   QuartzCore                          0x0455c481 -[CALayer layoutSublayers] + 177
10  QuartzCore                          0x0455c1b1 CALayerLayoutIfNeeded + 220
11  QuartzCore                          0x045552e0 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 302
12  QuartzCore                          0x04555040 _ZN2CA11Transaction6commitEv + 292
13  QuartzCore                          0x04585ebb _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 99
14  CoreFoundation                      0x0257ff4b __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 27
15  CoreFoundation                      0x02514b27 __CFRunLoopDoObservers + 295
16  CoreFoundation                      0x024ddce7 __CFRunLoopRun + 1575
17  CoreFoundation                      0x024dd350 CFRunLoopRunSpecific + 208
18  CoreFoundation                      0x024dd271 CFRunLoopRunInMode + 97
19  GraphicsServices                    0x02d5d00c GSEventRunModal + 217
20  GraphicsServices                    0x02d5d0d1 GSEventRun + 115
21  UIKit                               0x002beaf2 UIApplicationMain + 1160
22  xwtf                                0x00001af4 main + 102
23  xwtf                                0x00001a85 start + 53
)

So it's calling tableView:cellForRowAtIndexPath: on a.. String? Anyone have any ideas?

I'm sorry if this turns out to be a stupid question -- so far all my table views have been created programmatically by UITableViewController instances, but now I need to add a UITableView as a subview, which doesn't take up the entire screen. I've read the Apple guide on table views and Beginning iPhone Development to make sure I'm not missing anything, but to no avail.

Thanks!


Okay, I've figured out why: My subclass of ViewController that also serves as the File Owner in my NIB file has no declared outlet to DumbTableHelper. The Resource Programming Guide on Nib files at http://developer.apple.com/library/mac/documentation/cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html says:

Objects in the nib file are created with a retain count of 1 and then autoreleased... If you define outlets for nib-file objects, you should always define a setter method (or declared property) for accessing that outlet. Setter methods for outlets should retain their values, and setter methods for outlets containing top-level objects must retain their values to prevent them from being deallocated.

When the table is first displayed, the DumbTableHelper still has a retainCount of 1 and has not yet been autoreleased, so it can be used to populate the rows that are initially displayed. When I scroll, however, it no longer exists in memory. From the stack trace, we can surmise that a string has been allocated in the memory address where the DumbTableHelper used to be, and so it errantly receives the tableView:cellForRowAtIndexPath: message.

Again, simply connecting an outlet from the File Owner to the DumbTableHelper instance in Interface Builder file solves the problem.


I suggest deleting your connections in Interface Builder and trying to re-establish. It certainly seems as if the dataSource outlet has been connected to an NSString in the nib. You could also just try establishing the connection in code, using the delegate and datasource properties of UITableView.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜