Accessing a TableView within a ViewController - ios

I've got a ViewController that has a UITableView within it. When I'm watching tutorials people are using things like this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _Title.count;
}
How am I able to generate the stubs without firstly creating the class with them in. When I made the class I selected it as a UIViewController. I've been playing around trying to auto generate the stubs but all to no avail.

Simply add the UITableViewDataSource (and most likely the UITableViewDelegate) to your UIViewController declaration. Example:
// MyViewController.h
#interface MyViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
// ...
#end
After that your implementation file MyViewcontroller.m should help you with the code completion.
One note: don't forget to set yourself as dataSource:
_tableview.dataSource = self;

If you added the tableview by code, you need to create a property (weak) in order to have a reference to your table view after adding it to your view controller's subview. If you add it by using interface builder, you need to create a iboutlet property that will allow you to "bind" your table view property with the xib/storyboard file representing your view controller. Alternatively, you can use UITableViewController as the parent class of your view controller. This class already has a property to access the table view in your view controller.

Tell your controller that you need to conform to the table view protocols and they will start to auto-complete when you try to type them in. You can check the docs of a protocol to find the available methods. Checking the UITableView docs would tell you about the relevant data source and delegate:
The data source must adopt the UITableViewDataSource protocol and the delegate must adopt the UITableViewDelegate protocol.
In your header file:
#interface MyViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>

You have a couple of options.
You could make your class inherit from UITableViewController instead of UIViewController. This will give you a tableView so you don't need to make one.
Or...
Your UIViewController could implement the protocols UITableViewDataSource and UITableViewDelegate. Then set the dataSource and delegate properties of your table view to self (your view controller containing the table).

-First of all you may need to add datasource and delegate of UITableViewController in your UIViewController header file
#interface MyViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
and then implement the required and optional methods to populate the data in your _tableView.
Sample Code for TableView demonstration by Apple:
https://developer.apple.com/library/ios/samplecode/TableViewSuite/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007318

Related

Should I store data in my custom UITableView?

I have 2 viewControllers that each contains one UITableView among other subviews. The 2 UITableViews have the same section structure and cell types, but the data source is different.
So I decided to extract this UITableView into a custom UITableView. The custom UITableView implements methods like tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath, and is its own data source and delegate. The viewController only provides data.
The question is I can't figure out which is the best way for viewControllers to provide data. I can think of 2 ways:
first way
in MyCustomTableView.h:
#protocol MyCustomTableViewDataProvider <NSObject>
- (NSArray*)dataArray;
#end
#interface MyCustomTableView : UITableView
#property (nonatomic, weak) id<MyCustomTableViewDataProvider> dataProvider;
#end
The viewController should implement this protocol:
- (NSArray*)dataArray {
return self.dataArray;
}
And in MyCustomTableView.m I use it like:
NSArray* dataArray = [self.dataProvider dataArray];
second way
in MyCustomTableView.h:
#interface MyCustomTableView : UITableView
#property (nonatomic, weak) NSArray* dataArray;
#end
Every time when there's a change in data, the viewController should inform the custom TableView to update its data:
self.customTableView.dataArray = self.dataArray;
And in MyCustomTableView.m I use it like:
self.dataArray
It seems that the second way could save some code, but I heard that you shouldn't store data in views because it violates the MVC principle. Could you please give me some advice? Many thanks!
IMHO, I wouldn't subclass any UIView unless it's absolutely necessary. Both TableViews and Collections provide protocols to control their behavior correctly.
If I were you, in order to keep the ViewController clean and short, I would create a custom NSObject implementing both UITableViewDelegate and DataSource protocols. This class would be in charge of providing the style of cells and sections (that is shared in those 2 table views) and also the data source. Of course, this object must have a property referencing its TableView.
The ViewController would only be in charge of triggering data retrieval whenever is needed. That data should be passed to that custom NSObject, which would be in charge of updating the table view.
BTW, this object could even be added through InterfaceBuilder.
It's a bit old, I know, but you could check :Lighter VC It's just a step forward towards MVVM.

Communication between UITableViewDataSource and UIViewController

