So I am trying to add in to my current Xcode project a table view which, whenever you click on a cell, whichever one it is, a new subview is added to the window. I will use global variables and the didSelectRowAtIndexPath to pass data on.
As it stands, I have my table view drawn on screen with the correct data inside. What I want to happen is when I click, a new subview is added but i cannot seem to get this to work.
I have tried adding the "addSubview" inside the didSelectRowAtIndexPath method itself and this did not work and I have tried declaring a separate method that loads a subview called 'loadDetails' then calling it with [self loadDetails] when a cell is selected but it wants an id after the call and I don't know what to pass in.
I have elsewhere in my project used the line:
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
But I can't see how to adapt this to the tableCell unless I could somehow add a new button over the cell? I really don't know.
If anybody has any other ideas of how to solve this problem, that would be great.
Thanks,
Matt
EDIT:
Problem is now solved, was a really stupid mistake, I forgot to link the view on the xib I was moving to, to the view created programmatically in my header file
try using presentModalViewController to show your view, and then dismiss it from the modalViewController:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailView *detailView = [[DetailView alloc] initWithNibName:#"DetailView" bundle:nil];
[self presentModalViewController:detailView animated:YES];
}
Related
I want to remove the selection color that appears when I touch a cell in my tableview.
In IB there is a "shows selection" checkbox that does nothing and it seems from what I can gather that it is just a bug in IB.
But then there is the
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
that I can set to each cell.
This also does nothing, so this is where I am stuck, all documentation say that if I set this property it should not appear but it does.
I push another UIViewController on a UINavigationController, and when I go back to the view in question, the blue background on the cell is stuck until I touch another one.
The only thing special is that I instantiate this UITableViewController with the help of storyboard and I use prototype cells. Then I put it inside a UIScrollView to have horizontal paging between multiple UITableViewControllers. There is no way to access the navigation controller when I do this so I pass the UINavigationController along to the UITableView.
Sorry that I can't make the keywords appear as code, it says I should press the tab key then type a $ but that moves my cursor to tags.
You might try to set the selectedBackgroundView of your cell like this :
customCell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.png"]];
In the delegate method cellForRowAtIndexPath
From code you can use (for example for grey):
cell.selectionStyle = UITableViewCellSelectionStyleGray;
And put this at:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
In your ViewController.
The solution was to set the style on the prototype cell in IB. Many things are wierd about prototype cells.
I can't seem to figure this out for the life of me. I have a custom table view cell, in that cell I have a few buttons configured. Each button connects to other view controllers via a storyboard segue. I've recently removed these segues and put a pushViewController method in place. Transition back and forth across the various views works as expected however the destination view controller is not displaying anything! I have some code below as an example.
Buttons have this method set:
[cell.spotButton1 addTarget:self action:#selector(showSpotDetails:) forControlEvents:UIControlEventTouchUpInside];
// etc...
[cell.spotButton4 addTarget:self action:#selector(showSpotDetails:) forControlEvents:UIControlEventTouchUpInside];
// etc...
showSpotDetails Method contains this code:
- (void)showSpotDetails:(id)sender
{
// determine which button (spot) was selected, then use its tag parameter to determine the spot.
UIButton *selectedButton = (UIButton *)sender;
Spot *spot = (Spot *)[spotsArray_ objectAtIndex:selectedButton.tag];
SpotDetails *spotDetails = [[SpotDetails alloc] init];
[spotDetails setSpotDetailsObject:spot];
[self.navigationController pushViewController:spotDetails animated:YES];
}
The details VC does receive the object data.
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"spotDetailsObject %#", spotDetailsObject_.name);
}
The NSLog method below does output the passed object. Also, everything in the details view controller is as it was. Nothing has changed on the details VC. It just does not render anything ever since I removed the segue and added the pushViewController method. Perhaps I am missing something on the pushViewController method? I never really do things this way, I try to always use segues...
Any suggestions?
Welcome to the real world. Previously, the storyboard was a crutch; you were hiding from yourself the true facts about how view controllers work. Now you are trying to throw away that crutch. Good! But now you must learn to walk. :) The key here is this line:
SpotDetails *spotDetails = [[SpotDetails alloc] init];
SpotDetails is a UIViewController subclass. You are not doing anything here that would cause this UIViewController to have a view. Thus you are ending up a with blank generic view! If you want a UIViewController to have a view, you need to give it a view somehow. For example, you could draw the view in a nib called SpotDetails.xib where the File's Owner is an SpotDetails instance. Or you could construct the view's contents in code in your override of viewDidLoad. The details are in the UIViewController documentation, or, even better, read my book which tells you all about how a view controller gets its view:
http://www.apeth.com/iOSBook/ch19.html
The reason this problem didn't arise before is that you drew the view in the same nib as the view controller (i.e. the storyboard file). But when you alloc-init a SpotDetails, that is not the same instance as the one in the storyboard file, so you don't get that view. Thus, one solution could be to load the storyboard and fetch that SpotDetails instance, the one in the storyboard (by calling instantiateViewControllerWithIdentifier:). I explain how to do that here:
http://www.apeth.com/iOSBook/ch19.html#SECsivc
I was using initWithNibName to push the cells to detail views but I want to use single storyboard rather than having numerous nib files. The below code is supposed to push the view to subcategoriesViewController when the cell is clicked. the cells are dynamic from json data.
Its not giving any errors. Do you think its an issue with navigation control? Just to test, I added a button on this view and it works; when I click it, it does push to next view.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dict = [rows objectAtIndex: indexPath.row];
subcategoriesViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"subcategoriesViewController"];
controller.CATNAME = [dict objectForKey:#"C_NAME"];
controller.CATNUMBER = [dict objectForKey:#"CAT_ID"];
[self.navigationController pushViewController:controller animated:YES];
// [controller release];
}
Okay I think I have found the cause; but don't know how to fix it.
The tableview in this controller is actually a subview of a viewController. I duplicated these files and created a new view which is a TableViewController. This code, when used in the TableViewController does the job, but it doesn't do it when used in a controller where the tableview is a subview of a ViewController.
I want the table to be a subview because I want to put an image above the table. So, I think the problem here is this line:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
It does not reference the table in the view. Can anyone tell me how to modify this so it would reference the table within the view?
If didSelectRow... is not being called then your view controller is probably not set as the delegate of your table view.
This is set up for you automatically when using a UITableViewController but you have to explicitly do it when using a standard view controller.
An answer to your problem is often that self.navigationController is in fact nil because there is no navigation controller for your view. You perhaps have to get a pointer to the navigation controller of your projet and push your view on it.
I have not yet found any really good examples on how to do this. There is an image that I want to use as the accessory button and when I put it in and click on it doesn't work. So it looks correct but doesn't work...
Here is my code:
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
cell.accessoryView = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"TableView_Green_Disclosure.png"]];
So how do I get my UIImageView to call accessoryButtonTappedForRowWithIndexPath whenever it is tapped?
A thorough reading of accessoryView and accessoryType would reveal that they are mutually exclusive ways to customize a cell.
Setting the accessoryType will cause the table view delegate method to be called when it is tapped.
Setting the accessoryView will ignore the setting of accessoryType and give you something to display. If you want to receive a callback from the custom view you've put in place, it should be a control that is wired up to do so. (Or any view with a gesture recognizer.)
If you use a button, and set its action to accessoryTapped:, you will receive the button as the "sender" argument. You can walk up the view hierarchy until you find a table view cell, and then ask your table view what the indexPath of that cell is. This will then get you an index into your model objects and you be able to act on it appropriately.
Alternate to the button, you can enable interaction on the UIImageView above, and add a gesture recognizer to it.
To make the button actually do something, you'll need to implement - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath from UITableViewDelegate.
When an accessory button is tapped in a row, this method will be called and you'll have the chance to act appropriately using the passed in index path to determine which row's accessory was tapped.
Check the blog post hdr->cmdline for creating custom accessory view for UITableView.
The author used UIButton objects with images for custom accessory view.
To make use of the accessoryView - you would need to set the cell's accessoryType to UITableViewCellAccessoryNone deposit a UIButton (with associated image) into the cell and then wire it up to receive user touches. You might use something like the code below as the IBAction response to the cell's UIButton being touched:
- (IBAction) accessoryButtonPressed:(id) sender
{
NSUInteger pathInts[] = { 0,0 };
pathInts[1] = self.currentselectedrow; // ivar set when tableview row last selected
NSIndexPath* indexPath = [NSIndexPath indexPathWithIndexes:pathInts length:2];
[self tableView:mytableview accessoryButtonTappedForRowWithIndexPath:indexPath];
}
The UIButton would be wired to execute this glue code by way of a line inside your tableview's "cellForRowAtIndexPath:" function
[thecell setButtonTarget:self action:#selector(accessoryButtonPressed:)];
One thing I noticed is that the UIButton seems to want a 'swipe right' versus a simple 'tap' touch in order to trigger the event - but it could be my beta iOS that's the problem. Note that I had added a UIButton* object named 'cell_accessoryButton' to the Custom Cell source.
In the cell's source you'd support the 'setButtonTarget' call with code like this:
- (void) setButtonTarget:(MyViewController*)inTarget action:(SEL) inAction
{
[self.cell_accessoryButton addTarget: inTarget
action: (SEL) inAction
forControlEvents: UIControlEventTouchUpInside];
}
It's so much easier to just use the accessoryType reference and let iOS do the heavy lifting - but, if you want a custom graphic, etc - this is another path that works.
I'm using code to create a detailed view pushed when you press a row of an UITableView, but theres a problem.
The detailed view contain an UITextView and when a detailedView is called (only first time) this make the UITableView row pressed to lose its pressed state. It shouldn't ! It should lose the pressed state only when returning from the detailed view to the list view.
As soon as I remove the UITextView from my code, no problem !
I think it's something like UITextView taking focus?
Is there any way to avoid this ? By subclassing or such?
Hmmm not seeing this in the sandbox I just wrote.
Created a simple navigation-based project.
Added a view controller to the project with XIB; added a UITextField to the XIB.
Made following code changes to the root view controller:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
in cellForRowAtIndexPath:
cell.text = #"Push me";
in didSelectRowAtIndexPath:
SimpleViewController *detailViewController = [[SimpleViewController alloc] initWithNibName:#"SimpleView" bundle:nil];
in viewDidLoad:
self.navigationItem.title = #"Home";
Selecting the "Push me" row highlights the row and pushes the SimpleViewController onto the stack. Selecting the "Home" back button pops the view off the stack, returning to the table view and deselecting/un-highlighting the selected row. This is true whether or not the textfield in the SimpleViewController is the first responder at the time of the back navigation.