Use single UITableViewCell subclass across multiple UIViewControllers - cocoa-touch

So I have this UITableViewCell subclass that has some really complicated logics in it - it triggers some actions in UIViewController it's actually attached to. Of course the cell is not aware of its UIViewController but I still navigate to it like this:
UITabBarController *tabVC = (UITabBarController *)appDelegate.rootVC.centerPanel;
SGFirstTabViewController *firstTab1 = [tabVC.viewControllers firstObject];
[firstTab1 reloadCell:self];
The thing is now that I want to use the same subclass of UITableViewCell around about 5 different UIViewControllers.
What's the best way to do this? I will almost never know what is the UITableViewCell's VC is and I simply can't create 5 different cell subclasses with the same code over and over. What's the best way around it?

I think there is perhaps some misunderstanding in the role of the cell in the model-view-controller programming pattern.
The cell should not reload itself but it should be told to reload by the view controller that controls it. The reload code in the cell can stay the same.
So, rather than the cell having to find out which one its view controller is, have the view controller listen to the cell action (e.g. via delegate methods) and fill it with the appropriate reload data as directed.

Related

UITableViewController and custom UITableViewCell

Have couple of questions
When I place a UITableViewController on the storyboard, and wish to work with static cells must I create a class deriving from UITableViewController or can I only create a class deriving from UITableViewCell for the custom cell?
I created a custom UITableViewCell placed number of controls on it and tried dragging with control pressed to create an outlet but couldn't, any ideas why?
If I wish each cell to have different controls and behavior can I set each cell a different custom UITableViewCell and if so how does the UITableViewController initialize it? do I need to load it programmatically?
1) The cell must be a subclass of UITableViewCell.
2) No, I don't know why that didn't work, it should. Where were you trying to make the connection to? The cell or the table view controller?
3) Yes, I think this is the best way to do it. Have a different custom cell class for each different kind of cell, and make IBOutlets from the custom cell to its controls. Then just make one IBOutlet from the table view controller to the cell itself (you can then refer to the controls with something like self.cellType1.label1 ...). You don't need to do anything to initialize the cells if they're made in the storyboard.

Combined UITableView with other elements - how to create and use the view?

Ive a project close to doing everything I need it to do. Its got a Main page which has four buttons that allow you to choose an option. Then a tableview page is launched from those options and displays a parsed XML feed from a website. You can then select one of the options in the table to see a detail view of the item, enquire about it, etc.
My problem is I need to add more elements to the TableViewController page, other than the tableview itself. I want a customized back button (not the navigation controller standard) plus some labels, images, etc.
In the TableViewController xib, the tableview itself fills the page. I cant resize it to add more elements above it. I can add a 'view' window seemingly above the tableview and put things in it. But it seems to add the view to the tableview. This means that when I scroll the table, the other elements like new back button, scroll away as part of the table.
So I'm led to wonder whether I need this page not to be a tableviewcontroller, but a viewcontroller, with a tableview inside it, as well as my other view with buttons, etc. Is that the right way to go? But if thats the case, then how do I instantiate the tableviewcontroller within code? Because my page will not be of that type anymore - it will be just a viewcontroller. But in code Im making a tableviewcontroller .. slightly scared by that route tbh.
Any illumination on this would be much appreciated, as various searches have left me none the wiser. Thanks.
To customize it, this is the way to go:
Change your class to be a view controller instead, which implements the TableViewDelegate and TableViewData Source protocols.
In the view didLoad of you controller, create the table view, set its delegate, data source, and any other properties you wish and add it as a subview to your view.
tableView = [[[UITableView alloc] init] autorelease];
tableView.delegate = self;
tableView.dataSource = self;
// .. Other customization
[self.view addSubview:tableView];
I suggest doing this programatically rather than IB.
Instead of a UITableViewController, you want a UIViewController that has an IBOutlet UITableView. Drag and drop a UITableView component from Storyboard and hook it up, and position it as needed on the screen. This UIViewController should implement the UITableViewDelegate and UITableViewDataSource methods.
Edit: Remember that a UITableViewController is just a subclass of UIViewController so you don't really have to get rid of all your code. :) You only need to make minor tweaks to your header and main file, and change the Storyboard to be a UIViewController instead of UITableViewController as I mentioned above.

How to replace self (UIView) with another UIView?

View A has a button upon clicking it, we go to view B
View B does not retain a pointer to view A.
From view B, i'd like to load view A back (programmatically)
Effectively, i'd like to kill B and replace it with A.
I was thinking that the following should work but, it does not
Calling from View B
ViewController *main = [ViewController new];
[self addSubview:[main view]];
What am i missing please?
Personally I think the easiest way to do this would be by having a UIViewController with an IBOutlet to both UIView objects. You can add and design them both in the interface builder and just set one of them (view B) as hidden (it's a property in UIView).
Then, you could specify a button action to toggle the visibility of view B.
I must add though that there are constructs for implementing screen flows, such as the NavigationController. In your case, however, you might also consider the use of the presentModalViewController:animated: method.
It all depends really, but in general it's better practice to make a seperate UIViewController for each UIView in your application.
Hope this helps!
This sounds to me like you're looking for a navigation controller. You can easily take away a navigation controllers NavBar and take away the animations if you don't want them - but this would achieve exactly what you're looking for.

Re-use tableview from different controller: how to split didSelectRowAtIndexPath behaviour?

I'm currently working on my Favorites implementation. In the end, it should work the same as the favorites features in the Phone book on the iPhone.
I've the following set-up (besides other controllers and classes):
TabBarController (named mainTabBarController)
NavigationController with a Tableview (let's call it listNavController)
ViewController with some components for displaying row details (named detailViewController)
NavigationController with a TableView for favorite records (named favoritesNavController)
From the favoritesNavController, I want to select a row (from listNavController) so I can add a new entry to my Favorites tableview.
So, I decided to re-use my listNavController because it has all the functionality I need. Like searching, index, etc.
I've managed to show the listNavController from the mainTabBarController. So no problem here. When I select a row from the listNavController, it displays my detailViewController for that row. Of course, this was expected because that's in didSelectRowAtIndexPath in listNavController.
But, when I launch a listNavController from my favoritesNavController with the help of presentModelViewController, it still shows the detailViewController when selecting a row.
In this case, I want to return the selected row to my favoritesNavController. Then I can add it to my Favorite's list.
So, how do I differentiate this behaviour in code ? Should I use protocols, delegation, etc. ?
Any tips ?
With regards,
Rutger
It turned out that I was looking in the wrong direction.
The solution to the posted question is as follows:
I created a subclass of my listNavController and overrided the didSelectRowAtIndexPath method. Next I presented this new view controller with a navigation controller as a modal view (presentModalViewController).
Finally I set the delegate and a protocol for the subclassed view controller to the initiating class. This way I can present and dismiss the subclassed view controller from the same controller. A much more clean and MVC way to go!

how to write inside a cell of UITableView

How do I write inside a cell of UITableView using TouchesBegan and TouchesEnd methods?
A UITableView scrolls and so cells move. What you are talking about would pretty much prohibit a table from being able to scroll. Of course you could have a static table or some other table which never scrolls and so you think that's ok.
In that case, handling touch events in a UITableViewCell is the same as handling the touch events in any other UIView. You could use a add a UIGestureRecognizer to the view and pull interaction that way or access the information through the UIResponder.
On thing to remember is, make sure userInteractionEnabled is set to YES if you are going straight through the UIResponder otherwise you'll just end up ignoring the events.