CustomCell crash in UItableView [duplicate] - iphone

This question already has answers here:
"Auto Layout still required after executing -layoutSubviews" with UITableViewCell subclass
(31 answers)
Closed 9 years ago.
I have been using a customCell.xib with its own customCellClass within a UITableView,which is built without using autoLayout feature(since I need to make it work even on platforms prior to iOS6).
The UITableView fetches this custom made xib cell in its dataSource method.
The dilemma I'm facing is that the UITableView crashes abruptly 50 % of times I run it but executes and shows the tabeview perfectly rest of the times..
I m currently using XCode 4.5.
Here's the crash Log i receive ..
'Auto Layout still required after executing -layoutSubviews.
UITableViewCell's implementation of -layoutSubviews needs to call
super.'

This has been covered in some detail here, and it is not as simple as simply calling [super layoutSubviews];
"Auto Layout still required after executing -layoutSubviews" with UITableViewCell subclass
Try disabling 'translatesAutoresizingMaskIntoConstraints' on each of your views. Auto Layout is somehow being triggered, and that causes this bug on UITableView to pop up.

Your custom cell class implementation overrides layoutSubviews without calling super. That's right there in the crash log!

Related

UIButton not showing on real device while running on Xcode8

Today i run my project on Xcode8. Before that it was executed good and shown all button properly. when i run project on xcode8 simulator and device. few buttons not visible on run time but action performing.
Please assist me on this issue.
Actually, There are some problems in Xcode 8 compiler.
I were having such issue, i have resolved by doing following things
If i have done anyoperation on layer(cornerRadius,bordering,masksToBounds etc.) in viewDidLoad/viewWillAppear/awakeFromNib then move them to either layoutSubViews method or viewDidAppear method.
If I have set left/right view in textfield, then move it also to viewDidAppear or layoutSubviews.
Try most of UI Related operation in viewDidAppear or layoutSubviews

cellForRowAtIndexPath returns nil on device

I spent few hours trying to resolve one very strange issue, but I really don't know how to proceed.
I have a grouped UITableView referenced from XIB populated with custom (subclassed) UITableViewCell cells. All the cells (two section with one cell each) are visible and I am trying to get one of them by calling:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:1];
LocationSearchFilterCell *cell = (LocationSearchFilterCell *)[filterTable cellForRowAtIndexPath:indexPath];
On Simulator 4.2 the cell is returned properly;
On Device 4.0.x the code returns NIL;
On Simulator 4.0.x the code returns NIL;
On Simulator 4.1 the cell is returned properly BUT NOT on Device 4.1.
The strangest thing is that I am using this approach on few other places within the application and the cell is always returned properly. I guess it is some strange combination of me doing something differently combined with some iOS bug.
Any idea ?
P.S. In situation where NIL is returned, by using GDB I get the pointer of the cell when it is created and call:
(gdb) po (void *)[filterTable indexPathForCell:(UITableViewCell *)0x7b08520]
and I get a valid index path (that matches the one I am providing) which means the cell is valid and present into the table view.
I have even tried passing the object returned by this last call (by pointer) and I still get NIL.
Interesting,
It turned out someone is hiding the table view before I try to get the cell (stupid me :)).
What I was doing was, triggering an animation to hide the table view (nested into some methods I am calling from the method where I try to get the cell). Because I was stopped on a breakpoint the animation was also stopped, so it seamed to me like the table view is visible.
What I don't understand still is why the table view is threaded as hidden although the animation is still not finished (and I only change the frame in the animation and set the table hidden after the animation is finished) ?
I guess the answer to this question is the key point why on different combinations of Device / Simulator / iOS I get different behavior. Anyway the solution is as simple as moving the two lines I've posted above at the top of the method.
Thanks to Rits for his question that triggered my reasoning ;)
regards

How can I avoid a crash when VoiceOver encounters UIPickerView as subview of UITableViewCell contentView?

