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?
Related
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);
}
So I have a Custom UITableViewCell that holds a reference to its containing view controller (the VC that has its table in it).
// MyCell.h
#import <UIKit/UIKit.h>
#import "RootViewController.h"
#interface MyCell : UITableViewCell
#property (nonatomic, strong) IBOutlet RootViewController *rootViewController;
-(IBAction)checkBoxClicked:(UIButton*)sender;
// MyCell.m
#implementation MyCell
#synthesize rootViewController = _rootViewController;
-(IBAction)checkBoxClicked:(UIButton*)sender
{
[self setCheckBoxChecked:!_checkBoxChecked];
[_rootViewController refreshVisibleViewForCellTagged:self.tag];
}
In my cell I have a button that changes a variable and then calls a function in my rootViewController. The method is actually called however when I try to access any object in the RootViewController inside of the refreshVisibleViewForCellTagged method they are are '0x0' / nil;
// RootViewController.h
#interface RootViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) IBOutlet UITableView *myTableView;
// RootViewController.m
- (void) refreshVisibleViewForCellTagged:(NSInteger)cellTag
{
UITableView *tableView = self.myTableView; // nil
NSIndexPath *indexPath = [self.myTableView indexPathForSelectedRow]; // nil
MyCell *selectedCell = (MyCell*)[self.myTableView cellForRowAtIndexPath:indexPath]; // nil
if (selectedCell.tag == cellTag) {
NSLog(#"Refresh one way.");
} else {
NSLog(#"Do something else.");
}
}
Can anyone shed some light as to why I cant access any objects/variables in the RootController from within the method 'refreshVisibleViewForCellTagged'?
Please and thank you!
** My big question is Why can't I access any objects when calling a method in a view controller From a different view controller. There is some great programming truth that I am not aware of here, is it a permissions issue? Im not using #class (forward classing) in this instance.
As #trojanfoe said, delegation is a better way to do it.
Instead of #import "RootViewController.h", it is better to adop delegation. Because UITableViewCell is a child and RootViewController is the parent view. You don't want the child to talk directly with the parent.
To adopt delegation:
in MyCell.h file
remove #import "RootViewController.h".
revise MyCell.h as follows:
#protocol MyCellDelegate; // if you need to have forward declaration
#interface MyCell : UITableViewCell
// #property (nonatomic, strong) IBOutlet RootViewController *rootViewController;
#property (nonatomic) id <MyCellDelegate> delegate;
#end
#protocol MyCellDelegate <NSObject>
- (void)refreshVisibleViewForCellTagged:(NSInteger)cellTag;
#end
in MyCell.m.
#synthesize delegate;
-(IBAction)checkBoxClicked:(UIButton*)sender {
[self setCheckBoxChecked:!_checkBoxChecked];
//[_rootViewController refreshVisibleViewForCellTagged:self.tag];
[self.delegate refreshVisibleViewForCellTagged:self.tag];
}
in RootViewController.h adopt the delegation of MyCell
#import "MyCell.h"
#interface RootViewController : UIViewController <MyCellDelegate>
in RootViewController.m.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = // your implementation
//assuming all your cells are of MyCell kind
// set RootViewController as the delegate of each cell
((MyCell *)cell).delegate = self;
return cell;
}
implement the delegate method in RootViewController.m.
- (void)refreshVisibleViewForCellTagged:(NSInteger)cellTag {
// whatever you have
}
P.S. The above codes are for illustration. I didn't run them. If some part doesn't work, let me know, and I'll revise it.
The reason those objects in RootViewController are nil in the way you call, is because you are not accessing the same instance of RootViewController. It is a different (new) instance and hence all objects are nil.
Ignore the fact that view controllers are even involved. What you have are OBJECTS, connected together in a certain pattern. Accessing data in another view controller is no different from accessing data in any other object. There's no "magic" with view controllers, other than they have a few standardized connections to other objects.
IMHO, this is a poor design. For starters, your cell shouldn't need a reference to the view controller that the table it's in is in (read that twice, it barely makes sense just because the very idea of it is confusing). You have a strong reference to this view controller. So what happens when the OS tries to deallocate your view controller? It will never be able to, because the table view cell as a strong reference to it, keeping its retain count at 1. The same situation holds true for the cell. You risk running into a retain cycle here. Generally, child views should have weak references to their parents.
But this isn't even really a true parents/child relationship. I would suggest instead an approach like this, which all occurs in your view controller that contains the table view:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Assuming you set a reuse identifier "cellId" in the nib for your table view cell...
MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:#"cellId"];
if (!cell) {
// If you didn't get a valid cell reference back, unload a cell from the nib
NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:#"MyCell" owner:nil options:nil];
for (id obj in nibArray) {
if ([obj isMemberOfClass:[MyCell class]]) {
// Assign cell to obj, and add a target action for the checkmark
cell = (MyCell *)obj;
[cell.checkMarkButton addTarget:self action:#selector(checkPressed:) forControlEvents:whateverEventYouWant];
break;
}
}
}
// Set the tag of the cell here, since we may get a different cell back from the reuse queue
cell.checkMarkButton.tag = indexPath.row;
return cell;
}
Now set up the method for the clicking of the checkmark button
- (void)checkPressed:(id)sender {
UIButton *checkmark = (UIButton *)sender;
// This will give you the row of the checked button
int checkedCellRow = checkmark.tag;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:checkedCellRow inSection:0];
// Now you can grab a reference to that cell if you need to
MyCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
}
This way, you keep all of the controller-related stuff in your controller class (i.e. how to handle the checkmark button being pressed), and you don't need to deal with this whackiness of referencing the view controller of your cell's table.
EDIT: I guess I should also help answer your questions...First of all, if you're saying that in your refreshVisibleViewForCell method, you're getting a nil value for self.myTableView, are you sure it is hooked up properly in IB? Even if it's hooked up, click the little x to unhook it and hook it up again to be sure. Also make sure you've #synthesized your myTableView property. Without seeing more code, an IB issue is my best guess as to why you're getting a nil value for tableView. A nil value here will result in a nil indexPath and selectedCell, also. As for your big question, you can access properties of objects within your view controller. Those properties can, of course, be objects. So in your example, if you have a tag property on selectedCell, you can access it from anywhere that you have a valid reference to selectedCell. If selectedCell is nil, the property will be nil. #class is better suited for header files. For instance, if you wanted to make your custom cell a property of your view controller, you might say:
#import <UIKit/UIKit.h>
#class MyCell;
#interface RootViewController : UIViewController
#property (nonatomic, strong) MyCell *cell;
#end
Then, in your implementation file, you would actually import MyCell.h. Giving the #class forward declaration just keeps you from having to import all of the details about the MyCell class in your header file. The header doesn't need to know about all of the properties and methods of MyCell, just that you intend on using it in the implementation file. So you #class in the header, #import in the implementation.
in RootViewController.h:
#interface RootViewController : UITableViewController <UITableViewDelegate>
in RootViewController.m:
- (void) refreshVisibleViewForCellTagged:(NSInteger)cellTag {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
MyCell *selectedCell = (MyCell*)[self.myTableView cellForRowAtIndexPath:indexPath]; // nil
etc...
I'm not seeing declarations of myTableView in your RootViewController. But if your RootViewController implements UITableViewController, you can use self.tableView to access the tableview. You don't need to keep a reference to it by yourself.
#RachelD, if your RootView is more complicated than just a UITableViewController consider using a separate class, such as RootTableViewController. Then in your RootView xib, create IBOutlet for RootTableViewController to reference it. Like this:
// RootTableViewController definition
#interface RootTableViewController : UITableViewController
{
}
// RootViewController definition
#interface RootViewController : UIViewController
{
RootTableViewController *table_c;
}
#property (nonatomic, retain) IBOutlet RootTableViewController *table_c;
Note that you need to drag an "Object" into the "Objects" section (for RootViewController) in the interface builder, and type RootTableViewController in the Custom Class section for this object. Right click this object, make sure its IBOutlet, view, 2 delegates are correctly set.
The reason why your myTableView is nil is because it's not properly initialized. I mean, if you don't use UITableViewController you are responsible for assigning it manually via interface builder or something.
Hi I tried another code for passing data but it is not working. How to pass UITextField value on firstview on UITableViewCell on row? Please someone help me on delegate protocol
//
// first.h
// TextviewExample
//
// Created by pradeep.yadav on 12/5/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "second.h"
#import "TextviewExampleAppDelegate.h"
//#class second;
#interface first : UITableViewController <secondDelegate>{
//TextviewExampleAppDelegate*app;
//TextviewExampleAppDelegate *check;
second *secondview;
NSString *secondFavoriteColorString;
//second *value;
}
#property (nonatomic, retain) second *secondview;
#property (copy) NSString *secondFavoriteColorString;
#end
- (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] autorelease];
}
// Configure the cell...
cell.textLabel.text=#"message";
cell.detailTextLabel.text=secondFavoriteColorString;
NSLog(#"this second check:%#",secondFavoriteColorString);
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
second *viewTwo = [[second alloc] initWithNibName:#"second" bundle:[NSBundle mainBundle]];
self.secondview = viewTwo;
[viewTwo release];
[self.navigationController pushViewController:self.secondview animated:YES];
}
-(void)setsecond:(NSString*)secondtextview
{
secondFavoriteColorString = secondtextview;
NSLog(#"this second check:%#",secondFavoriteColorString);
}
this second class
//
// second.h
// TextviewExample
//
// Created by pradeep.yadav on 12/5/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import <UIKit/UIKit.h>
#protocol secondDelegate<NSObject>
#required
-(void)setsecond:(NSString*)secondtextview ;//forIndexPath:(NSIndexPath*)indexPath;
#end
#interface second : UIViewController {
IBOutlet UITextField *secondtextfield;
NSString *favoriteColorString;
id <secondDelegate> delegate;
}
#property (nonatomic,retain)UITextField *secondtextfield;
//#property (nonatomic,assign)id<secondDelegate>delegate;
#property (retain) id delegate;
#property (nonatomic,copy)NSString *favoriteColorString;
#end
#import "second.h"
#implementation second
#synthesize delegate,secondtextfield,favoriteColorString;
- (void) viewWillDisappear:(BOOL) animated
{
[[self delegate] setsecond:secondtextfield.text];
favoriteColorString=secondtextfield.text;
NSLog(#"thuis check:%#",favoriteColorString);
}
- (BOOL) textFieldShouldReturn: (UITextField *) theTextField
{
[theTextField resignFirstResponder];
return YES;
}
I think the trouble is that you have declared the delegate in the second view, and you are trying to call it from the first view. By the time you have returned to the first view, it's very likely that the second view has been cleaned up.
What you want to do is declare the delegate methods in the first view controller, and when you create the second view controller, you set the first view controller to be the delegate of the second view controller.
I created an example project a while ago. It doesn't deal with a table view, but it demonstrates passing a string back from a second view controller to the first view controller.
Here is a link to a tutorial how to share data between viewController:
http://www.iphonedevsdk.com/forum/iphone-sdk-development/54859-sharing-data-between-view-controllers-other-objects.html
It should help you out to solve your problem.
From TextField in View1 to Cell in View2
Take a String in Second View.
Property, synthesize it,
While moving from first view to second view Assign the value of UITextField to the synthesized string right after allocating and before pushing.
In second view display the text in synthesized string on the cell.
From TextField in View2 to Cell in View1
Take a String in First View.
Property, synthesize it,
Take a object of FirstView in secondView and property and synthesize it
While moving from first view to second view Assign the value of objSecondView.objFirstView=self; after allocating and before pushing.
Now in second view assign the value of text to firstViews synthesized string.
And in viewWillAppear of firstView assign the value of its string to the cell
E.g. Your method in the above example must look loke the one below
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
second *viewTwo = [[second alloc] initWithNibName:#"second" bundle:[NSBundle mainBundle]];
viewTwo.objViewOne = self;
[self.navigationController pushViewController:viewTwo animated:YES];
[viewTwo release];
}
Thats it.. Comment if still any problem faced.
I am trying to pass some information between a subview and a parentview on the navigation stack using delegates.
However for some reason when the I execute the delegate from the subview then pop the subview from the navigational controller it never enters the delegate method that is set up in the parent view.. I have tried NSLogs & Breakpoints the thread is defiantly not making it to this delegate method in the main view so I was hoping you could help me out.
First Of all I will show you how I have set up my delegate, where I call it in my subview and then where I set it up in the mainview hopefully you guys will be able to see something I have not so far.
Subview.h // I have left out things not related to the delegate
#import <UIKit/UIKit.h>
//Delegate - Protocol stuff for passing data from this view to the parent view
#protocol PassSearchData <NSObject>
#required
- (void) setManufactureSearchFields:(NSArray *)arrayValues withIndexPath:(NSIndexPath *)myIndexPath;
#end
#interface SecondViewController : UITableViewController <UITableViewDataSource> {
//Delegate (Used to pass information back to parent view)
id <PassSearchData> delegate;
}
//Delegate (Used to pass information back to parent view)
#property (strong) id delegate;
#end
SecondView.m
#import "SecondViewController.h"
#import "FirstViewController.h"
#implementation SecondViewController
//..
//Delegate (Used to pass information back to parent view)
#synthesize delegate;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//Access selected cells content (cell.textLabel.text)
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
//Parent view logic (sends info back to the correct cell in parent view)
if (parentViewSelectedIndexPath.section == 0)
{
if (parentViewSelectedIndexPath.row == 0)
{
//Predicates restrict the values that will be returned from the query
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K like %#",#"MANUFACTURER",cell.textLabel.text];
filterArray = [parsedDataArrayOfDictionaries filteredArrayUsingPredicate:predicate];
[[self delegate]setManufactureSearchFields:filterArray withIndexPath:indexPath];
// NSLog(#"Filtered Array = %#", filterArray);
}
}
[self.navigationController popViewControllerAnimated:YES]; //pops current view from the navigatoin stack
}//...
Then this is how I set it up inside the FirstViewController
FirstViewController.h
#import <UIKit/UIKit.h>
#import "VehicleResultViewController.h" //With this included I can now use the PassSearchData delegates of this view for passing data
#interface VehicleSearchViewController : UITableViewController <PassSearchData> {
//..
FirstViewController.m
#import "VehicleSearchViewController.h"
#import "VehicleResultViewController.h" //Subview
//..
#pragma mark - Received data from Sub view delegates
//These are the delegate method for passing data from the child to the parent view (parent being this view, with the delegate being declared in the subview)
- (void) setManufactureSearchFields:(NSArray *)arrayValues withIndexPath:(NSIndexPath *)myIndexPath
{
manufactureSearchObjectString = [[arrayValues valueForKey:#"MANUFACTURER"] objectAtIndex:0];
manufactureIdString = [[arrayValues valueForKey:#"MANUFACTURERID"] objectAtIndex:0]; //Restricts Models dataset
manufactureResultIndexPath = myIndexPath;
}
If anyone knows what I'm missing/doing wrong any help would be really really heapful
any questions let me know.
Solution
In the firstviewcontroller when I go to load the secondviewcontroller inside
tableView:didSelectRowAtIndexPath: I forgot to set the secondviewcontrollers delegate before I pushed the view to the navigational stack.. so the missing code was this.
FirstView.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//Get the subview ready for use
VehicleResultViewController *vehicleResultViewController = [[VehicleResultViewController alloc] initWithNibName:#"VehicleResultViewController" bundle:nil];
//Pass the selected object to the new view controller.
[self.navigationController pushViewController:vehicleResultViewController animated:YES];
[vehicleResultViewController setDelegate:self];
//etc
thanks guys.
Ok, first, your delegate should be a weak reference to avoid retain cycles. But I suspect maybe the delegate isn't getting set. Can you show the code where SecondViewController is instantiated and the delegate is set? Can you set a breakpoint at the delegate call and verify that it is not nil?
I think you are not setting Delegate.
After Creation Instanace(object)of SecondViewController ,you have to set Delegate.
ie
SecondViewController *secondObj=[[SecondViewController alloc]initWithNibName:#"SecondViewController"> bundle:nil];
[secondObj setDelegate:self];
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.