I have a XIB that has a bunch of views in it (iPad). One of the views is a UITableView. The delegate was set via IB. When you run the app cellForRowAtIndex is not being called. As a matter of fact, in this file, there is also no numberOfRowsInSection or numberOfSections methods. There is only a didSelectRowAtIndexPath method.
So I wrote a cellForRowAtIndex and manually set self.table.delegate = self.
If I click a cell the didSelectRowAtIndexPath is executed.
I honestly am at a loss? How can this even happen?
Add:
self.table.dataSource = self;
cellForRowAtIndexis a datasource protocol method, so you must set the datasource to self as well in order for the controller to respond to the datasource protocol.
If this controller is anything other than a UITableViewController, do not forget to add the following to your .h file:
#interface myViewController: UIViewController <UITableViewDelegate, UITableViewDataSource> {}
In your .h you need to add the Datasource and Delegate declarations
#interface HDMainViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
and in you .m file where you create your tableview you need to set
tableview.delegate = self;
tableview.dataSource = self;
Now your dataSource and Delegate methods should work
I'm not sure what is causing the problem, however an easy fix is that in your -(void)viewDidLoad method you could call [self.table reloadData] which forces it to manually call all of the functions
Somethign else that occurred to me is that you said "numberOfRowsInSection or numberOfSections is not implemented"... Those methods are required for a table view and oyu must make sure to implement them. That could very well be the problem
Related
UICollectionView has some built-in datasource methods, such as the "cellforItemAtIndexPath" method and the "numberofitemsinsection" method. If I understand correctly, these methods are called after viewDidLoad() completes. However, for my purposes, I want to be able to exactly control the point in time in which these methods are called. How can I do that?
The reason is that I am loading loading some images and I want to finish the task of loading before these methods are called.
It sounds like you don't want to show the collection until the images are downloaded, is that right? Does returning 0 for the number of items until the images finish downloading work? I don't have my Mac with me, or I'd test this before posting.
Disconnect the collectionView datasource and delegate connected to the controller from storyboard. Then set them in the code once you needed.
First connect the collectionView outlet to the interface section.
#interface YourViewController : UIViewController <UICollectionViewDataSource, UICollectionViewDelegate>
#property (weak, nonatomic) IBOutlet UICollectionView *collectionView;
So once your images are loaded, call this method:-
self.collectionView.delegate= self;
self.collectionView.dataSource= self;
[self.collectionView reloadData];
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
functions like this one:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
NSLog(#"called")
return 1;
}
aren't being called, because the log doesn't appear at the console. I tried using
[table realoadData]
but it still doesn't work
Make sure that you have both the UITableViewDataSource and UITableViewDelegate set to the class that this method is located in
.h
#interface class_name : UIViewController <UITableViewDelegate, UITableViewDataSource>
{ UITableView *tableView; }
.m
in the viewDidLoad (or any other loading method)
tableView.delegate = self;
tableView.dataSource = self;
If you are subclassing UITableViewController, it should be working already
hope that helps!
In Nib file, you need to outlet tableview.
Your subclass must have UITableViewDataSource and UITableViewDelegate.
Assign tableview.delegate = self and tableView.dataSource = self;
I want to create a self-contained UICollectionView subclass (acting as its own data source and delegate) so that I could load it in different viewControllers. Here's what I have so far:
CustomCollectionView.h
#interface CustomCollectionView : UICollectionView <UICollectionViewDataSource, UICollectionViewDelegate>
#property (weak, nonatomic) IBOutlet UICollectionView *collectionView;
#end
CustomCollectionView.m
#import "SSCalendarView.h"
#implementation SSCalendarView
#synthesize collectionView;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil];
[self registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"Identifier"];
[self addSubview:collectionView];
}
return self;
}
// Below are UICollectionViewDataSource and UICollectionViewDelegate methods
#end
CustomCollectionView.xib
Contains only one view - UICollectionView. It's class is set to CustomCollectionView
File's Owner's class is also set to CustomCollectionView
File's Owner is UICollectionView's delegate and data source
I understand that I have quite a few things wrong here. But perhaps we could use this as a starting point.
My questions are:
How to implement this sub-class correctly? I want to load the view fully from xib
To begin with, and aside from potential MVC violation (this sub-class would do it all), can a UICollectionView be its own data source and delegate?
If above is possible, how do I correctly create an instance of this subclass to use in my view controllers?
There already exists an object which you can use for this purpose - UICollectionViewController. This can be subclassed and added to any view controller (as a child view controller) and already contains a collection view which it is the datasource and delegate for.
The problems with your current approach are:
As you point out, you're putting too much responsibility on one object by having a view be its own datasource and delegate
File's owner for a xib can't be an object from within the xib. When you load the xib, the object you send to the owner argument is the file's owner. I've no idea what you actually end up with using the code you currently have.
I'm not sure why you insist on using a xib anyway - what does this give you, except the headache of an extra file and the complexity of nib loading? Just create a collection view controller, you can specify the layout and register cells in the init and viewDidLoad methods.
First of all making view to act like view controller is violation of MVC, ask you've said so - so you shouldn't probably do it.
Theoretically it's possible to force view to act as delegate & data source but I wouldn't recommend it.
If you still want to do it - just assign delegate & data source to self:
self.dataSource = self;
self.delegate = self;
and adopt UICollectionViewDelegate and UICollectionViewDataSource protocols in .h file
I have created a UIView with UICollectionView.
In the interface declaration of the UIView I have conformed to the UICollectionViewDataSource, UICollectionViewDelegate protocols:
#interface TestOverview : UIView <UICollectionViewDataSource, UICollectionViewDelegate>
But when I run the app, it crashes and i get this error:-
error: -[TestScreenViewController collectionView:numberOfItemsInSection:]: unrecognized selector sent to instance.
Just to be clear the method collectionView:numberOfItemsInSection is in the UIView (TestOverview), which was declared to be the delegate of the UICollectionView. So why does it expect to recieve it in the UIViewController(TestScreenViewController), which contains the UIView that contains the UICollectionView?
First of all, it would be better if you used a view controller as the delegate of your UICollectionView. That's what they are there for. Second of all, not only you need to declare that TestOverview implements the UICollectionViewDataSource and UICollectionViewDelegate protocols, but also you need to tell the UICollectionView instance who their delegate and data source respectively are. You can either do it in code like this:
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
Or in the Interface Builder, by binding the dataSource and delegate items to TestOverview.
It is better to user viewcontroller as collectionview delegate than a uiview.
self.collectionView.delegate = self;
self.collectionView.dataSource = self;