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
Related
I have a table view with 7 rows, I want to click on my rows and load the detailView( uiViewController )
I can select the row and I can see the Log in console but it never loads the detail view
would you please give me some hits, what is the problem?
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSLog(#"selected rows");
MyBookDetailView *c = [[MyBookDetailView alloc] init];
[self.navigationController popToRootViewControllerAnimated:NO];
[self.navigationController pushViewController:c animated:YES];
}
I also try performSelectorOnMainThread but still it just clickable and I have problem to load my view controller, I also add delegate in - (void)viewDidLoad method,
Thanks in advance!
lates code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
MyBookDetailView *c = [[MyBookDetailView alloc] initWithNibName:#"MyBookDetailView" bundle:nil];
[self.navigationController pushViewController:c animated:YES];
}
Why you want to pop up all controllers withing navigationcontroller stack to root controller and same time your want to push up new MyBookDetailView (i hope its base class is UIViewController).
Anyways, MyBookDetailView *c = [[MyBookDetailView alloc] init]; also will not work for you. Because c object of UIViewController (MyBookDetailView) view is nil. I recommend use break point trace execution stack and variable that you trying to remove and adding on run time you will better know what going on in your program.
I think following code may work for you,
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
MyBookDetailView *c = [[MyBookDetailView alloc] initWithNibName:#"WriteYourNibNameIfYouCreate" bundle:nil];
[self.navigationController pushViewController:c animated:YES];
}
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.
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.
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.
i tried to understand the uitable view and implemented it and able to populate data into row from a nsArray.I have make a NextViewController consisting of a dynamic lable which will receive inpur/text from the SimpleTable class.For ex,
in simple table view class i have rows with content as(see code please):
**My SimpleViewController.m**
#import "SimpleTableViewController.h"
#import "NextViewController.h"
#implementation SimpleTableViewController
- (void)viewDidLoad {
arryData = [[NSArray alloc] initWithObjects:#"iPhone",#"iPod",#"MacBook",#"MacBook Pro",nil];
self.title = #"Simple Table Exmaple";/**/NOT ABLE TO SET TITLE.WHY?????Please guide how to use NSlog here**
[super viewDidLoad];
}
***//And on selection of any row i want to navigate to next view controller class***
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NextViewController *nextController = [[NextViewController alloc] initWithNibName:#"NextViewController" bundle:nil];
[self.navigationController pushViewController:nextController animated:YES];
[nextController changeProductText:[arryData objectAtIndex:indexPath.row]];
}
#end
**My NextViewController.h**
#interface NextViewController : UIViewController {
IBOutlet UILabel *lblProductTxt;
}
- (IBAction) changeProductText:(NSString *)str;
#end
**my NextViewController.m**
//posted only important part of code where i feel may be an issue
- (IBAction) changeProductText:(NSString *)str{
lblProductTxt.text = str;
} #end
I have check IB properly and the connections are proper.Please help me.Not getting where i am wrong?
Make sure self.navigationController has a valid value. Add this before the pushViewController call:
NSLog(#" self.navigationController 0x%x", self.navigationController);