providing common functionality for different viewcontrollers in objective c - ios

I have many viewcontrollers which needs to have some common functionality related to navigation.
Earlier I made a base class BaseViewController(extending UIViewController) which have all common functionality (like doing some tasks on viewDidLoad etc) and all my viewcontrollers extends BaseViewController.
The problem is that some of my viewcontroller should be subclass of UIViewController and some of UITableViewController, so I can not use above approach.
One way could be to write base class for both and duplicating code. Is there any better way without duplicating code.

While you can get around this by using delegation or helper objects, I would make the case for just not using UITableViewController. It is only a very light subclass on top of UIViewController, providing a table view, conforming to the delegate & data source protocols, and adding a property or two for selection & refresh.
While I wouldn't normally suggest recreating something that the framework has already done for you, it may (in your case) make your code more easy to understand if you just keep everything inheriting from a common base class and add a table view to one of the subclasses.
If you do think this would be a reasonable approach, the UITableViewController documentation overview gives a detailed description of exactly what & where these behaviours are implemented, so mimicking its exact setup is trivial.
Adding a table view to UIViewController
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) IBOutlet UITableView *tableView;
#end
In your storyboard, drag a "Table View" from the object library and drop it on top of your View Controller scene's "View" in the Document Outline - this will replace the root view with a UITableView.
Then just hook it up:
ctrl-drag from the view controller to the table view to hook up the view and tableView outlets
ctrl-drag from the table view to the view controller to set the delegate and dataSource outlets.
Done - no magic required.

Related

iOS Simulator doesn't show prototype cell

I'm currently learning Objective-C by doing tutorials ("the iOS Apprecente")
Now I need to make a checklist
I added in viewController.h
#interface ViewController : UITableViewController
Normal there stands
#interface ViewController : UIViewController
The next is to go to Storyboard place there a TableViewController, give it the name: ChecklistsViewController (Identity inspector > Custom class > class.
I added a label into the first Table view cell. But when I run it there's nothing.
What to do?
Two separate issues here:
The choice of UIViewController with your own IBOutlet for the table view or a UITableViewController is simply a question of whether, in Interface Builder (IB), you added a standard view controller to which you added a table view, or whether you used a table view controller. You use the former if you have other controls on the view in addition to the table view. You'd generally use the latter if the table view is the only thing being presented in that view controller's view. Bottom line, your choice of UIViewController or UITableViewController is dictated by how you added the scene in IB. From your description, it sounds like you went down the UITableViewController approach, which is fine.
In terms of why you're not seeing anything, there are a bunch of possible reasons:
Did you specify the cell identifier for your table view cell prototype? Is it the same identifier you're using in cellForRowAtIndexPath method?
If you manually added a table view to a standard view controller's view, did you specify the view controller as the delegate and dataSource for the table view? Also, did you create an IBOutlet for the table view itself, hooking that up in IB? (If you used a table view controller in Interface Builder, you don't have to do these steps.)
You might want to double-check that the base class for the table view controller was correctly set in IB.
Did you implement all of the UITableViewDataSource methods, notably numberOfRowsInSection? If you don't do that, it will conclude that there are no rows, and no cells will be generated.
You say that you specified the base class for your view controller in IB to be ChecklistsViewController. But in your code snippets, it looks like you're using a custom class called ViewController. Make sure you're using the same UITableViewController subclass for both.

Create Relationship Segues

How can I create a relationship segue? I would like to create a UIViewController subclass similar to UITabBarController or UINavigationController where, using Interface Builder, I can control + drag from a view controller to another view controller. I have tried
#property (nonatomic) IBOutlet NSArray *viewControllers;
#property (nonatomic) IBOutlet UIStoryboardSegue *root;
and also tried dragging a Container View into my view controller. When I do that, I can drag from one view controller to another but I cannot drag to more than one view controller. I also cannot find any documentation for a UIContainerView object.
Relationship Segues are handled by Interface Builder. You cannot create them manually if the starting view controller is not one of those you mentioned. The simplest solution for your issue is to create a TabBarController and hide its tab bar in code.
Here is a quite advanced tutorial on something very similar to what you are trying to do. You may get some more ideas from it. Advanced Storyboard Techniques
EDIT:
Thanks for the tip about using a TabBarController, but I am asking this question because I am trying to subclass UIPageViewController so that I can create the PageViewController's datasource from IB
That's an interesting idea, and here is an explained solution for that: Using UIPageViewController in storyboards You don't have to subclass the UIPageViewController, it is against the recommendation in the documentation, too. Create a class that implements the UIPageViewControllerDataSource delegate. Place a "green cube" in the page view controller's listing panel and set its class to be newly created one. Then drag from the datasource outlet to this cube.
However, the pages cannot be set up visually in this way or any other. It is unfortunately not supported at all.

