how to call didSelectRowAtIndexPath from another class - iphone

I am in situation where i need to call didSelectRowAtIndexPath from another calls for that i do like this
i make object of that class and call viewdidload so my table view get initialised
- (void)_hideTapped:(id)sender
{
LeftController *left = [[LeftController alloc]init];
[left viewDidLoad ];
}
in LeftController
- (void)viewDidLoad {
[super viewDidLoad];
mainArray = [[NSMutableArray alloc]initWithObjects:#"Go To Camera",#"Big Contacts List",#"Where Am I? On map",#"Watch And Alarm",#"Calculator With Big Letters",#"Big KeyBoard For Email",#"Calendar With Events",#"Settings", nil ];
// NSLog(#"mainArray%#",mainArray);
if (!_tableView) {
UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
tableView.delegate = (id<UITableViewDelegate>)self;
tableView.dataSource = (id<UITableViewDataSource>)self;
[self.view addSubview:tableView];
self.tableView = tableView;
[self iDecideWhichCell];
}
}
-(void)iDecideWhichCell
{
NSIndexPath *path = [NSIndexPath indexPathForRow:0 inSection:0];
[self tableView:self.tableView didSelectRowAtIndexPath:path];
}
this is part of my didSelectRowAtIndexPath
i am using JASidePanels for splitview like facebook and this is how they push viewcontroller it works fine if i go to leftcontroller and click by my self but when i do this whole process programmatically then its not working
if (indexPath.row ==0)
{
NSLog(#"%#",tableView);
self.sidePanelController.centerPanel = [[UINavigationController alloc] initWithRootViewController:[[NewViewController alloc] init]];
}
please any one can tell me how can i achieve this
i checked this answer calling didSelectRowAtIndexPath from other ViewController not responding iPad
but i dont understand how to implement this in my code

tableView:didSelectRowAtIndexPath: is a delegate method. You shouldn't call it directly. It is called for you when a table view row is selected.
You should create a delegate for the LeftController, so the LeftController can remain as the delegate of its own tableView.
Implement in LeftController.h:
#class LeftController;
#protocol LeftControllerDelegate
-(void)leftController:(LeftController *)leftController didSelectTableView:(UITableView *)tableView rowAtIndexPath:(NSIndexPath *)indexPath;
#end
#interface LeftController : UIViewController
#property(nonatomic, weak) id<LeftControllerDelegate> delegate;
// ... other public properties
-(id)initWithDelegate:(id<LeftControllerDelegate>)delegate;
// ... other public methods
#end
Implement in LeftController.m:
-(id)initWithDelegate:(id<LeftControllerDelegate>)delegate
{
self = [super init];
if (self) {
self.delegate = delegate;
}
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
//create the tableView...
//set the tableView delegate
tableView.delegate = self;
//do other view setup...
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.delegate leftController:self didSelectTableView:tableView rowAtIndexPath:indexPath];
}
In your other view controller implementation, e.g. MyOtherController.m:
//create instance of LeftController that has self as delegate
LeftController *left = [[LeftController alloc] initWithDelegate:self];
and implement the delegate method:
-(void)leftController:(LeftController *)leftController didSelectTableView:(UITableView *)tableView rowAtIndexPath:(NSIndexPath *)indexPath
{
//Yay! This instance of MyOtherController has received the delegate message from LeftController, including details of table view and row selected.
}
Effectively here, you have a delegated the tableView messages to the LeftController, and in turn you've delegated the LeftController functionality to its delegate. You set its delegate in the init method when you created and initialised it.
Hope it makes sense, let me know!

You can make your own method in which class you want to handle didSelectRowAtIndexPath and call that method from didSelectRowAtIndexPath of same class. Also Set delegate to handle events.

Related

CellForRowAtIndexPath is not invoked

I'm writing an app hat has many views and I used sliding views library (ECSlidingViews). The problem is when I fill an array with objects and fill the table with the objects in tableView:cellForRowIndexPath: method, it does present the data in the table, but when I go to other view and come back the data disappears because tableView:cellForRowIndexPath: is not called. Here is the code:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"begin of cellForRowAtIndexPath");
SchedualeCell *cell = (SchedualeCell *)[tableView dequeueReusableCellWithIdentifier:#"Cell"];
Course *temp = [array objectAtIndex:indexPath.row];
cell.nameLb.text = temp.name;
cell.hourLb.text = [NSString stringWithFormat:#"%d",temp.hour];
cell.startTimeLb.text = temp.startTime;
cell.endTimeLb.text = temp.endTime;
NSLog(#"End of cellForRowAtIndexPath");
return cell;
}
tableView:numberOfRowsInSection: and numberOfSectionsInTableView: is invoked when I come back to the view that has the table view.
P.S.: The view is UIViewController that has table view inside of it, and I searched all StackOverflow before posting my problem.
EDIT : this is where I set the delegate and datasource
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Did Appear");
// Do any additional setup after loading the view.
self.view.layer.shadowOpacity = 0.75f;
self.view.layer.shadowRadius = 10.0f;
self.view.layer.shadowColor= [UIColor blackColor].CGColor;
if (![self.slidingViewController.underLeftViewController isKindOfClass:[MenuViewController class]])
{
self.slidingViewController.underLeftViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Menu"];
}
[self.view addGestureRecognizer:self.slidingViewController.panGesture];
if (array == nil)
{
array = [[NSMutableArray alloc]init];
}
table.delegate = self;
table.dataSource = self;
[table reloadData];
}
and I did included The delegate and datasource in the header
#interface MainViewController : UIViewController<UITableViewDataSource , UITableViewDelegate,addDelegate>
First of all , it's not numberOfRowsAtSection and numberOfTableView. It's numberOfSectionsInTableView and numberOfRowsInSection.
Things you can do :
1) NSLog your numberOfRowsInSection. Note that , If it's "0" then your cellForRowAtIndexPath is never going to be called.
2) If you are using your UITableView inside some UIView then you should add :
[self.view addSubview:table];
3) Don't Forget to include :
#interface yourViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
Once check that you reframed the tableview in ViewWillAppear.
Some times if we set out of frame, CellForRowAtIndexPath will not call.