In my app I have a UIPickerView as a subview of a table cell's contentView. I disable scrolling in the table view, and the arrangement works fine under normal circumstances. However, I've found that when VoiceOver (or the Accessibility Inspector) is turned on, the app crashes as soon as the picker is due to get focus.
The error is:
-[UITableViewCellAccessibilityElement numberOfComponents]: unrecognized selector sent to instance 0xc15dc70
What seems to be happening is that VoiceOver is sending messages presumably intended for the UIPickerView (or its own UIAccessibilityElement?) to the UITableViewAccessibilityElement instead.
When I patch UIAccessibilityElement with the following category...
#implementation UIAccessibilityElement (GMPatches)
- (NSInteger)numberOfComponents {
return 0;
}
#end
... I eliminate the crash -- but now, unsurprisingly, VoiceOver cannot change the UIPickerView value.
And if I change it to the true value in this context...
#implementation UIAccessibilityElement (GMPatches)
- (NSInteger)numberOfComponents {
return 1;
}
#end
... then VoiceOver sends the next misaddressed message, bringing everything down again:
-[UITableViewCellAccessibilityElement selectedRowInComponent:]: unrecognized selector sent to instance 0x1e97b0
I'm feeling fairly sure this is an iOS bug.
I've tried setting isAccessibilityElement = NO on the picker, the table cell and the table cell's content view, none of which helps.
I guess I might be able to expand the UIAccessibilityElement category above to forward various messages to its parent cell's child UIPickerView. But this feels like unpleasantly brittle hackery.
Any better ideas how I might work around this?
I had the same crash when I just set tableView.tableHeaderView = myUITextField and turn VoiceOver on in the system setting app. Problem has been solved now when I wrap myUITextField in a UIView and then assign it to tableView.tableHeaderView.
I believe this would be a bug in iOS 9 or later, for UITextField is also a sub class of UIView.
The issue you are facing has to be solved differently. You are trying to add the UIPicker to the UITableCell, but this is not possible. It looks like it is not possible to determine if you actually scrolled / picked the table cell or the UIPicker.
To overcome this issue, push another view to the table that includes the UIPicker.

cellForRowAtIndexPath called before viewWillAppear iPhone SDK 3.2 plus

After upgrading my SDK version I noticed that cellForRowAtIndexPath is always called prior to viewWillAppear. Previously the order of execution was opposite: viewWillAppear would always be called prior to cellForRowAtIndexPath. Because my application logic often used viewWillAppear to initialize objects that are subsequently used in cellForRowAtIndexPath, the application is often crashing.
I tried searching for an official expiation regarding this change with no success. I can likely move my initialization code to viewDidLoad, but wanted to see if there are better solutions or more information about this change in behavior.
You can just add the line
[self.tableView reloadData];
at the end of viewWillAppear and your problem will be fix
It is not "cellForRowAtIndexPath called before viewWillAppear", it is [super viewWillAppear:animated] will call UITableView's delegate.
I made the same mistake and it took me a lot of time to find it.

UITableView issue when using separate delegate/dataSource

