UITableView crashing when scrolled (iOS 7.1.2) - ios

I create a UITableView when a user presses a button, set it's delegate and data source to the current controller (which implements both UITableViewDelegate and UITableViewDataSource protocols), add it as a subview to the controller's view and implement the data source methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
Whenever I scroll the table view, the application crashes with
[UITableView currentPage]: unrecognized selector sent to instance 0x11365c00
where 0x11365c00 is the tableView. If I don't set the tableView's delegate and only set the data source, it doesn't crash. This behavior is the same if I return 0 in numberOfRowsInSection, so that nothing is added to the tableView and there is no crash related to my data. Any help would be great!

The crash occurs because you are sending a message -currentPage to an object that can't handle it.
And actually tableviews doesn't have this method in their interfaces, unless you are using a category. So the question is which object n your implementation file should handle this message?

Reason:
[someObjectHere currentPage]; // Here someObjectHere is really a table view(UITableView type)
If you have table view class and forgot to define the currentPage method, then define it there. That's y it crashed the app.
If you have currentPage method in your view controller then you have to make sure that someObjectHere is a your View controller.
[self currentPage];

Related

Two UITableViews in the same UIViewController

Im trying to have 2 table views on the same view. They both are within the same UIViewController which implementes the UITableViewDelegate and Datasource. one of the tableviews is static and the other is dynamic. The dynamic table view is loading just fine using the methods from its datasource, but the static one is showing up blank. Normally I erase the datasource methods from the controller so the static TableView doesn't override what's already done on the storyboard, but now I can't because those methods are being used by the dynamic TableView.
How can I have both of then under the same controller?
As Putz says, you can set up your view controller to manage 2 table views by setting up your data source and delegate methods to check the table view that's passed in.
However, I don't think you can use static table views with anything but a UITableViewController, and a table view controller only knows how to manage a single table view.
The trick is to add 2 container views to your view controller that will contain 2 table views, and embed a different UITableViewController into each container view. Then each table view is managed by it's own table view controller. I have a project on github that does exactly this: https://github.com/DuncanMC/test
I've set up protocols that the parent view controller and the 2 table view controllers use to communicate, although you don't have to do that if your needs are simpler.
Here is the easiest option, that let's you keep a single VC for your delegate/datasource :
Set both tableviews delegate and datasource to your UIViewController.
Ctrl-drag from one of the static cells to your .h file, and create an IBOutlet collection ( called here staticCellsCollection). Add each static cell to this collection, careful with the order, it will be important.
Implement cellForRowAtIndexPath: this way :
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == _dynamicTableView) {
// Do your dynamic thing
}
else if (tableView == _staticTableView) {
// Return the static cells one by one
// Here the static TV has only one section, and all cells are in staticCellsCollection
return staticCellsCollection[indexPath.row];
}
}
You also need to adapt numberOfRowsInSection and numberOfSectionInTableView but this is pretty basic (check which table is asking, and return appropriate values, for example staticCellsCollection.count for the number of rows of the static TV).
You may need to adapt this, for example if you want multiple sections in your static TableView, you should create an IBOutletCollection for each section, and handle the number of rows/sections accordingly, and return the correct cells. Anyway, this is pretty straightforward to implement once you get the idea.
You can have two tableView's use the same delegate functions. It's not amazingly pretty, but you can:
- (UITableViewCell *)tableView:(UITableView *)inTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(inTableView == tableView1)
{
...
}
else if
...
}
Put that type of logic into every tableView delegate function.

Adding a Navigation to a View Controller with a TableView

