
Tab Bar Controller
#1
Posted 23 March 2011 - 04:44 PM
Apologies in advance if this is covered somewhere on the forum...
Wondering if there's a way to persist a consistent tab bar controller while navigating thru UITableViewControllers? One of my apps has that typical steady state tab bar across the bottom, and while I'm retrofitting in STV (actually re-purposing the app to be STV), I noticed that my tab bars swipe away as I navigate into lower details....
Thanks in advance!
Adam
#2
Posted 23 March 2011 - 04:59 PM
Hope that helps
#3
Posted 23 March 2011 - 05:12 PM
Adam: If I correctly understand what you mean, all you need is set your SCArrayOfObjectsSection/Model "detailViewHidesBottomBar" property to FALSE.
Hope this helps!
#4
Posted 23 March 2011 - 05:19 PM
Thanks guys!
#5
Posted 23 March 2011 - 10:52 PM
Hi guys,
Adam: If I correctly understand what you mean, all you need is set your SCArrayOfObjectsSection/Model "detailViewHidesBottomBar" property to FALSE.
Hope this helps!
After checking into this, my use of SCObjectSection presented another little challenge.
Another question if you don't mind..
I'm prepping my object section with:
SCObjectSection *objectSection = [SCObjectSection sectionWithHeaderTitle:nil withBoundObject:eventObject
withClassDefinition:profDef];
And detailViewHidesBottomBar fits with SCArrayOfObjectsSection/Model
Any quick / obvious thoughts?
Thanks!
#6
Posted 24 March 2011 - 11:00 PM
The purpose of using SCObjectSection, as a prep to an individual section at the top that ultimately presents itself like a preferences app... Nickname editable cell at the top..

Code below which leads up to SCObjectSection:
tableModel = [[SCTableViewModel alloc] initWithTableView:self.tableView withViewController:self];
// Get the Profile object (if exists, otherwise create a new one)
NSManagedObject *profObject = nil;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:profDef.entity];
NSArray *objectsArray = [profDef.managedObjectContext executeFetchRequest:fetchRequest error:NULL];
if(objectsArray.count)
profObject = [objectsArray objectAtIndex:0];
[fetchRequest release];
if(!profObject)
{
// create a new object
profObject = [NSEntityDescription insertNewObjectForEntityForName:[profDef.entity name]
inManagedObjectContext:profDef.managedObjectContext];
}
SCObjectSection *objectSection = [SCObjectSection sectionWithHeaderTitle:nil withBoundObject:profObject
withClassDefinition:profDef];
[tableModel addSection:objectSection];
#7
Posted 25 March 2011 - 02:28 AM
Thanks for the update. detailViewHidesBottomBar is also a property of SCTableViewCell.
... for(int i=0; i<objectSection.cellsCount; i++) [objectSection cellAtIndex:i].detailViewHidesBottomBar = FALSE; ...
Hope this helps

#8
Posted 25 March 2011 - 10:57 AM
I'm thinking I'll need to do an SCTableViewCell override given as I drill down and add related objects during the 1 ViewDidLoad, the tab bar ends up going away.
I'm Testing this morning, but if you think this is a un-recommended idea let me know.
Reality is this, I'm showing my "Fresh Boarder" colors here on how best to do things with STV.
This being said, I truly appreciate your, and all the senior boarder feedback.
#9
Posted 25 March 2011 - 04:28 PM
Please hold back from doing anything. We're releasing an STV update in the next couple of days, and I'll make sure that STV will detect if you assign detailViewHidesBottomBar to a cell, and will automatically have all the detail cells inherit that. Hope this helps