I have a tableview inside a viewcontroller and datasource of tableview is separate class, which is the best way to notify viewcontroller that some data has been added/deleted so it can add/remove rows to data ?
One idea I have is to use delegates but It will be like
Callback from webservice to Datasource -->
Fire delegate method from datasource to viewcontroller
This is giving me feeling that I am doing something wrong, Help !!
You can create weak property in your other class (the one with datasource) to hold reference to the view controller:
#property (nonatomic, weak) MyViewController *viewController;
and when you add/delete row just call appropriate method on your view controller, something like that:
//Row deleted
[self.viewController deleteRowAtIndexPath:indexPath];
Of course you have to add this method to your view controller.
The last step you have to do is connect view controller with your other class.
In view controller in the same place where you set up table view delegate do something like that:
tableView.delegate = otherClass; //<- this is the class you store table view delegate.
otherClass.viewController = self;
Note that this is just one way you can do this, the other one can be delegate (as you mentioned above) or blocks, notifications, etc.
// Extended
With block you have to do it like that.
In other class .h:
// create typedef to avoid typing all block definition
typedef void (^CompleteBlock) (NSIndexPath *indexPath);
//Declare property
#property (nonatomic, copy) CompleteBlock removeRowCompleteBlock;
// in .m file call block where you remove row:
if (self. removeRowCompleteBlock)
self. removeRowCompleteBlock(indexPath);
In view controller file after you create instance of other class add remove row block:
tableView.delegate = otherClass; //<- this is the class you store table view delegate.
otherClass.removeRowCompleteBlock = ^(NSIndexPath *indexPath) {
// od something
NSLog(#"Row removed: %#", indexPath);
};

Obj-C/iOS: Setting delegations programmatically versus through the NIB

Is there a difference between delegating in iOS like this:
#interface JOLoginHomeVC : MCViewController <UITextFieldDelegate>
versus in the NIB, delegating each individual UI element by dragging it to the objects owner?
Yes, this:
#interface JOLoginHomeVC : MCViewController <UITextFieldDelegate>
Sets JOLoginHomeVC to conform to UITextFieldDelegate protocol.
Setting a delegate in InterfaceBuilder actually assigns the delegate. It serves the same function as assigning it like:
someTextField.delegate = self;

Is it possible to connect delegate and dataSource of CustomViews in interface builder?

In Interface builder, If I right click on a tableView, I get option of delegate and dataSource outlets which at times we connect to the file's owner which is in most cases the View Controller which implements these protocol,
How can I get a similar option for my custom view which has a delegate and a datasource property ?
You'll need to meet these conditions:
The view's Custom Class should be set to your custom view's class name in Interface Builder (via the Identity Inspector). If your delegate or dataSource object is also a custom view, also make sure that that view's Custom Class is set
The #interface for your custom class should decorate its delegate and dataSource properties with IBOutlet. For example, #property (nonatomic, weak) IBOutlet id <SomeProtocol> delegate;
If you declared protocol(s) for your delegate or dataSource, the target object that you want to use as the delegate or dataSource should be declared as implementing that protocol
Create your custom delegate,
#objc protocol CustomDelegate: class {
func itemSelected(_ success: Bool)
}
Create your custom class and property of your custom delegate (Make sure you add #IBOutlet during the property declaration),
class CustomView: UIView {
#IBOutlet weak var cDelegate: CustomDelegate!
//...
//...
//...
}
Now, Go to the Storyboard where you want to add this custom view, Take a UIView and change the class then right click on it, you will able to see the property ("cDelegate") you declared. See the picture for better understanding,
You can achieve this by following these steps.
create new subclass of UIview
in .h file set the tableview delegate and datasource property like
UIViewController
then implement the delegate and datasource protocols in your .m file. like you normally do.
OK. now in your view controller drag a view into the interface builder or create an instance programmatically.
set class of your view to the subclass you have created. (in interface builder right side );
then put a UITableView inside this view. and drag connections to its parent UIview and select datasource and delegates.
thats all done now your UIview sub class will act as a datasource and delegate for the tableview..

UITableView inside a UIView

I would put an UITableView inside a UIView. I created a XIB where I have a tableView.
#import <UIKit/UIKit.h>
#interface PointsViewController : UIViewController <UITableViewDelegate>
{
IBOutlet UITableView *tableView;
}
#end
- (void)viewDidLoad
{
[super viewDidLoad];
[tableView setDelegate:self];
}
I instantiate the PointViewController class from another class and add it to a UINavigationBar by means of a button:when I click the button, the PointsViewController'view (the tableView) shall open. But it does not.
What am I missing? I tried also to make PointsViewController as a subclass of UITableViewController which works, but no UITableView is displayed.
You will also need to make your ViewController a delegate for UITableViewDataSource.
#interface PointsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
IBOutlet UITableView *tableView;
}
#end
...and support the corresponding methods.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDataSource_Protocol/Reference/Reference.html
You need to also hook up the table's dataSource and delegate to the File's Owner. Otherwise the view controller doesn't know what table to send responses to.
In your XIB, select the table and open the Connection Inspector. Then drag the 'plus' sign next to dataSource to File's Owner to make the connection. Do the same for delegate and the table's referencing outlet.

Resources