I'm trying to add (or have) a navigation bar (or items) on the top of a View controller and and a tableview right below the navigation bar. The problem I'm having is when I set the tableview's datasource to View Controller, my app will crash (setting the tableview's delegate to View controller doesn't). For now, the code for the tableview are in the default ViewController.m. Do I have the tableview's code in the right place or did I connect something improperly?
Here's the error that it gives me:
2013-10-10 15:14:48.442 SomeApp[15058:a0b] -[UIViewController >tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x8d42450
2013-10-10 15:14:48.450 SomeApp[15058:a0b] *** Terminating app due to uncaught exception >'NSInvalidArgumentException', reason: '-[UIViewController >tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x8d42450'
Make sure your view controller adheres to the proper protocols:
CustomViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
And add the necessary methods from these protocols to your implementation. These are the documentation links for your ease:
UITableViewDelegate Protocol Reference
UITableViewDataSource Protocol Reference
You are missing some methods that are required for your tableview to work,
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
More information on UITableViewDataSource Protocol Reference

Multiple tableview within one view controller

I was wandering if its possible to have more than one uiTableView in one ViewController.
For example:
tableView1 and tableView2 in one view controller.
Initial start up of view controller, tableView2 should be disabled and not visible.
tableView1 should show the data associated with it.
When user selects a row from tableView1... it should then show the data corresponding to the selected row in tableView2.
tableView1 should still be enabled, and if user selects another row, the contents of tableView2 should also change respectively.
Thanks for any help or guidance given. :)
Of course you can do this. This is 5 minutes in storyboard.
You should choose UIViewController (not UITableViewController!)
And create something like this:
Then you should create object references with a ctrl key.
You have to remember that you have to set delegate and dataSource in both tableViews to your ViewController:
And in yout second table view set initialView to hidden.
Then in your code in method - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath you should in first line call:
[self.mySecondTableView setHidden:NO]
and do all your stuff later. That's it.
EDIT:
Now i realize that you have set topic to "multiple" tableViews. This solution is messy enough for two TableViews. I suggest you to use container, and then all tableView will have own ViewController.
You can set different tags and outlets for this two TableView.
Then in
-(void)ViewDidLoad
self.yourSecondTableView.hidden = YES;
to hide second tableView
and when delegates methods was called
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
or
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
you can ask for tag like
if (tableView.tag == yourSecondTableViewTag)
return something

Objective-C: How to declare/define method used on tableView

My initial problem of multiple line selection in a UITableView has been answered in this question. But the answer left me at a point where I can't go on on my own, as I am very new to Objective C and iOS development.
Following daxnitros answer, I want to implement the code he/she suggested:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([tableView indexPathIsSelected:indexPath]) {
[tableView removeIndexPathFromSelection:indexPath];
} else {
[tableView addIndexPathToSelection:indexPath];
}
// Update the cell's appearance somewhere here
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
I still need the methods and I thought I can do it for indexPathIsSelected (for example) like this:
#interface MyTableViewController ()
- (BOOL)indexPathIsSelected:(NSIndexPath *)indexPath;
#end
#implementation MyTableViewController
// ...
- (BOOL)indexPathIsSelected:(NSIndexPath *)indexPath
{
BOOL bIsSelected = NO;
// ...
return bIsSelected;
}
#end
But that doesn't work. The error message is: No visible #interface for 'UITableView' declares the selector 'indexPathIsSelected:' Note: The same happens, if I declare the method in the .h file's interface instead.
Now, what baffles me, is this: [tableView indexPathIsSelected:indexPath] is somehow called on the tableView object and I don't even know why. Is that something I have to take into account in my method declaration/definition? I feel really stupid right now, that I can't even write a method by seeing its invocation.
How do I define and declare the method indexPathIsSelected correctly, so I can use it properly?
In your didSelectRowAtIndexPath, the variable tableView is a UITableView.
Your implementation for indexPathIsSelected is in class MyTableViewController, which is probably a UITableViewController.
UITableViewController and UITableView are different classes.
So you can't find the method indexPathIsSelected on UITableView because it's not implemented there, it's implemented on MyTableViewController which is a different class.
SO... I'm going to take an educated guess and assume that didSelectRowAtIndexPath is part of class MyTableViewController. If this is the case, then
[self indexPathIsSelected:indexPath]
may be the answer (i.e. call indexPathIsSelected in self rather than the table view).
The error message you're seeing is the key to the problem. The method indexPathIsSelected is implemented in your custom class MyTableViewController. However, the UITableView you have is apparently still a basic UITableView. At the very least you'll need to go into the storyboard and set the custom class of the table view controller object to MyTableViewController.
To do this, open the storyboard (or nib) and select the table view controller. Then in the identity inspector (on the right hand side, typically), under custom class, select MyTableViewController from the drop down.