#10
Posted 25 March 2011 - 04:36 PM
Thanks for the heads up. Much appreciated!
Best,
Adam
#11
Posted 28 March 2011 - 06:01 PM
I'm thinking I'll need to do an SCTableViewCell override given as I drill down and add related objects during the 1 ViewDidLoad, the tab bar ends up going away.
Please accept my apologies here, what I actually overlooked is that you're referring to an SCTableViewCell and not an SCTableViewSection. In an SCTableViewSection, when you set detailViewHidesBottomBar, STV should propagate that to all its cells. In the case of SCTableViewCell, it does not need to propagate anything, as the detail cells would already have their tab bar hidden.
Would you please rephrase the text I quoted above so that I would be able to get a better understanding of your problem? I apologize again for the confusion.
#12
Posted 28 March 2011 - 10:08 PM
Maybe I need to start over with the explanation. And pictures will help with visually.
I'd like my tab bar to persist at "as many levels" while drilling down, adding entities of
the table view - common HIG for the most part...
So it starts here where:

Then drilling down to add or edit a Favorite:

Then my tab bar goes away at this next level down:

And here's the implementation code (some old code not removed yet for date formatting):
#import "ProfileView.h" #import "HBAppDelegate.h" @implementation ProfileView #pragma mark - #pragma mark View lifecycle - (void)viewDidLoad { [super viewDidLoad]; NSManagedObjectContext *managedObjectContext = [(HBAppDelegate *)[UIApplication sharedApplication].delegate managedObjectContext]; // Create a class definition for Favorites SCClassDefinition *favorites = [SCClassDefinition definitionWithEntityName:@"Favorites" withManagedObjectContext:managedObjectContext withPropertyNames:[NSArray arrayWithObjects:@"name", @"category",nil]]; SCPropertyDefinition *favDef = [favorites propertyDefinitionWithName:@"category"]; favDef.type = SCPropertyTypeSelection; favDef.attributes = [SCSelectionAttributes attributesWithItems:[NSArray arrayWithObjects:@"This", @"That", @"The other thing", nil] allowMultipleSelection:NO allowNoSelection:NO]; // Create a class definition for Dates SCClassDefinition *dates = [SCClassDefinition definitionWithEntityName:@"Dates" withManagedObjectContext:managedObjectContext withPropertyNames:[NSArray arrayWithObjects:@"name", @"date",nil]]; dates.uiElementDelegate = self; SCPropertyDefinition *datedate = [dates propertyDefinitionWithName:@"date"]; datedate.type = SCPropertyTypeDate; datedate.required = FALSE; datedate.title = @"Name"; SCPropertyDefinition *dateName = [dates propertyDefinitionWithName:@"name"]; dateName.title = @"Name"; dateName.type = SCPropertyTypeTextField; SCPropertyDefinition *apptDatePropertyDef = [dates propertyDefinitionWithName:@"date"]; apptDatePropertyDef.type = SCPropertyTypeDate; apptDatePropertyDef.required = TRUE; apptDatePropertyDef.title = @"Date"; NSDateFormatter *apptDateFormatter = [[NSDateFormatter alloc] init]; [apptDateFormatter setDateFormat: @"MM-dd-yyyy" ]; apptDatePropertyDef.attributes = [SCDateAttributes attributesWithDateFormatter:apptDateFormatter]; [apptDateFormatter release]; // Create a class definition for Sizes SCClassDefinition *sizes = [SCClassDefinition definitionWithEntityName:@"Sizes" withManagedObjectContext:managedObjectContext withPropertyNames:[NSArray arrayWithObjects:@"type", @"value",nil]]; // Date field def SCPropertyDefinition *sizeDef = [sizes propertyDefinitionWithName:@"type"]; sizeDef.title = @"Type"; sizeDef.type = SCPropertyTypeTextField; // Create a class definition for Profile SCClassDefinition *profDef = [SCClassDefinition definitionWithEntityName:@"Profile" withManagedObjectContext:managedObjectContext withPropertyNames: [NSArray arrayWithObjects:@"nickname", @"favorites", @"dates", @"sizes", nil]]; // Profile field Def SCPropertyDefinition *eventPDef = [profDef propertyDefinitionWithName:@"nickname"]; eventPDef.title = @"Nickname"; eventPDef.type = SCPropertyTypeTextField; // relationships // ** favorites relationship SCPropertyDefinition *favPropDef = [profDef propertyDefinitionWithName:@"favorites"]; favPropDef.attributes = [SCArrayOfObjectsAttributes attributesWithObjectClassDefinition:favorites allowAddingItems:TRUE allowDeletingItems:TRUE allowMovingItems:FALSE]; // ** dates relationship SCPropertyDefinition *datePropDef = [profDef propertyDefinitionWithName:@"dates"]; datePropDef.attributes = [SCArrayOfObjectsAttributes attributesWithObjectClassDefinition:dates allowAddingItems:TRUE allowDeletingItems:TRUE allowMovingItems:FALSE]; // ** size relationship SCPropertyDefinition *sizePropDef = [profDef propertyDefinitionWithName:@"sizes"]; sizePropDef.attributes = [SCArrayOfObjectsAttributes attributesWithObjectClassDefinition:sizes allowAddingItems:TRUE allowDeletingItems:TRUE allowMovingItems:FALSE]; tableModel = [[SCTableViewModel alloc] initWithTableView:self.tableView withViewController:self]; // This is to place an Editable cell at the top for Nickname // Get the Profile object (if exists, otherwise create a new one) NSManagedObject *nickNameObject = nil; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; [fetchRequest setEntity:profDef.entity]; NSArray *objectsArray = [profDef.managedObjectContext executeFetchRequest:fetchRequest error:NULL]; if(objectsArray.count) nickNameObject = [objectsArray objectAtIndex:0]; [fetchRequest release]; if(!nickNameObject) { // create a new object nickNameObject = [NSEntityDescription insertNewObjectForEntityForName:[profDef.entity name] inManagedObjectContext:profDef.managedObjectContext]; } SCObjectSection *objectSection = [SCObjectSection sectionWithHeaderTitle:nil withBoundObject:nickNameObject withClassDefinition:profDef]; // for loop put in place to keep tab bar persistent // this works to a point... how about once someone starts adding values to a lower hierachy? // perhaps I need more than ViewDidLoad, or an override // Thanks for the update. detailViewHidesBottomBar is also a property of SCTableViewCell - Tarek // Hold on working this thru per Tarek, he's got a fix - 3/25 for(int i=0; i<objectSection.cellCount; i++) { [objectSection cellAtIndex:i].detailViewHidesBottomBar = FALSE; } // Probably need an SCTableViewCell override. [tableModel addSection:objectSection]; } - (void)dealloc { [tableModel release]; [super dealloc]; } - (void)willConfigureCell:(SCTableViewCell *)cell { if([cell isKindOfClass:[SCDateCell class]]) { SCDateCell *dateCell = (SCDateCell *)cell; dateCell.datePicker.datePickerMode = UIDatePickerModeDate; } } @end
Hope this explains it better....
Thanks,
Adam
#13
Posted 28 March 2011 - 10:48 PM
Thanks a lot for the detailed explanation. When you need to set a property of a cell that's deep down into the detail view hierarchy, you basically have two options:
* Option 1
Set a delegate directly for this cell. This can be easily done by setting the uiElementDelegate property of the class definition that will generate the cell. Please note that a cell's delegate must conform to the SCTableViewCellDelegate protocol (what this essentially means for you is that you need to go to your view controller's header file and add SCTableViewCellDelegate to the list of protocols). Here is how you should set uiElementDelegate in your case:
... favorites.uiElementDelegate = self; ...
Next, you'll just implement the SCTableViewCellDelegate method called willConfigureCell, which is the best place to configure the detailViewHidesBottomBar property you want to set:
- (void)willConfigureCell:(SCTableViewCell *)cell { cell.detailViewHidesBottomBar = TRUE; }
* Option 2
While option 2 may seem a little bit more complicated, it's usually very powerful when you want to perform the same operation on all detail views.
The game plan here is to assign a tag to each of the detail models that is equivalent to their level in the heirarchy. We'll do this by implementing the SCTableViewModelDelegate method called detailModelCreatedForRowAtIndexPath, which gets called every time a detail model is created. We'll also need to assign a delegate to each detail model, otherwise the delegate methods we'll implement are not going to get called for it. Finally, we should implement SCTableViewModelDelegate's willConfigureCell method, and depending on the model's tag, we'll decide whether to show or hide the tab bar. This is all implemented in a way that's much easier than it sounds:
- (void)tableViewModel:(SCTableViewModel *)tableViewModel detailModelCreatedForRowAtIndexPath:(NSIndexPath *)indexPath detailTableViewModel:(SCTableViewModel *)detailTableViewModel { // Set a tag equivalent to the detail model's level in the hierarchy detailTableViewModel.tag = tableViewModel.tag + 1; // Set the detail model's delegate detailTableViewModel.delegate = self; } - (void)tableViewModel:(SCTableViewModel *)tableViewModel willConfigureCell:(SCTableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { // 0 is the main model, 1 is the Favorites level in your hierarchy if(tableViewModel.tag == 1) cell.detailViewHidesBottomBar = TRUE; }
The power behind option 2 is that, for example, I can configure all date cells in your entire application (all detail views) just by implementing the willConfigureCell method.
Hope this helps!
#14
Posted 28 March 2011 - 11:02 PM
Both make sense to me, option 2 is most appealing.
I hope this thread will help others with similar questions.
Thanks for the great level of detail, and two viable options!
I'll check it out in practice now

Best,
Adam
#15
Posted 29 March 2011 - 03:12 AM
I actually tried both options and I'm not seeing the expected behavior for some reason.
There's something obviously missing in my code. I've set my delegates, and the only thing possibly questionable to me is I've left in the for loop we touched on earlier in the thread.
Can I send you the project to have a quick look?
Thanks,
Adam
#16
Posted 30 March 2011 - 03:03 PM
Thanks for sending in your project. I see your point, setting detailViewHidesBottomBar to FALSE only affects one level of detail views. We'll fix that in an update coming in a couple of days (2.0.3). Thanks again!
#17
Posted 30 March 2011 - 03:16 PM
Thanks for the time on investigating this.
As always, I appreciate your efforts!
Best,
Adam
- Tarek and Thomas Hempel like this
#18
Posted 06 April 2011 - 09:20 AM
- (void)tableViewModel:(SCTableViewModel *)tableViewModel detailModelCreatedForRowAtIndexPath:(NSIndexPath *)indexPath detailTableViewModel:(SCTableViewModel *)detailTableViewModel
{
// Set a tag equivalent to the detail model's level in the hierarchy
detailTableViewModel.tag = tableViewModel.tag + 1;
// Set the detail model's delegate
detailTableViewModel.delegate = self;
}
- (void)tableViewModel:(SCTableViewModel *) tableViewModel willConfigureCell:(SCTableViewCell *) cell forRowAtIndexPath:(NSIndexPath *) indexPath
{
cell.height = 45;
cell.editable = FALSE;
cell.movable = FALSE;
if([cell isKindOfClass:[SCTextViewCell class]])
{
SCTextViewCell *scTextViewCell = (SCTextViewCell *)cell;
scTextViewCell.maximumHeight = 1000;
}
// 0 is the main model, 1 is the Table View Detail level in your hierarchy
if(tableViewModel.tag == 1){
cell.detailViewHidesBottomBar = FALSE;
cell.detailViewTitle=@"My Detials View Title";
}
}
#19
Posted 06 April 2011 - 10:03 AM
Hi Adam,
Thanks for sending in your project. I see your point, setting detailViewHidesBottomBar to FALSE only affects one level of detail views. We'll fix that in an update coming in a couple of days (2.0.3). Thanks again!
Tarek,
Thanks so much for the fix! And the release of 2.0.3:
http://www.sensiblecocoa.com/forum/announcements/2392-minor-update-stv-203.html
I tested it and it works beautifully!
Cheers!
Adam
#20
Posted 06 April 2011 - 04:43 PM
Your tab bar is hidden since you're setting it to FALSE on the second level. Try changing "if(tableViewModel.tag == 1)" to "if(tableViewModel.tag == 0)". Also, if you're creating an SCArrayOfObjectsSection in your model, then you should set its detailViewHidesBottomBar property to FALSE.
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users