UITableViewController Grouped Property Not Working - objective-c

I have two UITableViewControllers. In the first UITableView, once a user selects a cell, a new UITableViewController is pushed. I have set both UITableViews to "Grouped" in IB. However, when the second UITableViewController is pushed, it appears as a "Plain" UITableView. Is there a way to fix this?
Just as a sanity check, I changed the code so that the second UITableViewController is pushed not from the first UITableViewController, and it does appear to be "Grouped". Is there a reason this is happening?
Code From UITableViewController that is pushing second UITableViewController:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell.text isEqualToString:#"Long Term Disability"]) {
LongDisabilityTableView *ldvc = [LongDisabilityTableView alloc];
[self.navigationController pushViewController:ldvc animated:YES];
}
if ([cell.textLabel.text isEqualToString:#"Short Term Disability"]) {
ShortDisabilityTableView *sdvc = [ShortDisabilityTableView alloc];
[self.navigationController pushViewController:sdvc animated:YES];
}
}

If you are pushing to a UITableViewController, you can force the table to be grouped by doing one of the following:
Init
MyTableController *grouped = [[MyTableController alloc] initWithStyle:UITableViewStyleGrouped];
Super
This needs to be added to a UITableViewController.
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:UITableViewStyleGrouped]; /* This is where the magic happens */
if (self) {
self.title = #"My Grouped Table";
}
return self;
}
Double Check
Make sure that you are not placing your UITableView on a UIViewController.
Make sure that you are calling the correct controller in your code (from didSelectRowAtIndexPath:)
Update, added after code
Well there's one reason right there, you aren't using init. See my first example above.
You should also change your code to this:
/* This assumes that your Long Term Disability cell is at index 0
and that your Short Term Disability cell is at index 1.
*/
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
switch ( indexPath.row )
{
case 0: /* #"Long Term Disability" */
LongDisabilityTableView *ldvc = [[LongDisabilityTableView alloc] initWithStyle:UITableViewStyleGrouped];
[self.navigationController pushViewController:ldvc animated:YES];
break;
case 1: /* #"Short Term Disability" */
ShortDisabilityTableView *sdvc = [[ShortDisabilityTableView alloc] initWithStyle:UITableViewStyleGrouped];
[self.navigationController pushViewController:sdvc animated:YES];
break;
}
}

Related

Xcode / ObjectiveC - Convert UITableViewController into TableView embedded in a UIViewController

I am fairly new to this Native App dev - I have built an app which contains a UITableViewController to display messages - all works fine - but for styling reasons I need to change it from a TableViewController to a tableview embedded within a viewcontroller.
I have made a view controller containing a table view and relevant linked custom cells / fields and altered the associated header file to -
#interface NotificationsListTVController : UIViewController
but my table methods no longer fire and I'm not sure how to instantiate them?
(code below)
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return self.GPTNotifications.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
static NSString *CellIdentifierRead = #"CellRead";
UITableViewCell *cell;
notifications *n = [self.GPTNotifications objectAtIndex:indexPath.row];
if (n.read == false) {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
CustomCellRead *cellReadB = (CustomCellRead *)cell;
cellReadB.notifTitle.text = n.notifTitleD;
cellReadB.notifDate.text = n.notifDateD;
cellReadB.notifMsg.text = n.notifMessage;
return cellReadB;
}
else {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifierRead forIndexPath:indexPath];
CustomCell *cellReadB = (CustomCell *)cell;
cellReadB.notifTitle.text = n.notifTitleD;
cellReadB.notifDate.text = n.notifDateD;
cellReadB.notifMsg.text = n.notifMessage;
return cellReadB;
}
}
Are you setting the delegate and datasource of your tableview to your class?
Something like:
self.myTableView.delegate = self;
self.myTableView.dataSource = self;
When you create a UITableViewController this is done for you, but if you add the table yourself you need to set them.
Also:
#interface NotificationsListTVController : UIViewController <UITableViewDelegate, UITableViewDataSource>
I do it this way in Interface Builder:
Make your TableViewController
Make your ViewController and add a ContainerView to it
Delete the segued embedded ViewController that comes with it
Select the ContainerView and draw a connection from viewDidLoad to your TableViewController
you'll get only once option: embed
Done. Your TableViewController will now get displayed within your ViewController.
Pass whatever Data you need forward from the ViewController to the TableViewController with the embedded Segue.
Make the following changes in NotificationsListTVController.h:
#interface NotificationsListTVController : UIViewController<UITableViewDataSource,UITableViewDelegate>
Also in NotificationsListTVController.m, dont forget to provide these two statements as well.
tableView.delegate=self ;
tableView.dataSource=self;
These are required to set the delegate methods.These two statements need to be provided after initializing your tableView. Like for instance :
tblView = [[UITableView alloc] initWithFrame:CGRectMake(100,200,320,420) style: UITableViewStyleGrouped];
tblView.delegate = self;
tblView.dataSource = self;
[self.view addSubview:tblView];
These methods you are referring to are the delegate methods which cannot be fired directly unlike other ordinary methods.
Hope it Helps!!!

