I currently have a MatchCenterViewController that I want to programmatically turn into a UITableViewController. I've attempted to do so below based on tutorials I've found, but it doesn't seem to be appearing.
MatchCenterViewController.m:
#import "MatchCenterViewController.h"
#import <UIKit/UIKit.h>
#interface MatchCenterViewController () <UITableViewDataSource, UITableViewDelegate>
#end
#implementation MatchCenterViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"newFriendCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"newFriendCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
//etc.
return cell;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
#end
As a minimum, you need to implement the following methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
And you need to set the delegate and datasource, typically in viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.dataSource = self;
self.tableView.delegate = self;
}
Also, you need an IBOutlet to the table view if the table view was created in storyboard, or a property for the table view, if the table view was created in code.
Related
I'm subclassing UITableView in my app. It's set up to be it's own delegate.
#interface TableView : UITableView <UITableViewDelegate, UITableViewDataSource>
#property (nonatomic, assign) id delegate;
- (id)initWithFrame:(CGRect)frame;
#end
#implementation TableView
#synthesize delegate;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, self.frame.size.height-144, self.frame.size.width, 40)];
super.delegate = self;
super.dataSource = self;
self.tableFooterView = footerView;
}
return self;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 15;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
return [self.delegate tableView:tableView cellForRowAtIndexPath:indexPath];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSLog(#"Selected row!");
}
#end
Now, what I don't understand is how I TableView can be the delegate of UITableView, but also have a different delegate property that it pipes some functions to sometimes. So, I'd like for - for example - numberOfRowsInSection to be handled by this class, but for - for example - didSelectRowAtIndexPath to be forwarded to the UIViewController or whatever's presenting it.
Each of the delegate methods have a property (UITableView *)tableView you can use this to identify which table views action to be performed
Eg lets say you have 2 table views tableView1 & tableView2 now do something like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if tableView == self {
return [self.delegate tableView:tableView cellForRowAtIndexPath:indexPath];
} else if tableView == tableView2 {
// Do something
}
}
You can do the same concept using super and self calls
EDIT
Create a property called customDelegate, now in your ViewController set customDelegate = self and keep the TableView's delegate same
Now when you wish the class should handle the call just don't do anything as the behaves would be default
But if you wish that your viewController should handle the call then just pipe it using that customDelegate property
Eg
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if <SOME_CONDITION> {
// This will cause the TableView's delegate to be called
return [self.delegate tableView:tableView cellForRowAtIndexPath:indexPath];
} else {
// We wish the ViewController to handler this action then
return [self.customDelegate tableView:tableView cellForRowAtIndexPath:indexPath];
}
}
I have a UITableView inside a UITableViewCell and I need to figure out how to set the sub table view datasource and delegate. At the moment this is what I have:
MainTableViewController.h
#import <UIKit/UIKit.h>
#interface MainTableViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate>
#end
MainTableViewController.m
#import "MainTableViewController.h"
#import "TableViewCell.h"
#interface MainTableViewController ()
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
#implementation MainTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UITableView delegate functions
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 3;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"tableViewCell";
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.cellLabel.text = [NSString stringWithFormat:#"%ld", (long)indexPath.row];
return cell;
}
#end
TableViewCell.h
#import <UIKit/UIKit.h>
#interface TableViewCell : UITableViewCell <UITableViewDelegate, UITableViewDataSource>
#property (weak, nonatomic) IBOutlet UILabel *cellLabel;
#property (weak, nonatomic) IBOutlet UITableView *subTableView;
#end
TableViewCell.m
#import "TableViewCell.h"
#implementation TableViewCell
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
self.subTableView.delegate = self;
self.subTableView.dataSource = self;
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"subTabeViewCell"];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"subTabeViewCell"];
cell.textLabel.text = #"test";
return cell;
}
#end
Because I can't ctrl + drag from my sub table view to the TableViewCell class, I'm trying to set the delegate and datasource programmatically within the initialisation, but it's not working and I'm just getting straight up confused.
I know I can set the datasource and delegate to connect to the first class and then within each of the delegate functions check to see which tableView I'm dealing with, but the with the nature of what I'm trying to do it won't really work, I've tried.
So all help is welcome
So I figured it out, well i figured out a way of doing it. Within the cellForRowAtIndexPath in the MainTableViewController.m, I simply added:
[cell.subTableView setDelegate:cell];
[cell.subTableView setDatasource:cell];
And all is working away
I'm following a textbook and it's a bit outdated so I ended up mixing my code with it.
Its a basic app that populates a table view with Cities (london,san francisco,sydney and madrid) and upon clicking it, It should open up a detail view that should display the city as its title and an image of the city with the description, somehow even if I click any cell it shows me "London" with London's picture and description.
Here's my code
ViewController.m
#import "ViewController.h"
#import "City.h"
#import "AppDelegate.h"
#import "CityController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
citys = appDelegate.cities;
}
#pragma mark - UITableViewDataSource Methods
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
City *theCity = [citys objectAtIndex:indexPath.row];
cell.textLabel.text = theCity.cityName;
return cell;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [citys count];
}
#pragma mark - UITableViewDelegate Methods
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#end
CityController.m (the detail View)
#import "CityController.h"
#import "AppDelegate.h"
#import "City.h"
#implementation CityController
- (id) initWithIndexPath:(NSIndexPath *)indexPath{
if((self = [super init])){
index = indexPath;
}
return self;
}
- (void) viewDidLoad{
[super viewDidLoad];
AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
City *thisCity = [delegate.cities objectAtIndex:index.row];
self.title = thisCity.cityName;
labelDescription.text = thisCity.cityDescription;
//descriptionView.editable = NO;
pictureView.image = thisCity.cityImage;
}
#end
City.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#interface City : NSObject
#property (nonatomic, strong) NSString *cityName;
#property (nonatomic, strong) NSString *cityDescription;
#property (nonatomic, strong) UIImage *cityImage;
#end
You don't show in your code how you are calling this method on your CityController
- (id) initWithIndexPath:(NSIndexPath *)indexPath
Therefore indexPath.row in CityController will always be zero which I'm assuming is the first entry in the cities that relates to London
You need to do something in this method to set the indexPath correctly for the CityController
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Are you using Storyboards?
Your code must be,
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
CityController *cityVC = [[CityController alloc] initWithIndexPath:indexPath];
[[self view] addSubview:[cityVC view]];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
I have a view controller with a static cell named 'Make' I have two controllers one called "AddCarTableViewController" and "MakeTableViewController" when you click on the static cell named 'Make' it presents the make table view controller where you can select the make, then pops the view controller and am trying to store the selected value in the detailTextLabel of the static cell. here is my code for all the controllers.
The problem I'm having is once I select the make everything happens as it should I even log the selected item and it saves it after popping the view controller, but I can't figure out how to implement selected item into the detailTextLabel. Any help will be much appreciated!
"MakeTableViewController.h"
#import <UIKit/UIKit.h>
#import "AddCarTableViewController.h"
#protocol CarMakeDelegate <NSObject>
- (void)updateCarMake:(NSString *)updateMake;
#end
#interface MakeTableViewController : UITableViewController
#property (nonatomic, strong) NSArray *carMakes;
#property (nonatomic, weak) id <CarMakeDelegate> delegate;
#end
MakeTableViewController.m
#import "MakeTableViewController.h"
#interface MakeTableViewController ()
#end
#implementation MakeTableViewController {
NSIndexPath *oldIndexPath;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.carMakes = [[NSArray alloc] initWithObjects:#"Acura", #"Aston Martin", nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.carMakes count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [self.carMakes objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
oldIndexPath = indexPath;
NSString *addMake = self.carMakes[indexPath.row];
[self.delegate updateCarMake:addMake];
NSLog(#"%#", addMake );
[[self navigationController] popViewControllerAnimated:YES];
}
#end
AddCarTableViewController.h
#import <UIKit/UIKit.h>
#import "MakeTableViewController.h"
#interface AddCarTableViewController : UITableViewController
#property (strong, nonatomic) NSString *makeName;
#property (weak, nonatomic) IBOutlet UITableViewCell *makeCell;
#end
AddCarTableViewController.m
#import "AddCarTableViewController.h"
#interface AddCarTableViewController ()
#end
#implementation AddCarTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 4;
}
-(void)updateCarMake:(NSString *)updateMake {
self.makeCell.detailTextLabel.text = updateMake;
}
#end
You don't need to use delegate in this case. Just update the underlying data model. and call
[tableview reloadData];
When the makeViewController is popped.
In the AddCarVC's cellForRowAtIndex, add another line to check if current indexPath corresponds to Make cell and if it does update the detailLabel text.
I am trying to implement a UITableView. My issue is that tableview cells, in order to be selected in simulator, require the user to press and hold that cell. I don't understand why this is happening. I would like cell's to be selected with a simple tap. Here is my code. There isn't much.
The header file:
#import "BasisViewController.h"
#define kDISCUSSIONS 5
#interface MyDiscussionsViewController : BasisViewController <UITableViewDataSource,UITableViewDelegate>
#property (strong, nonatomic) IBOutlet UITableView *myDiscussionsTable;
#end
The implementation file:
#import "MyDiscussionsViewController.h"
#interface MyDiscussionsViewController ()
#end
#implementation MyDiscussionsViewController
#synthesize myDiscussionsTable;
- (void)viewDidLoad
{
[super viewDidLoad];
// Annoyingly, iOS 7 makes it so the seperators of table views are offset slightly. Get rid of this property.
if ([myDiscussionsTable respondsToSelector:#selector(setSeparatorInset:)]) {
[myDiscussionsTable setSeparatorInset:UIEdgeInsetsZero];
}
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return kDISCUSSIONS;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"TheDiscussions";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
[cell.textLabel setText:#"This Discussion"];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"User selected discussion at index: %d",indexPath.row);
}
#end