Overriding of Tableview Datasource/Delegate Methods

I have one parent class with one tableview.
That class is the delegate and datasource of that tableview as well.
Now I subclassed (derived) that class and made a child class.
I have one tableview in child class too.
Then I defined delegate and datasource functions in that child class, but it overrides parent class tableview data source/delegate methods.
But I want both of them to be separate.
However my Requirement is as Follows :
I want to retain a search bar and side button, on the top of all the viewControllers that search bar includes , a recent searches terms table underneath that.
So i thought of defining parent class for that and subclass other viewControllers from that class.
Am i doing it the right way ?
I assume you are talking about a view controller class. If I understood you right, then you are about to mess it up. Delegation is a way to avoid subclassing. Of course you can subclass the delegate - no problem. But you want a table view in the super class that owns a table in its view. And you want a subclass that has another table in its view plus the table that the superclass owns.
That is not impossible. But from your subclass' point of view, your subclass owns two table views. Even that is possible. Your view controller is the delegate of two tables (regardless of where in the view hierarchy they are declared and instanciated). When you now override the delegate and data source methods theny your subclass must either:
Determine which table it is dealing with/being called from. And then serve both tables appropriately.
Determine wich table it is dealing with/being called from. And then serve "its own" table appropriately and calls [super sameMehtod:withSamePamaters] to ensure that the superclas can still provide the data and server as delegate.
Which of both is smarter depends on the context and what you are about to achieve in detail.
A way of determinnig which table's delegate was called can be done by tagging the table views (do not use 0 as tag) or by comparing the tableView parameter of the delegate method with the corresponding properties (IBOutlets in this case). (In other cases you can compare the sender parameter with the IBOutlets. But tagging is probably easier to understand when reading the code later.)
Let's look at an example of the UITableViewDataSourceDelegat:
Your superclass implements:
#interface MySuperTableViewController:UITableViewController <UITableViewDelegate>
// There will be something in here.
// But it inherits self.tableView from UITableViewController anyway. We leave it with that.
#end
#implementation MySuperTableViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// This method creates or re-uses a cell object and sets its properties accordingly.
}
#end
And your subclass:
#interface MySubTableViewController : MySuperTableViewController // no need to declare the delegate here, it is inherited anyway
#property (weak, nonatomic) IBOutlet UITableView *mySecondTableView; // self.table will be used by the superclass already.
#end
#implementation MySubTableViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == self.table) { // This call refers to the one talbe that is managed by super
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
// This method now creates or re-uses a cell object and sets its properties accordingly.
// You may want to check wether tableView == self.mySecondTableView etc.
}
#end
(This comes from scratch, not syntax checked etc. Do not expect this to run properly right away :)
BUT ... please re-consider your class structure. I am afraid you are getting lost in some rather unlogical class hierarchy. There is nothing wrong with having two talbes managed by a common view controller even without this subclassing-thing. And there is nothing wrong with using multiple tables in a view where each of the tables has its own delegate (can be a view controller). Since iOS 5 (or was it introduces with 6) we can use the UIContainerView for that purpose and nicely build it up in IB/storyboard.
try this,
ViewController.h
IBOutlet UITableView *firstTable;
IBOutlet UITableView *secondTable;
ViewController.m
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
if (tableView == firstTable) {
return 1;
}
else if(tableView == secondTable)
{
return 1;
}
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
if (tableView == firstTable) {
return [arrItems count];
} else if(tableView == secondTable)
{
return [arrData count];
}
return 0;
}
etc etc ....

Resources