How to implement didSelectRowAtIndexPath method with sectioned UITableView

I have been implementing a app with sectioned UITableView. In the tableview, I used a array, called sections, to store different classes array and show them in different sections. On the other hand, I also used a array, called headers, to store section headers' name. For example, in the "weekday" section, there are seven words, Sunday to Saturday, in the tableViewCell under this section. In the MainViewController:
-(void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *weekday=[[NSMutableArray alloc]init];
NSMutableArray *traffic=[[NSMutableArray alloc]init];
for (NSArray *sec_ary in listData) {
NSString *class=[[sec_ary valueForKey:#"vocabulary_list"]valueForKey:#"Class"];
if ([class isEqualToString:#"WEEKDAY"]) {
[weekday addObject:[[sec_ary valueForKey:#"vocabulary_list"]valueForKey:#"Vocabulary"]];
}else if ([class isEqualToString:#"TRAFFIC TOOLS"]){
[traffic addObject:[[sec_ary valueForKey:#"vocabulary_list"]valueForKey:#"Vocabulary"]];
}
sections=[[NSArray alloc ]initWithObjects:weekday,traffic,nil];
headers=[[NSArray alloc]initWithObjects:#"WEEKDAY",#"TRAFFIC TOOLS",nil];
}
In this App, I also implemented the navigation controller, which can bring user to view detail information in the didSelectRowAtIndexPath method. The codes are following
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
ContentViewController *content= [[ContentViewController alloc] initwithIndexPath:indexPath];
[delegate.navController1 pushViewController:content animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *TableIdentifier = #"tableidentifier"; /
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:TableIdentifier] autorelease];
}
cell.textLabel.text = (NSString*)[[self.sections objectAtIndex:indexPath.section]objectAtIndex:indexPath.row];
cell.textLabel.font = [UIFont boldSystemFontOfSize:15];
return cell;
}
In the ContentViewController:
-(void)viewDidLoad{
[super viewDidLoad];
AppDelegate *delegate=(AppDelegate*)[[UIApplication sharedApplication]delegate];
NSDictionary *voc_list=[delegate.vcblr objectAtIndex:index.row];
//extracting the voc_list dictionary to show infomation.....
}
I am wondering why each section will load the information from beginning in the voc_list. That is to say, the tableViewCell do not respond to the right detail content. Could anyone provide me with ideas to resolve it?
I am wondering why each section will load the information from beginning in the voc_list.
Because the code of your viewDidLoad method ignores index.section, paying attention to index.row alone. You need to decide on the index that you pass to delegate.vcblr based on both the section and the row; the exact calculation depends on the structure of your data, i.e. how many rows you have in each section.
Note : Using AppDelegate to share data among view controllers is not a good idea. Consider separating out your data in a separate model class, and make that class a singleton.

Push a string and display in a UITextField

I am doing a small app and I am using a UISplitVIewController and I am trying to push the UITable cell text to the detail view and display it in a UITextField. I have managed to push the string nicely when i test it with a NSLog but when i apply to the UITextField it does not display not sure why here my method: (I am doing this using a storyboard)
-(void)pushModuleName:(NSString*)moduleName
{
self.Lv4ModuleTitleTextField.text = moduleName;
NSLog(#"name pushed%#",moduleName);
}
Not sure why this doesn't work.
[UPDATE]
UITableViewController.m (where the method is called)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *selectedModule = [NSString stringWithFormat:#"%#",[_numberOfRows objectAtIndex:indexPath.row]];
Lv4GradeViewController *lv4 = [[Lv4GradeViewController alloc] initWithNibName:nil bundle:nil];
[lv4 pushModuleName:selectedModule];
}
You are creating a new instance of Lv4GradeViewController with the following code but no XIB file which will contain the text field:
Lv4GradeViewController *lv4 = [[Lv4GradeViewController alloc] initWithNibName:nil bundle:nil];
I would suggest you instantiate Lv4GradeViewController with the storyboard instantiateViewControllerWithIdentifier method:
Lv4GradeViewController *lv4 = [self.storyboard instantiateViewControllerWithIdentifier:#"IdentifierName"];
And remember to set the storyboard ID of the Lv4GradeViewController the same as IdentifierName in the storyboard.
The problem is that you're not getting a reference to the Lv4GradeViewController that you have on screen, you're creating a new one with alloc init. A split view controller, has a viewControllers array, with the controller at index 0 being the master controller, and the one at index 1 being the detail controller. So, the didSelectRowAtIndexPath method should look like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *selectedModule = [NSString stringWithFormat:#"%#",[_numberOfRows objectAtIndex:indexPath.row]];
Lv4GradeViewController *lv4 = self.splitViewController.viewControllers[1];
[lv4 pushModuleName:selectedModule];
}

Basic iOS issues

I am trying to to complete the 'Your Second iOS App' tutorial from the apple developer program. It is a basic tableView app. My problem is that the app is building successfully and without warnings, however I cannot get the detail view to segue from the master view. I have copied and pasted both the segue identifier and the code that apple has provided. The segue is using push and I have deleted it and tried again several times. I am testing the app in the simulator.
How can I tell if a segue is working?
Every time I copy/paste my code from Xcode into the stack overflow question text area, I get warnings at the bottom saying that code must be indented by 4 spaces??? Does this mean I have to go line-by-line indenting code?? I did the control + k and pasted in the highlighted area, however I still got the warning??
When running the simulator and looking at it, I'm trying to use a disclosure indicator by clicking on it, do I have to push something special like control = click or command = click, etc. ?
Here is the code for BirdsMasterViewController.m file:
//
// BirdsMasterViewController.m
// BirdWatching
//
// Created by David Hall on 11/13/12.
// Copyright (c) 2012 David Hall. All rights reserved.
//
#import "BirdsMasterViewController.h"
#import "BirdsDetailViewController.h"
#import "BirdSightingDataController.h"
#import "BirdSighting.h"
/*
#interface BirdsMasterViewController () {
NSMutableArray *_objects;
}
#end
*/
#implementation BirdsMasterViewController
- (void)awakeFromNib
{
[super awakeFromNib];
self.dataController = [[BirdSightingDataController alloc] init];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
/*
self.navigationItem.leftBarButtonItem = self.editButtonItem;
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(insertNewObject:)];
self.navigationItem.rightBarButtonItem = addButton;
*/
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
/*- (void)insertNewObject:(id)sender
{
if (!_objects) {
_objects = [[NSMutableArray alloc] init];
}
[_objects insertObject:[NSDate date] atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
*/
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.dataController countOfList];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"BirdSightingCell";
static NSDateFormatter *formatter = nil;
if (formatter == nil)
{
formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterMediumStyle];
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
BirdSighting *sightingAtIndex = [self.dataController objectInListAtIndex:indexPath.row];
[[cell textLabel] setText:sightingAtIndex.name];
[[cell detailTextLabel] setText:[formatter stringFromDate:(NSDate *)sightingAtIndex.date]];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return NO;
}
/*- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[_objects removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ShowSightingDetails"]) {
BirdsDetailViewController *detailViewController = [segue destinationViewController];
detailViewController.sighting = [self.dataController objectInListAtIndex:[self.tableView indexPathForSelectedRow].row];
}
}
#end
And here is the code for the BirdsDetailViewController.m
//
// BirdSightingDataController.m
// BirdWatching
//
// Created by David Hall on 11/25/12.
// Copyright (c) 2012 David Hall. All rights reserved.
//
#import "BirdSightingDataController.h"
#import "BirdSighting.h"
#interface BirdSightingDataController ()
- (void)initializeDefaultDataList;
#end
#implementation BirdSightingDataController
- (void)initializeDefaultDataList
{
NSMutableArray *sightingList = [[NSMutableArray alloc] init];
self.masterBirdSightingList = sightingList;
BirdSighting *sighting;
NSDate *today = [NSDate date];
sighting = [[BirdSighting alloc] initWithName:#"Pigeon" location:#"Everywhere" date:today];
[self addBirdSightingWithSighting:sighting];
}
- (void)setMasterBirdSightingList:(NSMutableArray *)newList
{
if (_masterBirdSightingList != newList)
{
_masterBirdSightingList = [newList mutableCopy];
}
}
- (id)init
{
if (self = [super init])
{
[self initializeDefaultDataList];
return self;
}
return nil;
}
- (NSUInteger)countOfList
{
return [self.masterBirdSightingList count];
}
- (BirdSighting *)objectInListAtIndex:(NSUInteger)theIndex
{
return [self.masterBirdSightingList objectAtIndex:theIndex];
}
- (void)addBirdSightingWithSighting:(BirdSighting *)sighting
{
[self.masterBirdSightingList addObject:sighting];
}
#end
David Hall
It's working when it works. But without knowing more about what you are doing it's hard to give you an answer.
Highlight the code in the textbox and then click on this button.
It will indent the code correctly for you.
I can't make sense of this question.
Edited to add
(After seeing a copy of the project that the OP mailed me)
Your segue wasn't wired up properly.
The segue is supposed to go from the cell to the next view controller, because the point is to transition on a cell click. Your segue is wired up from the controller to the detail view controller. In your project - right click on your view controller and you'll see the segue is manually connected. But right clicking on the cell doesn't show a segue connection.
Delete the current segue and recreate it, this time by control-dragging from the cell to the next view controller. You can then double check the connection by right clicking on the cell and making sure that the segue is connected.
It should look like:
If the segue is supposed to transition from your table to a detail view, and if you can't get to the detail view from the table, then your segue isn't working.
You can use the code sample button at the top of the SO editor, or you can select the code in your text editor and indent it before you copy it. For example, in Xcode it's easy to select the code, hit Command-], and copy. Then just paste into the SO editor.
Please edit your question so that it makes sense. However, I think you might be asking something along the lines of how to push a view controller from your table. If you're using a segue, and if you've created the segue in your storyboard and it's connected to both the source and destination view controllers, then you can send -performSegueWithIdentifier:sender: to your table's view controller. That is, your table view controller's -tableView:didSelectRowAtIndexPath: method should call -performSegueWithIdentifier:sender: and specify the identifier for the segue leading from the table view controller to the detail view controller. It doesn't matter whether you're using the simulator or running your app on a real device.
See the other answers from Caleb and Abizem regarding 1. and 2. If I understood your question No 3 correctly, then the answer is no. You do not have to press something in particular in the simulator when you want to select a table row or the detail desclosure indicator. Just click on those items that you would tap on your device too. If it does not segue then the chances are that its not the simulator causing the problem :)

iPad: SplitViewController with navigation

I'm following Apple sample code "MultipleDetailViews" but what I want to do is that:
at start, shows the RootViewController (table view) display the default detailViewController (1st detailView)
when user selected a table cell, push into the stack, display the SubCategoriesVC (table view) in the master of the splitView but don't update the detailView.
in SubCategoriesVC, selecting a table cell.. update the detailViewController (2nd detailView)
So, in RootViewController.m, I push another navigation
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
SubCatVC *browseSubCatView = [[SubCatVC alloc] initWithNibName:#"SubCatVC" bundle:nil];
[self.navigationController pushViewController:browseSubCatView animated:YES];
[browseSubCatView release];
}
Then, in SubCatVC.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
SecondDetailViewController *newDetailViewController = [[SecondDetailViewController alloc] initWithNibName:#"SecondDetailViewController" bundle:nil];
detailViewController = newDetailViewController;
// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
self.splitViewController.viewControllers = viewControllers;
[viewControllers release];
// Dismiss the popover if it's present.
if (self.popoverController != nil) {
[self.popoverController dismissPopoverAnimated:YES];
}
// Configure the new view controller's popover button (after the view has been displayed and its toolbar/navigation bar has been created).
if (self.rootPopoverButtonItem != nil) {
[detailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
}
[detailViewController release];
[[NSNotificationCenter defaultCenter] postNotificationName:#"updateProduct" object:nil];
}
but it didn't update my detailView.. so I don't know what's wrong?
Src here: http://pastebin.com/iy6SqLqt
Hope someone can advise me. Thanks
I Have not looked at your source, but but a common problem with Split views are delegates.
When you Push a new rootController ont the nav stack, you need to make sure it has the pointer to the detailViewController that you want it to talk to. You can check htis my logging the delegate before you try to update it:
In your SubCatVC (or any root for that matter):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//do stuff, init alloc vc's....
NSLog(#"DELEGATE: %#",self.delegate);
//push/delegate etc..
}
If you find its nil, copy the original roots delegate, or when your putting your new detail in, notify/set the root you want to comunicate with it.
If you need any more detail, just ask.