Should UIViews have properties?

Using proper MCV with Objective-C can a UIView subclass have #propertys?
i.e. in the .h file
#class MyViewSubclass;
#interface MyViewSubclass : UIView
#property (strong, nonatomic) UILabel *labelLabel;
#property (strong, nonatomic) UILabel *valueLabel;
#end
or should this be done in a UIViewController subclass?
Thanks in advance.
It is most common to subclass UIViewController to manage the labels, fields, images, and other views within a view hierarchy. However, if you are creating a reusable component view that will be used throughout your application, then it's perfectly appropriate to subclass UIView and add properties to your subclass.
From Apple's iOS App Programming Guide:
View controller objects manage the presentation of your app’s content on screen. A view controller manages a single view and its collection of subviews. When presented, the view controller makes its views visible by installing them in the app’s window.
The UIViewController class is the base class for all view controller objects. It provides default functionality for loading views, presenting them, rotating them in response to device rotations, and several other standard system behaviors. UIKit and other frameworks define additional view controller classes to implement standard system interfaces such as the image picker, tab bar interface, and navigation interface.
http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/AppArchitecture/AppArchitecture.html#//apple_ref/doc/uid/TP40007072-CH3-SW1
It's good for views to have properties, but don't mix model logic into a view. The properties in a view should describe how the property looks, not what the property holds. I would avoid having a property named valueLabel in a view.
An example of view property names is UITableViewCell. It has properties imageView, textLabel, and detailTextLabel.
It's perfectly reasonable for a UIView subclass to have properties. You might need them to implement layoutSubviews, for example.
It is perfectly reasonable, also if you want to create a reusable component that allows for interaction and better flexibility, take a look at UIControl (which is a subclass of UIView)

IB - add UIView to UITableViewController?

I like to accomplish an UIToolbar below an UITableView and I wanted to use the UITableViewController because it sets up the data source and delegate and other stuff on its own.
I don't need an UINavigationController as has been proposed in similar topics due to only having 1 view currently and my data is without a hierarchy.
I didn't manage to drag and drop an UIView or UIToolbar to my UITableViewController at any place (scene design area or view hierarchy) in Interface Builder of XCode 4.2.
Thus my question: How to add an UIView to an UITableViewController in Interface Builder?
I did manage to achieve the look I intend to accomplish using an UIViewController with an UITableView and an UIToolbar contained in its UIView.
Would using an UIViewController with an UITableView be much more involved than relying on the UITableViewController?
Thank you for your time!
I think this is your real question
Would using an UIViewController with an UITableView be much more
involved than relying on the UITableViewController?
The answer is no, its not much more work. Just add this to the viewcontrollers' .h
#interface MyViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
Then in the .h add the datasource and delegate functions( you could just copy and paste the functions your'e currently using in your TableViewController)
NOTE: From Xcode 4.5.1: "Static table views are only valid when embedded in UITableViewController instances."

How to change UITableView

I'm using iPhoneCoreDataRecipes sample as as base code for my project and there is one thing that I was not able to modify. Also, I'm not quite sure if it is even possible.
I would like to modify the table that displays recipes (the first one). Right now the table gets the data from recipeListControllerand by default it covers the whole screen. I would like to change that. I still want to build a table with recipes data but I'm planning to shrink the table and modify its look.
I guess table view controller is created in the mainWindow.xib.
Normally when I'm creating tables, I'm inserting them into UIViewController in the interface builder and then I use UIViewController <UITableViewDelegate, UITableViewDataSource> in my class.
Here are the bits that I think I need to modify:
#interface RecipeListTableViewController : UITableViewController <RecipeAddDelegate, NSFetchedResultsControllerDelegate> {
to something like this:
#interface RecipeListTableViewController : UIViewController <RecipeAddDelegate, NSFetchedResultsControllerDelegate, UITableViewDelegate, UITableViewDataSource> {
and then after creating UIView Controller in MainWindow.xib I think I need to hook it up with recipeListController. Inside of this UIView, I want to have a custom table, which then should use recipe data. Unfortunately I get errors...
I would appreciate any suggestions. Here is the project that I used:
http://developer.apple.com/library/ios/#samplecode/iPhoneCoreDataRecipes/Introduction/Intro.html
My suggestion : create a uiview below the table view, then put the table view as a subview of that view, and then you can manage its size as being not full screen. The underlying view is mapped to the RecipeListTableViewController.view outlet, you probably need to create another one for the table view (just to call [tableView reloadData] for example). The delegate and data source of the table view point as well to RecipeListTableViewController. By experience this will work.

Resources