I get that you need to use the following method and return what you want the new title to be as an NSString. However I don't know where to put this method. Where is it normally placed?
- (NSString *)tableView:(UITableView *)tableView
titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
return #"Close";
}
I've tried it in my TableViewController and it doesn't work:
interface
#import <Three20/Three20.h>
#interface PositionsController : TTTableViewController {
}
#end
implementation
#import "PositionsController.h"
#import "NetworkController.h"
#import "PositionsDataSource.h"
#implementation PositionsController
- (id) init {
if (self = [super init]) {
self.variableHeightRows = NO;
}
return self;
}
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
return #"Close";
}
#end
I won't put all the code in there, nevertheless everything functions as it should but I still get Delete as the title for my button and not Close.
Three20 Library Revised Working Code
The problem I was having is that I was using the TTTableViewDragRefreshDelegate for my UITableView's delegate. I was doing so via the following method:
- (id<UITableViewDelegate>)createDelegate {
return [[[TTTableViewDragRefreshDelegate alloc] initWithController:self] autorelease];
}
That's all well and good but if you want to override a method that the UITableViewDelegate calls, like what I was trying to do here, then you need to create your own delegation class that inherits TTTableViewDragRefreshDelegate and put your method overrides in that class. Here is what my working code looks like:
Revised PositionsController.m createDelegate method
- (id<UITableViewDelegate>)createDelegate {
return [[[PositionsTableDelegate alloc] initWithController:self] autorelease];
}
PositionsTableDelegate.h
#import <Three20/Three20.h>
#interface PositionsTableDelegate : TTTableViewDragRefreshDelegate <UITableViewDelegate> {
}
#end
PositionsTableDelegate.m
#import "PositionsTableDelegate.h"
#implementation PositionsTableDelegate
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
return #"Close";
}
#end
This is a delegate method of UITableView. You need to implement it in the class which instance is set as the delegate of your TableView.
Try to set the delegate-property of the TableView to the instance of PositionsController.
The method that you are using is defined for UITableViewDelegate, so you need to define it for a class that is the delegate for your UITableView.
First off, I don't know if TTTableController is doing anything different so you're problem may lie there.
The function you're using only effects the button's title on the actual cell (ie swipe to delete, or after the user had tapped the minus button), not the Edit button above the tableView.
If you want to change the button above your tableView I believe you will need to create your own button and implement the setEditing:animated: functionality yourself.
See here for more info: http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html
Edit:
The function you're using should be in the TableView's delegate.
Related
I'm quite new to iOS development. I have read about the issues with ViewControllers becoming huge and would like to follow the design I have seen in the answer to this previous question UITableView issue when using separate delegate/dataSource for my app which has 2 different tables and couple of buttons on one screen. But somehow I get confused in the storyboard connections to make between TestTableViewController and TestTableTestViewController.
Can anyone provide a sample working project or some screen shots on how to connect the UITableView delegate, data source and connecting outlet to the separate custom UIViewController subclass (TestTableTestViewController) in storyboard please?
Also, does this design work with xCode 5 / iOS 7 and above?
Note: For those having moved to Swift I strongly recommend using swift extensions for the delegate & data source and in fact any other implementation of an inherited class or protocol as per the 'Grouping' section of Natasha The Robot's blog post here
You have to create another class named as MyTableViewDataSource and implement TabbleViewDataSource methods in it. Create an a property of your data source class. Set data source in ViewController
Here is the examle:
#interface MyTableViewDataSource ()
#property (nonatomic, assign) int sectionOneRows;
#property (weak) id<YourDelegate> delegate;
#property (nonatomic, strong) NSArray *dataSourceArray;
#end
#implementation MyTableViewDataSource
#synthesize delegate=_delegate;
-(id) initDataSourceWithdArray:(NSArray *)array
delegate:(id)delegate
{
if (self = [super init]) {
self.dataSourceArray=array;
self.delegate = delegate;
}
return self;
}
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return numberOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cellToReturn = nil;
//Your code here
return cellToReturn
}
#pragma mark - UITableView Delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
//Your logic here
//implement the delegate method in you ViewController
[self.delegate performSelector:#selector(loadDetailsAtIndexPath:)withObject:indexPath];
}
}
In your ViewController:
self.myDataSource = [[MyTableViewDataSource alloc] initDataSourceWithdArray:self.dataArray delegate:self];
[self.myTableView setDataSource:self.myDataSource];
[self.myTableView setDelegate:self.myDataSource];
[self.myTableView reloadData];
Your delegate method:
-(void)loadDetailsAtIndexPath:(NSIndexPath *)indexPath
{
MyDetailViewController *myDetailController = [[MyDetailViewController alloc] initWithNibName:#"MyDetailViewController" bundle:nil];
//Your logic here
[self.navigationController pushViewController:myDetailController animated:YES];
}
Go to the Connections Inspectors and make changes like this:
Data source for the tableView will be set programatically here rather in IB.
I hope this will help you.
Press and hold Ctrl and click + hold + drag on item you want to make outlet to .h file. it will make connection by itself you just have to name them.
See This Video Tutorial
Also check these tutorials
Link 1
Link 2
I created master details template project in xcode 4.6 and I added custom cell with 2 textfields. I also created new class which is subclass of UITableViewCell and inside this class I created outlets for text fields. When user types something NSMutableArray is updated and this works fine. Now I am wondering how to pass this array back to MasterViewController (UITableViewController) so that I can use this data to show calculations.
I tried using tutorials for delegates between UIViewControllers but I keep getting errors. Any help is appreciated.
You shouldn't keep data inside the UITableViewCell, as it breaks the MVC.
You need to get a reference of the UITextField on your cell. This is how I do in a login form:
I have a custom cell subclass called TextFieldCell, it has an outlet called textField, I want that my UITableViewController have references to these UITextFields.
First I open my storyboard, set the cell class to TextFieldCell and than connect the UITextField to cell textField outlet. Than I add this to the tableView:cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
(…)
if (indexPath.row == 0) {
// Sets the textField of the first cell as the loginTextField.
self.loginTextField = tCell.textField;
} else {
// Sets the textField of the second cell as the passwordTextField.
self.passwordTextField = tCell.textField;
}
tCell.textField.delegate = self;
(…)
}
Now I can access the value of my loginTextField and my passwordTextField. I do that on the tableView:cellForRowAtIndexPath: because that's when I'm creating the cell to add to the table view.
In your case you need to create Protocol:
I just Give Basic Idea for how to Create Protocol
Also Read This Question
#DetailViewController.h
#import <UIKit/UIKit.h>
#protocol MasterDelegate <NSObject>
-(void) getButtonTitile:(NSString *)btnTitle;
#end
#interface DetailViewController : MasterViewController
#property (nonatomic, assign) id<MasterDelegate> customDelegate;
#DetailViewController.m
if([self.customDelegate respondsToSelector:#selector(getButtonTitile:)])
{
[self.customDelegate getButtonTitile:button.currentTitle];
}
#MasterViewController.m
create obj of DetailViewController
DetailViewController *obj = [[DetailViewController alloc] init];
obj.customDelegate = self;
[self.navigationController pushViewController:reportTypeVC animated:YES];
and add delegate method in MasterViewController.m for get button title.
#pragma mark -
#pragma mark - Custom Delegate Method
-(void) getButtonTitile:(NSString *)btnTitle;
{
NSLog(#"%#", btnTitle);
}
I've done this before but I have no idea what I'm missing.
I started the project as a single View project.
Then converted the ViewController to inherit from UITableViewController like so:
#interface ViewController : UITableViewController
went into the .xib for this ViewController and changed the class in the Custom Class section form UIView to UITableView:
Looking in my other project(s) where the ViewControllers are just straight TableView controllers, I don't see what else needs to be done, but when I run the app or when I view the xib it's not showing a tableview.
You'll need to drag out a UITableView in Interface Builder to replace the UIView. Then add the UITableViewDataSource and UITableViewDelegate protocols to your view controllers header file and connect the datasource and delegate outlets from your UITableView to your view controller in Interface Builder.
#interface ViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate>
add delegate & dataSource. i think you are forgotten to add delegates &dataSource thats why its not showing table. add following lines to your viewDidLoad().
self.myTableView.dataSource = self;
self.myTableView.delegate = self;
after this also implements the required methods of delegate, that are
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return
10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//your code for cell data
}
What init method are you using in the .m file. You need to use the
[[UITableViewController alloc] initWithStyle:UITableViewStylePlain]
allocation method and make sure you have included the<UITableViewDataSource, UITableViewDelegate> and the relevant datasource and delegate methods.
Ok,
basically, if you want to just have a UITableViewController from scratch without having to manually do the above, just create a new Obj-C class, have it inherit from UITableViewController, and select to create a xib, and it will give you a viewcontroller and view already wired to working with a UITableView:
EDIT2: I try to summarize my problem and the solutions:
I've got a TableViewController named DetailedViewController. My intention was to activate TouchesBegan to recognize actions like sliding etc, and normally, the method touchesbegan is replaced with the DidSelectRow method. In many posts on stackoverflow, subclassing the UITableView is the only possibility to realize this.
So i created a SpecificTable with .xib file and i used this as a subclass of UITableViewController by adding the SpecificTable as the nib-file.
Selecting a row works fine, and also the TouchesBegan method (i called a method IN the SpecificTable.m with an Alert.) But now i want to call a Method in the UITableViewController (DetailedViewController) where moveToNextItem is declared like
-(void)moveToNextItem:(id)sender
{
[self.navigationController
pushViewController:bbarChart animated:YES];
}
But by calling this method with [self moveToNextItem] the App crashes by touching. (in the Debugger-Mode, the App crashes in the line of [self moveToNextItem].
What is the right way to call the method of DetailedViewController.m?
Update: You should probably subclass UITableViewCell rather than UITableView. Then in your table view controller's cellForRowAtIndexPath: method, return an instance of this subclass rather than an instance of UITableViewCell.
You will also need to pass a DetailedViewController pointer on to the cell, so that you can invoke its moveToNextItem method in the touchesBegan, etc. methods.
Adapt this example to your needs:
MyTableViewCell.h
#class DetailedViewController;
#interface MyTableViewCell : UITableViewCell {
DetailedViewController *dvc;
}
#property (nonatomic, retain) DetailedViewController *dvc;
#end
MyTableViewCell.m
#import "MyTableViewCell.h"
#import "DetailedViewController.h"
#implementation MyTableViewCell
#synthesize dvc;
- (void)someMethod { // This would be your touchesBegan, etc. methods
[dvc moveToNextItem];
}
- (void)dealloc {
[dvc release]; // We retained dvc so we have to release it when we're done with it
[super dealloc];
}
#end
DetailedViewController.h
#interface DetailedViewController : UITableViewController {
// iVars here
}
// Methods and properties here
- (void)moveToNextItem;
#end
DetailedViewController.m
#import "DetailedViewController.h"
#import "MyTableViewCell.h"
#implementation DetailedViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyTableViewCell"];
if(cell == nil) {
cell = [[[MyTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyTableViewCell"] autorelease];
cell.dvc = self; // This gives the cell a reference to the detailed view controller
}
return cell;
}
- (void)moveToNextItem {
// ...
}
#end
There are probably far better ways to achieve what you want, but this is the best I can do without more information.
Declare the method in DetailedViewController.h, and #import that file in SpecificTable.h.
if SpecificTable is really a subclass of DetailedViewController you can call
[self moveToNextItem];
as already mentioned.
but i think you mean a subview or not? so SpecificTable.view is a subview ob DetailedViewController.view
you have several options then. for example using NSNotificationCenter.
or what is probably also a good way for you is to setup an instance variable of DetailedViewController in your SpecificTable and assign it when you init your SpecificTable.
as an example:
// the parent view .m
testTVC *tableview = [[testTVC alloc] initsomething];
tableview.parentVC = self;
[self.view addSubView:tableview.view];
[tableview release];
now in your testTVC
// the .h
#interface testTVC : UITableViewController {
testVC *parentVC;
}
#property(nonatomic,retain) testVC *parentVC;
#end
// the .m
[parentVC moveToNextItem];
you also have to synthesize and release your parentVC.
Is [NSNotificationCenter defaultCenter] something you are looking for?
The typical UITableView usage pattern is to have the main UIViewController become a target datasource and delegate for the UITableView it is holding on to.
Are there any simple and easy to follow tutorials that would help me figure out how to move the code that pertains to the UITableViewDelegate and UITableViewDataSource methods into a separate class and hook that to my UIViewController instead? I would ideally like to have both the delegate and datasource living in the same class.
Right now, I am creating the UITableView via Interface Builder and connecting its outlet to my controller class.
Typical code:
#interface MyController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
IBOutlet UITableview *myTableview;
}
I want to do something more like this:
#interface MyController : UIViewController
{
IBOutlet UITableview *myTableview;
}
#end
#interface MyTableSourceDelegate : NSObject<UITableViewDelegate, UITableViewDataSource>
{
}
#implementation MyTableSourceDelegate
// implement all of the UITableViewDelegate and methods in this class
#end
I spend 2 hours to solve this problem:
It's working for me
// GenreDataSource.h
#import Foundation/Foundation.h
#interface GenreDataSource : NSObject <UITableViewDataSource> {
NSArray *dataSource;
CGSize cellSize;
}
#property(nonatomic, assign) CGSize cellSize;
#end
// GenreDataSource.m
#import "GenreDataSource.h"
#implementation GenreDataSource
#synthesize cellSize;
-(id)init{
self = [super init];
if ( self != nil ) {
dataSource = [[NSArray alloc] initWithObjects:#"All",#"Folk",#"Disco",#"Blues",#"Rock",#"Dance",#"Hip-Hop",#"R&B",#"Soul",#"Lounge",#"Techno",#"Bubstep", nil];
}
return self;
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [dataSource count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"CellPicker";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero] autorelease];
[cell setSelectionStyle:UITableViewCellSelectionStyleGray];
//сконфигурируем структуру
FontLabel *fLabel= [[FontLabel alloc] initWithFrame:CGRectMake(30,
5,
cellSize.width-30,
cellSize.height-5)
fontName:#"HelveticaNeueCondensedBlack"
pointSize:18.0f];
[fLabel setTextColor:[UIColor darkTextColor]];
[fLabel setTag:101];
[fLabel setBackgroundColor:[UIColor clearColor]];
[cell.contentView addSubview:fLabel];
[fLabel release];
}
FontLabel *fLabel = (FontLabel*)[cell viewWithTag:101];
[fLabel setText:[dataSource objectAtIndex:indexPath.row]];
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
#end
First thing is if you're using a UITableViewController subclass with interface builder you will want to disconnect the delegate and datasource outlets that are already hooked up by default. (Hint, look in the connections inspector). Check even if you have a tableView inside a viewController.
Second create your classes and make sure they conform to <UITableViewDelegate> and <UITableViewDataSource>. You're probably going to have to declare this contract in the .h file if you're using objc.
Third, In your view controller instantiate this class or two separate classes somewhere like viewDidLoad, and then assign self.tableView.delegate = myCustomDelegateInstance and self.tableView.dataSource = myCustomDataSourceInstance.
Now, any calls that come through the controller will be dispatched to your custom handlers. Pretty basic.
The only reason to really do this is if you 1) have a very bloated controller, or 2) you need to reuse the dataSource and delegate methods somewhere else and you want to avoid code repetition. Otherwise, it's probably better practice to leave it put.
You can create separe classes (with UITableViewDelegate , UITableViewDataSource) and add them in IB as external files and link the IBActions
In IB, you can drag a 'External Object' from Library->Cocoa Touch->Controllers into your xib window. You can then select that object, view the inspector, and set the class. It is now available to serve as a delegate, etc.