This is more of cosmetic issue.
I have added a searchbar via the storyboard and I want to hide the following with the storyboard.
I was able to do this previously using codes that was before storyboard came into the picture.
Can anyone point me in the right direction if this is achievable using storyboard?
Cheers,
Lance
On your storyboard, select your search bar and open the object inspector on the right. In their you will find a property called "hidden". check the box and the object will be hidden when the storyboard is initialized.
If you ctrl-drag from the search bar and create a property in your view controller, you can then control the hidden flag in code. So you can make it re-appear when you need it, something like:
self.searchbar.hidden = NO;
Edited 1/2/2013 -
Here is a different approach.
Checklist:
a)Add a search bar to your tableview's header view in your storyboard. Link that search bar to a property called searchBar. When you link it, xcode will give it a weak reference, change the weak reference to strong. ex:
#property (strong, nonatomic) IBOutlet UISearchBar *searchBar;
b)Add a BOOL property called showSearch to control showing and hiding the search bar.
#property (nonatomic) BOOL showSearch;
c)Add the following methods to your controller code
- (void)setShowSearch:(BOOL)showSearch {
_showSearch = showSearch;
if (! _showSearch) {
self.tableView.tableHeaderView = nil;
}
[self.tableView reloadData];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection: (NSInteger)section
{
if (self.showSearch && self.tableView.tableHeaderView == nil) {
return self.searchBar.frame.size.height;
}
return 0;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if (self.showSearch && self.tableView.tableHeaderView == nil) {
return self.searchBar;
}
return nil;
}
by default this will start with the search bar showing. If you want to start with it hidden, just add the following to your viewDidLoad method:
self.showSearch = NO;
best of luck and happy new year!
Related
I created master details template project in xcode 4.6 and I added custom cell with 2 textfields. I also created new class which is subclass of UITableViewCell and inside this class I created outlets for text fields. When user types something NSMutableArray is updated and this works fine. Now I am wondering how to pass this array back to MasterViewController (UITableViewController) so that I can use this data to show calculations.
I tried using tutorials for delegates between UIViewControllers but I keep getting errors. Any help is appreciated.
You shouldn't keep data inside the UITableViewCell, as it breaks the MVC.
You need to get a reference of the UITextField on your cell. This is how I do in a login form:
I have a custom cell subclass called TextFieldCell, it has an outlet called textField, I want that my UITableViewController have references to these UITextFields.
First I open my storyboard, set the cell class to TextFieldCell and than connect the UITextField to cell textField outlet. Than I add this to the tableView:cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
(…)
if (indexPath.row == 0) {
// Sets the textField of the first cell as the loginTextField.
self.loginTextField = tCell.textField;
} else {
// Sets the textField of the second cell as the passwordTextField.
self.passwordTextField = tCell.textField;
}
tCell.textField.delegate = self;
(…)
}
Now I can access the value of my loginTextField and my passwordTextField. I do that on the tableView:cellForRowAtIndexPath: because that's when I'm creating the cell to add to the table view.
In your case you need to create Protocol:
I just Give Basic Idea for how to Create Protocol
Also Read This Question
#DetailViewController.h
#import <UIKit/UIKit.h>
#protocol MasterDelegate <NSObject>
-(void) getButtonTitile:(NSString *)btnTitle;
#end
#interface DetailViewController : MasterViewController
#property (nonatomic, assign) id<MasterDelegate> customDelegate;
#DetailViewController.m
if([self.customDelegate respondsToSelector:#selector(getButtonTitile:)])
{
[self.customDelegate getButtonTitile:button.currentTitle];
}
#MasterViewController.m
create obj of DetailViewController
DetailViewController *obj = [[DetailViewController alloc] init];
obj.customDelegate = self;
[self.navigationController pushViewController:reportTypeVC animated:YES];
and add delegate method in MasterViewController.m for get button title.
#pragma mark -
#pragma mark - Custom Delegate Method
-(void) getButtonTitile:(NSString *)btnTitle;
{
NSLog(#"%#", btnTitle);
}
I'm doing an app that has a UITableViewController populated with a list of products. Each row segues to a UIViewController that presents the details of the product in the row. Now since tapping on each row and going back to see the details of the next product might be too tedious for the user, we decide to add this feature: when a user swipes on the UIViewController of a product, then the UIViewController with the details for the next product is pushed.
But, as of now, I'm not sure of the best way to implement this. I'm tempted to pass the array of products to the UIViewController so that the swiping is achieved but this will be a violation of the MVC framework,right? Views cannot own the data they're presenting. The product details UIViewController should only know about the specific product that's passed to it, not the rest, right?
I think this can be accomplished using delegation but I'm not sure how. Can anybody help me? Thanks!
EDIT:
Rob Mayoff's code was really helpful so I decided to implement it. But for the meantime, instead of implementing a swipe, I'll just use a simple round rect button to call the functions.
- (IBAction)showNextProduct:(id)sender {
[self.productsTVC goToProductAtIndex:self.productIndex + 1];
}
- (IBAction)showPriorProduct:(id)sender {
[self.productsTVC goToProductAtIndex:self.productIndex - 1];
}
But every time I click any of the buttons, my app crashes with the message: Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted. Unbalanced calls to begin/end appearance transitions for <ProductDetailsViewController: 0x6e510c0>.
Let's say you have a CatalogViewController (which is a subclass of UITableViewController) and a ProductViewController (which is a subclass of UIViewController).
The simplest way to implement “swipe to next product” is to give the ProductViewController a reference to the CatalogViewController. It should be weak (if using ARC) or assign (if not using ARC). You will also want a property that holds the index of the product in the catalog:
#interface ProductViewController
#property (nonatomic, weak) CatalogViewController *catalogViewController;
#property (nonatomic) NSInteger productIndex;
#end
Then in the action method for a swipe, you send a message to the CatalogViewController asking it to go to the next (or prior) product in the catalog:
#implementation ProductViewController
- (IBAction)showNextProduct:(id)sender {
[self.catalogViewController goToProductAtIndex:self.productIndex + 1];
}
- (IBAction)showPriorProduct:(id)sender {
[self.catalogViewController goToProductAtIndex:self.productIndex - 1];
}
In CatalogViewController, whenever you create a ProductViewController, you need to set those properties:
#implementation CatalogViewController
- (ProductViewController *)productViewControllerForProductAtIndex:(NSInteger)index {
if (index < 0 || index >= self.products.count)
return nil;
ProductViewController *vc = [[ProductViewController alloc] initWithProduct:[self.products objectAtIndex:index]];
vc.catalogViewController = self;
vc.productIndex = index;
return vc;
}
and you implement the goToProductAtIndex: method like this:
- (void)goToProductAtIndex:(NSInteger)index {
ProductViewController *vc = [self productViewControllerForProductAtIndex:index];
if (!vc)
return;
NSMutableArray *vcs = [[self.navigationController viewControllers] mutableCopy];
while (vcs.lastObject != self)
[vcs removeLastObject];
[vcs addObject:vc];
[self.navigationController setViewControllers:vcs animated:YES];
}
You can use the same method to handle a table row selection:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self goToProductAtIndex:indexPath.row];
}
If you want to get more software-engineery, you can create a protocol around the goToProductAtIndex: method and use that to avoid making ProductViewController know about the CatalogViewController class.
I have a UITableView inside a UIViewController like so:
.h
#interface OutageListViewController : UIViewController<UITableViewDelegate,UITableViewDataSource> {
IBOutlet UITableView *outageTable;
.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Selected");
}
I have customized table cell:
//EDIT
I have fire UILabel side by side on my customized view, as well as a background spreading the entire area. But after resizing/removing the background image and label I putted on the customized cell, "didSelectRowAtIndexPath" is still not being called.
//END EDIT
#interface AbstractSummaryListViewCell : UITableViewCell {...}
and
#interface FiveColumnSummaryCell : AbstractSummaryListViewCell {...}
This UIView is inside another UIView:
#interface CustomTabBarController : UIViewController {
OutageListViewController *outageListViewController;
And my AppDelegate add this to the window:
[window addSubview:[customTabBarController view]];
Now I'm trying to determine which cell get clicked and didSelectRowAtIndexPath doesn't get called, I have dataSource and delegate connect from the UITableView to File's Owner, in fact the data populates correctly as my "cellForRowAtIndexPath" specifies, any ideas how can I fix this?
Thanks!
I solved it: forgot to check User Interaction Enabled in my customized cell xib. What a fool!
Are the following properties of UITableView all YES?
allowsSelection
allowsSelectionDuringEditing
Edit:
I think Paul is right. The delegate property has some problem. You can check the delegate property of tableView inside -(void)viewDidLoad. As you said, they should be connected to FileOwner in xib. So the following codes won't obtain nil.
- (void)viewDidLoad {
[super viewDidLoad];
// They should not be nil.
NSLog(#"delegate:%# dataSource:%#", self.tableView.delegate, self.tableView.dataSource);
}
It's possible that the view controller has not been connected to the delegate property of the outageTable anywhere.
You can make a quick test... Remove the "big" label and see if the didSelectRowAtIndexPath is called.
My goal is to have a UISearchBar fixed in a view right above a UITableView. When I set this up in IB and then build, the table view expands to fill the whole window and the search bar is not visible. If I make the UISearchBar a subview of the UITableView, the search bar displays as expected, but this is not what I want. What I'm after is that after the user selects a row, I want to display a detail view with the search bar still remaining on the screen. So I figured it needed to be a separate subview, not part of the table. For some reason though, I can't can the search bar to display when it's simply a subview outside of the table.
You have to do this programatically. Here's what I ended up doing.
First add the following to the .h file of your ViewController.
#interface YourViewController : UITableViewController <UISearchBarDelegate>
{
UISearchBar *mySearchBar;
}
#property (nonatomic, retain) UISearchBar *mySearchBar;
#end
Then put this code in the viewDidLoad method of my RootViewController.
self.mySearchBar = [[[UISearchBar alloc]
initWithFrame:CGRectMake(0.0, 64.0, self.view.bounds.size.width,
44.0)] autorelease];
self.mySearchBar.delegate = self;
self.mySearchBar.showsCancelButton = YES;
self.mySearchBar.hidden = YES;
self.mySearchBar.tintColor = [UIColor lightGrayColor];
[self.navigationController.view addSubview: self.mySearchBar];
You may also need to add something like this to prevent the searchBar from being on top of your tableView.
self.tableView.frame = CGRectMake(0.0, 44.0, 320, 324);
In my case, the searchBar remained in the view when I drilled down to a detail view. I had to call:
self.mySearchBar.hidden = YES;`
In my didSelectRowAtIndexPath to get rid of it when I click on a cell.
It doesn't work with UITableViewController. Here's what will give you desired behaviour:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
return search; //in .h, IBOutlet UISearchBar* search;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 44;
}
I have a structure like this....
UITableViewController -> UITableViewCell -> UIView
I need the UIView to access a HashTable (NSMutableDictionary) in the UITableViewController
Is there a way to access the ViewController simply from the ViewCell (using [ViewCell superview] obviously won't work) ....Do I need to go down through the AppDelegate using [[UIApplication sharedApplication] delegate]?
Thanks!
This should do the trick:
UITableView *tv = (UITableView *) self.superview.superview;
UITableViewController *vc = (UITableViewController *) tv.dataSource;
I usually maintain a weak reference from my UIView to my UIViewController if I need one, usually by creating a method something like this:
-(MyView*)initWithController:(CardCreatorViewController*) aController andFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
{
controller = aController;
// more initialisation here
}
return self;
}
You could also use a delegate pattern if you want a more decoupled solution. I tend to think this is overkill for a view and its controller, but I would use it with a system of controllers and subcontrollers.
You can create a category for this:
#implementation UITableViewCell (FindTableViewController)
- (id<UITableViewDataSource>)tableViewController
{
UIView *view = self;
while (!(view == nil || [view isKindOfClass:[UITableView class]])) {
view = view.superview;
}
return ((UITableView *)view).dataSource;
}
#end
Then you can simply access self.tableViewController from the cell itself (assuming you have included this category). You may need to cast it to your table view controller's class tho.
Since the UITableViewCell is somewhere in the view hierarchy, you can access your root view by retrieving view.superview until you get it. If you don't want to add any properties to your view, you can access its controller through the view's nextResponder property. You would have to cast it to whatever class you need, of course, and it may not be the cleanest use of the property. It's a quick-n-dirty hack to get to it.
If you're looking for something you can show your children though, I'd aim for going through your app delegate, or if your view controller happens to be a singleton, just implement the singleton design pattern and access it through that.
Some modification from Kare Morstol answer :
The hierarchy of tableviewcell is in iOS 5.0(my test version)
cell.superview = tableview
cell.superview.superview = UIViewControllerWrapperView
So, use cell.superview to get tableview. And the tableview and tableviewController has a relation of delegate, dataSource in default.
You can get tableviewController reference by tableview.delegate or tableview.dataSource.
UITableView *tableView = cell.superview;
UITableViewController *tableViewController = tableView.delegate; // or tableView.dataSource`