UITableView becomes Nil After getting response from server

This is my scenario,
I have ViewController1 and Class1(Service Class).
I am loading tableView in nib by setting delegate and datasource in ViewController1. In viewDidLoad, i am calling a networkCall function in another class(Class1). In Class1, After getting a response it will pass an array of response data to a function in ViewController1 where the data should be populated in tableview.
i have connected datasource and delegate in xib.
Problem:
When i get a response as an array in ViewController1, UITableView becomes nil, i cannot able to use reloadData, but my array contains list of items from server.
Here's my code
ViewController1
- (void)viewDidLoad
{
[super viewDidLoad];
ClassA *class = [[ClassA alloc]init];
[class getResponse];
}
//This method is calling from ClassA using delegate
-(void)responseData:(NSArray*)arrayList
{
//arrayList have response data
[tableView reloadData];//here tableView becomes nil.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"array count %d",array.count);//has number of items(for me, its 3).
return array.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"TableView";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = #"dsds";
return cell;
}
tableView is calling first time.
In ViewController1
in interface, i am setting protocols
<UITableViewDelegate,UITableViewDataSource>
You are creating new instance of ViewController1 instead of using the one that has been loaded.
you can do the following:
for ClassA:
interface:
#interface ClassA : ...
#property (weak) ViewController1 * vcDelegate;
...
#end
implementation:
#implementation ClassA
#synthesize vcDelegate;
...
#end
and instead of
id<ViewController1Protocol>view1 = [[ViewController1 alloc]init];
[view1 responseData:objects];
call
[vcDelegate responseData:objects];
In your ViewController, when creating ClassA you need to set delegate to self:
- (void)viewDidLoad
{
[super viewDidLoad];
ClassA *class = [[ClassA alloc]init];
[class setVcDelegate: self];
[class getResponse];
}
It's not the best implementation, but should give you idea of how to do it.
For example, property should probably be
#property (weak) id<ViewController1Protocol> vcDelegate;
You have to connect your tableView with the table view in the xib.
The red region in the image is not connected with your table view. It is empty.

Why is my delegate method not called?