General Description:
To start with what works, I have a UITableView which has been placed onto an Xcode-generated view using Interface Builder. The view's File Owner is set to an Xcode-generated subclass of UIViewController. To this subclass I have added working implementations of numberOfSectionsInTableView: tableView:numberOfRowsInSection: and tableView:cellForRowAtIndexPath: and the Table View's dataSource and delegate are connected to this class via the File Owner in Interface Builder.
The above configuration works with no problems. The issue occurs when I want to move this Table View's dataSource and delegate-implementations out to a separate class, most likely because there are other controls on the View besides the Table View and I'd like to move the Table View-related code out to its own class. To accomplish this, I try the following:
Create a new subclass of UITableViewController in Xcode
Move the known-good implementations of numberOfSectionsInTableView:, tableView:numberOfRowsInSection: and tableView:cellForRowAtIndexPath: to the new subclass
Drag a UITableViewController to the top level of the existing XIB in InterfaceBuilder, delete the UIView/UITableView that are automatically created for this UITableViewController, then set the UITableViewController's class to match the new subclass
Remove the previously-working UITableView's existing dataSource and delegate connections and connect them to the new UITableViewController
When complete, I do not have a working UITableView. I end up with one of three outcomes which can seemingly happen at random:
When the UITableView loads, I get a runtime error indicating I am sending tableView:cellForRowAtIndexPath: to an object which does not recognize it
When the UITableView loads, the project breaks into the debugger without error
There is no error, but the UITableView does not appear
With some debugging and having created a basic project just to reproduce this issue, I am usually seeing the 3rd option above (no error but no visible table view). I added some NSLog calls and found that although numberOfSectionsInTableView: and numberOfRowsInSection: are both getting called, cellForRowAtIndexPath: is not. I am convinced I'm missing something really simple and was hoping the answer may be obvious to someone with more experience than I have. If this doesn't turn out to be an easy answer I would be happy to update with some code or a sample project. Thanks for your time!
Complete steps to reproduce:
Create a new iPhone OS, View-Based Application in Xcode and call it TableTest
Open TableTestViewController.xib in Interface Builder and drag a UITableView onto the provided view surface.
Connect the UITableView's dataSource and delegate-outlets to File's Owner, which should already represent the TableTestViewController-class. Save your changes
Back in Xcode, add the following code to TableTestViewController.m:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSLog(#"Returning num sections");
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"Returning num rows");
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Trying to return cell");
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
cell.text = #"Hello";
NSLog(#"Returning cell");
return cell;
}
Build and Go, and you should see the word Hello appear in the UITableView
Now to attempt to move this UITableView's logic out to a separate class, first create a new file in Xcode, choosing UITableViewController subclass and calling the class TableTestTableViewController
Remove the above code snippet from TableTestViewController.m and place it into TableTestTableViewController.m, replacing the default implementation of these three methods with ours.
Back in Interface Builder within the same TableTestViewController.xib-file, drag a UITableViewController into the main IB window and delete the new UITableView object that automatically came with it
Set the class for this new UITableViewController to TableTestTableViewController
Remove the dataSource and delegate bindings from the existing, previously-working UITableView and reconnect the same two bindings to the new TableTestTableViewController we created.
Save changes, Build and Go, and if you're getting the results I'm getting, note the UITableView no longer functions properly
Solution:
With some more troubleshooting and some assistance from the iPhone Developer Forums, I've documented a solution! The main UIViewController subclass of the project needs an outlet pointing to the UITableViewController instance. To accomplish this, simply add the following to the primary view's header (TableTestViewController.h):
#import "TableTestTableViewController.h"
and
IBOutlet TableTestTableViewController *myTableViewController;
Then, in Interface Builder, connect the new outlet from File's Owner to TableTestTableViewController in the main IB window. No changes are necessary in the UI part of the XIB. Simply having this outlet in place, even though no user code directly uses it, resolves the problem completely. Thanks to those who've helped and credit goes to BaldEagle on the iPhone Developer Forums for finding the solution.
I followed your steps, recreated the project and ran into the same problem. Basically you are almost there. There are 2 things missing (once fixed it works):
You need to connect the tableView of the TableTestTableViewController to the UITableView you have on the screen. As I said before because it is not IBOutlet you can override the tableView property and make it and IBOutlet:
#interface TableTestTableViewController : UITableViewController {
UITableView *tableView;
}
#property (nonatomic, retain) IBOutlet UITableView *tableView;
Next thing is to add a reference to the TableTestTableViewController and retain it in the TableTestViewController. Otherwise your TableTestTableViewController may be released (after loading the nib with nothing hanging on to it.) and that is why you are seeing the erratic results, crashes or nothing showing. To do that add:
#interface TableTestViewController : UIViewController {
TableTestTableViewController *tableViewController;
}
#property (nonatomic, retain) IBOutlet TableTestTableViewController *tableViewController;
and connect that in the Interface Builder to the TableTestTableViewController instance.
With the above this worked fine on my machine.
Also I think it would be good to state the motivation behind all this (instead of just using the UITableViewController with its own UITableView). In my case it was to use other views that just the UITableView on the same screenful of content. So I can add other UILabels or UIImages under UIView and show the UITableView under them or above them.
I just spent many hours pulling my hair out trying to figure out why a UITableView wouldn't show up when when I had it embedded in a separate nib instead of in the main nib. I finally found your discussion above and realized that it was because my UITableViewController wasn't being retained! Apparently the delegate and datasource properties of UITableView are not marked "retain" and so my nib was loading but the controller was getting tossed... And due to the wonders of objective-c I got no error messages at all from this... I still don't understand why it didn't crash. I know that I've seen "message sent to released xxx" before... why wasn't it giving me one of those?!?
I think most developers would assume that structure that they build in an interface builder would be held in some larger context (the Nib) and not subject to release. I guess I know why they do this.. so that the iPhone can drop and reload parts of the nib on low memory. But man, that was hard to figure out.
Can someone tell me where I should have read about that behavior in the docs?
Also - about hooking up the view. First, if you drag one in from the UI builder you'll see that they hook up the view property (which is an IBOutlet) to the table view. It's not necessary to expose the tableView, that seems to get set internally. In fact it doesn't even seem to be necessary to set the view unless you want viewDidLoad notification. I've just broken the view connection between my uitableview and uitableviewcontroller (only delegate and datasource set) and it's apparently working fine.
Yes for some reason (please chime in if anybody knows why...) tableView property of the UITableViewController is not exposed as an IBOutlet even though it is a public property. So when you use Interface Builder, you can't see that property to connect to your other UITableView. So in your subclass, you can create a tableView property marked as an IBOutlet and connect that.
This all seems hacky and a workaround to me, but it seems to be the only way to separate a UITableViewController's UITableView and put it somewhere else in UI hierarchy. I ran into the same issue when I tried to design view where there are things other than the UITableView and that was the way I solved it... Is this the right approach???
I was able to make this work. I built a really nice dashboard with 4 TableViews and a webview with video. The key is having the separate tableView controllers and the IBOutlets to the other tableview controllers defined in the view controller. In UIB you just need to connect the other tableview controllers to the file owner of the view controller. Then connect the tables to the corresponding view controllers for the datasource and delegate.