this is probably simple but I'm stuck!
Basically I have a parent and child view controller, and I'm trying to pass data from the child to the parent.
//Child VC interface
#protocol ANSearchGetawayFilterDelegate
-(void)selectedCell:(NSString *)cellTitle;
#end
#interface ANSearchGetawayFilterViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate>
{
NSString* cellTitle;
}
#property (nonatomic, assign) id<ANSearchGetawayFilterDelegate> delegate;
#end
//Child VC implementation
#implementation ANSearchGetawayFilterViewController
#synthesize delegate = _delegate;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
cellTitle = selectedCell.textLabel.text;
[[self delegate] selectedCell:cellTitle];
[self dismissModalViewControllerAnimated:YES];
}
//Parent VC interface
#import "ANSearchGetawayFilterViewController.h"
#interface ANGetawayFilterViewController : UIViewController <ANSearchGetawayFilterDelegate>
{
NSString* _cellText;
}
//Parent VC Implementation
- (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
ANSearchGetawayFilterViewController *search = [[ANSearchGetawayFilterViewController alloc] init];
search.delegate = self;
}
return self;
}
//delegate method
-(void)selectedCell:(NSString *)cellTitle
{
_cellText = cellTitle;
NSLog(#"cell text %#", _cellText);
}
the delegate method is never called and when is NSLog the _cellText else where it comes up as null...what am I doing wrong? Thanks!
You are most likely creating a new instance of ANSearchGetawayFilterViewController when you present it and not configuring the delegate on it.
When you called
ANSearchGetawayFilterViewController *search = [[ANSearchGetawayFilterViewController alloc] init];
search.delegate = self;
you created an instance of ANSearchGetawayFilterViewController and then set the delegate up correctly, but you never stored this instance of ANSearchGetawayFilterViewController anywhere. So later on when you come to present it you call again
ANSearchGetawayFilterViewController *search = [[ANSearchGetawayFilterViewController alloc] init];
which gives you a completely different instance, which you then need to configure again. For example
ANSearchGetawayFilterViewController *search = [[ANSearchGetawayFilterViewController alloc] init];
ANSearchGetawayFilterViewController *search1 = [[ANSearchGetawayFilterViewController alloc] init];
NSLog(#"%d", search1 == search);
#=> 0
To fix update your code to be
- (BOOL)textFieldShouldBeginEditing:(UITextField*)textField;
{
BOOL shouldBeginEditing = YES;
NSLog(#"text field should begin editing");
ANSearchGetawayFilterViewController *myANSearchGetawayFilterViewController = [[[ANSearchGetawayFilterViewController alloc] init] autorelease];
myANSearchGetawayFilterViewController.delegate = self; // <--- configure the delegate
[self presentModalViewController:myANSearchGetawayFilterViewController animated:YES];
[self closeAllPickers];
return shouldBeginEditing;
}
I wouldn't make it an ivar as the likelihood is you will present this viewController momentarily just to select some data and then get rid of it, so it is probably safe to discard it and make a new one each time.
Au contraire, the delegate method is being called (hence the NSLog()). However, _cellText is (null) because the value being passed in is nil, ergo selectedCell.textLabel.text.
Firstly, are you sure that the -selectedCell method is being called?
You can do this by putting an NSLog() before or after -tableViewDidSelectRow...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
...
NSLog(#"TABLEVIEW DID SELECT ROW BEFORE -> %# <-", cellTitle);
[[self delegate] selectedCell:cellTitle];
NSLog(#"TABLEVIEW DID SELECT ROW DELEGATE CALLED");
...
}
Also, you might want to do some cleanup (optional)
Firstly, you are leaking in your initialisation method. Either set the ANGetawayFilterViewController as a property of the parent class using the delegate, or release it after you set the delegate.
Secondly, in the -tableViewDidSelectRow, your code assumes that the delegate has the -selectedCell method coded. If you don't have the method implemented, then the application will result in a crash. You can prevent this by checking to see if the delegate -respondsToSelector...:
if ([self.delegate respondsToSelector:#selector(selectedCell:)]) {
[self.delegate selectedCell:cellTitle];
}
Thirdly, the method of which is being called by the delegate to notify the parentViewController doesn't follow the general schema that delegate methods use, with the exception of -numberOfRowsInSection (UITableViewDelegate). Your method should contain the actual ANFilterGetawayViewController instance too:
- (void) filterGetawayViewController:(ANSearchGetawayFilterViewController *) controller didSelectCellWithTitle:(NSString *) title {
...
}
It can be called as such:
[self.delegate filterGetawayViewController:self didSelectCellWithTitle:cellTitle];
Are you using ARC? Because when the init function ends, your object (and it's reference to the delegate) are cleaned up. What happens if you make the search variable a global one (defining it in your header and initializing it in your code)?
Assuming you are using ARC:
You need to make a retained #property for your ANSearchGetawayFilterViewController instance. It will have been released by ARC by the time the delegate method is called. Do something like this.
#property (strong, nonatomic) ANSearchGetawayFilterViewController *search;
...
#synthesize search = _search;
- (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
self.search = [[ANSearchGetawayFilterViewController alloc] init];
self.search.delegate = self;
}
return self;
}
Not related to your problem, but best practice is to check if the delegate actually implements the method you expect it to before calling it, like so:
if ([self.delegate respondsToSelector:#selector(selectedCell:)]) {
[self.delegate selectedCell:cellTitle];
}

How to pass data to detail view after being selected in a table view?

I have a UITableViewController that has data populated from an NSMutableArray called userList. When specific user is selected, it goes to a detail view, and updates the title in the NavBar, but it wont pass the data to update a UILabel in the UIView.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
//Attempt at a singleton to pass the data
DetailView *details = [[DetailView alloc] init];
details.userNameLbl = [userList objectAtIndex:indexPath.row];
DetailView *detailVC = [[DetailView alloc] initWithNibName:nil bundle:nil];
//This line doesn't pass the data
detailVC.userNameLbl.text = [userList objectAtIndex:indexPath.row];
//This line does update the title in the NavBar
detailVC.navigationItem.title = [userList objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailVC animated:YES];
[details release];
[detailVC release];
}
Should I be trying to push the data from the table view to the detail view, or have the detail view try to pull the data from the table view?
DetailView.h has the following line that is in fact hooked up in IB.
IBOutlet UILabel *userNameLbl
The userNamelbl isn't instantiated until the view is loaded from the nib file. This doesn't happen immediately at initialisation, but will have happened by the time viewDidLoad is called.
So, you should to declare a property in DetailView to store your title, and then assign that value to userNamelbl.text in the viewDidLoad method.
For example, in your table viewController:
DetailView *detailVC = [[DetailView alloc] initWithNibName:nil bundle:nil];
detailVC.userName = [userList objectAtIndex: indexPath.row];
and in your detail viewController:
- (void) viewDidLoad
{
[super viewDidLoad];
self.userNameLbl.text = self.userName;
}
The viewController's navigationItem property is created when the viewController is initialised, hence you can assign to the navigationItem.title immediately.
Swift code
let detailVC = DetailView(nibName: nil, bundle: nil)
detailVC.userName = userList.objectAtIndex(indexPath.row) as? NSString
and
class DetailView: UIViewController {
#IBOutlet var userNameLbl: UILabel
var userName:NSString?
override func viewDidLoad() {
super.viewDidLoad()
self.userNameLbl.text = self.userName
}
}
Are you mixing UIViews and UIViewControllers? You should have a DetailViewController class that inherits from UIViewController or some sublcass (like UITableViewController); it will have DetailViewController.m and DetailViewController.h files to declare and define your class. It should have a corresponding nib that defines the UIView that the UIViewController loads; it will have a DetailView.xib file.
You can't assign the value to the UILabel directly because UIView hasn't been loaded at the time you need to assign the user name value.
In order to do what you want, you should declare a public property (userName) to "push" the value onto the detail view controller from the master controller. Once the detail view is loaded, it can assign the value from the property to the label and nav bar.
In your master view controller (UITableViewController):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
DetailViewController *detailVC = [[DetailView alloc] initWithNibName:#"DetailView" bundle:nil];
detailVC.userName = [userList objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailVC animated:YES];
[detailVC release];
}
In your detail view controller:
DetailViewController.h
#property (retain) NSString* userName;
#property (nonatomic, retain) IBOutlet UILabel *userNameLbl;
DetailViewController.m
#synthesize userName;
#synthesize userNameLbl;
-(void) viewDidLoad {
[super viewDidLoad];
self.userNameLbl.text = self.userName;
self.navigationItem.title = self.userName;
}
Presumably your DetailView requires the data from your selected row to function?
If so, I'd say the 'correct' approach would be to create a custom init method that passed in the data you required. For example:
[[DetailView alloc] initWithTitle:(NSString *)title text:(NSString *)text]
There's nothing inherently wrong with your approach, but passing the data the view controller requires at its creation is architecturally better (in my opinion, I'm sure someone will disagree!). For example, think of a table view controller - you pass in the table view style in the init method, you don't set it later on. Same for a UIImageView - you have an initWithImage method that lets you set the image at creation.

Call UIViewController from "subview"

I have a UIViewController which when it loads it loads up this..
MapViewController *mapController = [[MapViewController alloc] initWithNibName:#"MapView" bundle:nil];
self.mapViewController = mapController;
[self.view insertSubview:mapController.view atIndex:0];
[mapController release];
I also have a switch views button that can change to a table view....
if (self.tableViewController ==nil)
{
TableViewController *tableController = [[TableViewController alloc] initWithNibName:#"TableView" bundle:nil];
self.tableViewController = tableController;
[tableController release];
//[self.view insertSubview:detailController atIndex:0];
}
if (self.mapViewController.view.superview == nil)
{
[tableViewController.view removeFromSuperview];
[self.view insertSubview:mapViewController.view atIndex:0];
}
else
{
[mapViewController.view removeFromSuperview];
[self.view insertSubview:tableViewController.view atIndex:0];
}
I am trying to change the view to a detail view based on selecting a row in the table view and I cannot work out how to call it at all. All methods I have seem to fail! Please help!
Add the UITableViewDelegate protocol to your controller class.
#interface myTableViewController : UITableViewController <UITableViewDelegate>
When you create your table veiw controller set its delegate to be your controller using:
myTableViewController.delegate = self; // Assuming your setup code runs within the table view controller
In your tableViewController, implement didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int rowSelected = [indexPath indexAtPosition:0]; // Assuming your UITableView has a single section.
The class you should look at for handling row selection is UITableViewDelegate, which has the method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath