Background: I have a UIViewController that, when loads, has a UITableView generated programmatically that gets its data from an SQLite3 database. This works fine.
Problem: I need to add a UISearchBar (and associated logic) but when I try, the UISearcBar is not rendered.
Code so far:
.h file:
#import <UIKit/UIKit.h>
#import "sqlite3.h"
#import "Exhibitor.h"
#interface ExhibitorViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate>
{
sqlite3 *congressDB;
NSMutableArray *searchData;
UISearchBar *searchBar;
UISearchDisplayController *searchDisplayController;
}
#property (strong, nonatomic) IBOutlet UITableView *tableView;
-(NSString *) filePath;
-(void)openDB;
#end
.m file where the UISearchBar is added:
-(void)loadTableView
{
CGRect usableSpace = [[UIScreen mainScreen] applicationFrame];
CGFloat usableWidth = usableSpace.size.width;
CGFloat usableHeight = usableSpace.size.height;
UITableView *tableView = [[UITableView alloc] init];
[tableView setFrame:CGRectMake(0,0,usableWidth, usableHeight)];
tableView.dataSource = self;
tableView.delegate = self;
[self.view addSubview:tableView];
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 64)];
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
searchDisplayController.delegate = self;
searchDisplayController.searchResultsDataSource = self;
self.tableView.tableHeaderView = searchBar; // I think this should have loaded the searchBar but doesn't
// [self.tableView setTableHeaderView:searchBar]; // Have also tried this
// [self.tableView.tableHeaderView addSubview:searchBar]; // And this
NSLog(#"searchBar = %#", searchBar); // This shows the searchBar is an object with values
NSLog(#"HeaderView = %#", self.tableView.tableHeaderView); // This shows the tableHeaderView as null ??
}
What am I doing wrong? What do I need to do to add a UISearchBar programmatically to a UITableView within a UIVewController?
You should use a UITableViewController instead...
.h
#interface ExhibitorViewController : UITableViewController <UISearchBarDelegate, UISearchDisplayDelegate> {
sqlite3 *congressDB;
NSMutableArray *searchData;
UISearchBar *searchBar;
UISearchDisplayController *searchDisplayController;
}
-(NSString *) filePath;
-(void)openDB;
#end
.m
-(void)loadTableView {
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 64)];
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
searchDisplayController.delegate = self;
searchDisplayController.searchResultsDataSource = self;
self.tableView.tableHeaderView = searchBar;
}
The problem is you were creating a table view but not assigning it to the property, and using UITableViewController makes things much simpler anyway...
If you want to keep it the way it is now, then you could just put self.tableView = tableVew; after [self.view addSubview:tableView];...
The problem is that
self.tableView
in loadTableView is nil or it is not that table that you have created programmatically.
Add
self.tableView = tableView;
after
[self.view addSubview:tableView];
Without this your searchBar is added to invalid tableView.
should
Related
In my application, I do not use the NavigationController, in general.
In UITableView I would do so, would add
[Self.view addSubview: self.myCustomHeaderView];
But I'm using ASTableNode. If I do something, something similar here:
- (instancetype)init {
_tableNode = [[ASTableNode alloc] init];
self = [super initWithNode:_tableNode];
if (self) {
_tableNode.dataSource = self;
_tableNode.delegate = self;
self.navigationItem = //navigationItem implement
UINavigationBar *navbar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
navbar.backgroundColor = [UIColor redColor];
navbar.items = #[self.navigationItem];
ASDisplayNode *navBarNode = [[ASDisplayNode alloc] initWithViewBlock:^UIView * _Nonnull {
return navbar;
}];
[self.node addSubnode:navBarNode];
}
return self;
}
Then this node is added as part of the list and scrolled along with the list, and I need it to be as fixed header.
initWith ASDisplayNode rather than ASTableNode,then add table node on VC's node,for example:
#interface OCTextureTableController : ASViewController<ASDisplayNode *>
#property (nonatomic, strong) ASTableNode *tableNode;
- (instancetype)init
{
self = [super initWithNode:[ASDisplayNode new]];
if (self) {
self.tableNode = [[ASTableNode alloc] init];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.tableNode.backgroundColor = [UIColor yellowColor];
self.tableNode.frame = CGRectMake(0, NAVIGATION_BAR_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT-NAVIGATION_BAR_HEIGHT);
[self.node addSubnode:self.tableNode];
}
(i) take Class A as base Class.
(ii) take Class B as derived Class having type of class A.
Now in class A Add a uiview on top. that will be considered as navigation.(do anything in that view)
To use same navigation bar: you have to take other all classes as having type of class A.
that's it.
I have the problem like this: Hide UISearchBar Cancel Button
I have subclassed UISearchController and UISearchBar, and override methods layoutSubviews in UISearchBar.
How to override searchBar property with custom UISearchBar in my custom UISearchController?
Update 1
To implement property with custom UISearchBar i do in MyUISearchController:
#property(nonatomic, strong, readonly) UISearchBar *searchBar;
And
#synthesize searchBar=_searchBar;
- (UISearchBar *)searchBar {
return [MySearchBar new];
}
But UISearchController uses default searchBar anyway..
Update
In h file:
#interface MySearchController : UISearchController <UITableViewDelegate, UITableViewDataSource>
In m file:
#interface MySearchController () <UISearchDisplayDelegate, UISearchControllerDelegate,
UISearchBarDelegate, UISearchResultsUpdating, SearchAutocompleteLoader>
#property UISearchController *searchController;
#property (strong, nonatomic) UITableView *searchResultTable;
#property UIView *viewForSearchBar;
#property (nonatomic) NSInteger filterSettings;
#property (strong, nonatomic) UILabel *matchesLabel;
#property (strong, nonatomic) UIView *loading;
#property (strong, nonatomic) UIView *foggView;
#end
- (instancetype)initWith:(UIView *)viewForSearch foggView:(UIView *)view delegate:(id)delegate andResultTableView:(UITableView *)tableView
{
self.viewForSearchBar = viewForSearch;
self.searchResultTable = tableView;
self.foggView = view;
self.searchDelegate = delegate;
[self configureSearchController];
return self;
}
- (void)configureSearchController {
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.delegate = self;
self.searchController.hidesNavigationBarDuringPresentation = NO;
self.searchController.dimsBackgroundDuringPresentation = NO;
[self loadFilterSettings];
self.searchController.searchBar.delegate = self;
[self.searchController.searchBar setShowsCancelButton:NO];
//self.searchController.searchBar.searchBarStyle = UISearchBarStyleDefault;
[self.searchController.searchBar setBackgroundImage:[UIImage imageWithCGImage:(__bridge CGImageRef)([UIColor clearColor])]];
[self.searchController.searchBar setImage:[UIImage imageNamed:#"iconSearchSettings"] forSearchBarIcon:UISearchBarIconBookmark state:UIControlStateNormal];
self.searchController.searchBar.frame = CGRectMake(0, 0, self.view.frame.size.width, self.viewForSearchBar.frame.size.height);
self.viewForSearchBar.tintColor = [UIColor yellowColor];
// [self.viewForSearchBar addSubview:self.searchController.searchBar];
self.searchController.searchBar.barTintColor = [UIColor whiteColor];
self.searchController.searchBar.tintColor = [UIColor blackColor];
//self.searchController.searchBar.backgroundColor = [UIColor whiteColor];
[self.viewForSearchBar addSubview:self.searchController.searchBar];
for (UIView *subView in self.searchController.searchBar.subviews) {
if ([subView isKindOfClass:[UITextField class]]) {
[subView setTintColor:[UIColor blueColor]];
[[(UITextField *) subView valueForKey:#"textInputTraits"] setValue:[UIColor blueColor] forKey:#"insertionPointColor"];
}
}
[self.searchController setActive:YES];
[self.searchController setActive:NO];
}
UISearchController's searchBar is a computed property, you have to store your custom searchBar and return it when call searchBar.
Here is some code in Swift:
var mySearchBar = MySearchBar()
override var searchBar: UISearchBar {
get{
return mySearchBar;
}
}
In order to customize the searchBar property begin the customization process by subclassing first the search bar (UISearchBar). Then, use this custom search bar in the subclass of the search controller, and at the end use both of them in the your ViewController class.
Refer this tutorial:
UISearchController Customization
import UIKit
class MySearchController: UISearchController {
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
searchBar.showsCancelButton = false
}
}
See this one tutorial for customise the UISearchBar in Swift:
Customise UISearchBar
Objective - C : Add the code in ViewDidLoad. You have already declare object of UISearchBar
[searchBar setShowsCancelButton:NO];
Swift : in ViewDidLoad
searchBar.showsCancelButton = false
I'm using a UISearchController and it is working fine. However it is leaving a blank space over the search bar (when it is focused) which partially hides the status bar. This espace
I already tried setting the self.edgesForExtendedLayout = UIRectEdgeNone also self.navigationController.extendedLayoutIncludesOpaqueBars = YES but the space is still there. I tried setting the self.definesPresentationContext = YES;but it generated that the searchBar take the status bar position like this.
I'm using a UIViewController embedded in a UINavigationController. This is the setUp that im implementing now:
#interface DirectoryViewController : UIViewController <UITableViewDataSource , UITableViewDelegate ,UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating>
#property (strong, nonatomic) NSMutableArray *personsArray;
#property (nonatomic, strong) UISearchController *searchController;
#property (nonatomic, strong) NSMutableArray *searchResults;
#implementation DirectoryViewController
- (void)viewDidLoad {
[super viewDidLoad];
UINavigationController *searchResultsController = [[self storyboard] instantiateViewControllerWithIdentifier:#"TableSearchResultsNavController"];
// Our instance of UISearchController will use searchResults
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
// The searchcontroller's searchResultsUpdater property will contain our tableView.
self.searchController.searchResultsUpdater = self;
self.searchController.delegate = self;
self.searchController.searchBar.delegate = self;
//Cancel button tint
_searchController.searchBar.tintColor = [UIColor whiteColor];
[self.searchController.searchBar setBackgroundImage:[UIImage imageNamed:#"navBar"]
forBarPosition:0
barMetrics:UIBarMetricsDefault];
if ([self respondsToSelector:#selector(edgesForExtendedLayout)]) { /// iOS 7 or above
self.edgesForExtendedLayout = UIRectEdgeNone;
}
self.navigationController.extendedLayoutIncludesOpaqueBars = YES;
}
I appreciate any help. Thanks
I found the solution in This answer.
Changing the tableInsets:
self.directoryTable.contentInset = UIEdgeInsetsMake(-10, 0, 0, 0);
when the searchController is becameFirstResponder
and
self.directoryTable.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
when the search bar action is finished.
I have a UIVIew with Button. This is loaded in the VIewController as hidden. No problem unhiding it but the button on top of it is not working. Is the UIview class the right place to put the codes for the exit button (hiding it again)?
in .h
#interface infoView : UIView
#property (nonatomic, strong) IBOutlet UIView *infoTextView;
#property (nonatomic, strong) UIButton *exitButton;
-(void)exitView:(UIButton*)sender;
#end
in .m
#import "infoView.h"
#implementation infoView
#synthesize infoTextView = _infoTextView;
#synthesize exitButton=_exitButton;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
_infoTextView = [[UIView alloc]initWithFrame:CGRectMake(40, 40, 240, 240)];
[_infoTextView setBackgroundColor: [UIColor blueColor]];
[self addSubview:_infoTextView];
_exitButton = [[UIButton alloc] initWithFrame:CGRectMake(200, 10, 30, 30)];
//other info
[self.infoTextView addSubview:self.exitButton];
}
return self;
}
-(void)exitView:(UIButton*)sender
{
self.infoTextView.hidden=YES;
}
viewController
#implementation gjViewController
#synthesize imageViewMain = _imageViewMain;
#synthesize changeImageButton = _changeImageButton;
#synthesize infoButton = _infoButton;
#synthesize myInfo = _myInfo;
- (void)viewDidLoad
{
[super viewDidLoad];
_imageViewMain = [[UIImageView alloc] init];
//other info
[self.view addSubview:self.imageViewMain];
_changeImageButton = [[UIButton alloc] initWithFrame:CGRectMake(110, 50, 100, 50)];
//other info
[self.view addSubview:self.changeImageButton];
_infoButton = [[UIButton alloc] initWithFrame:CGRectMake(260, 30, 40, 40)];
//other details
[self.view addSubview: self.infoButton];
the section below is the part where the UIView is loaded. It loads and unhides with the IBAction at the bottom. I think you are pointing that this is wrong, not sure how. Thanks for comments.
_myInfo = [[infoView alloc] init];
[self.view addSubview:_myInfo];
[_myInfo setHidden:YES];
}
-(IBAction)newImage:(UIButton*)sender{
//task
-(IBAction)oldImage:(UIButton*)sender{
//taks
-(IBAction)viewInfo:(UIButton*)sender{ <--- unhides the UIView
[_myInfo setHidden:NO];
I'm adding a UIViewController which has only an UILabel to the main UIView. I create it like this:
WEPopoverLabel *contentViewController = [[WEPopoverLabel alloc] init];
[contentViewController setContents:#"aaa"];
(The hole code .m):
if (!self.popoverController) {
WEPopoverLabel *contentViewController = [[WEPopoverLabel alloc] init];
[contentViewController setContents:#"aaa"];
contentViewController.lContent.text=#"aaarrr";
self.popoverController = [[[popoverClass alloc] initWithContentViewController:contentViewController] autorelease];
self.popoverController.delegate = self;
self.popoverController.popoverContentSize = CGSizeMake(50.0f, 20.0f);
self.popoverController.passthroughViews = [NSArray arrayWithObject:sender];
CGRect rectForPopover = [self.view convertRect:sender.bounds fromView:sender];
[self.popoverController presentPopoverFromRect:rectForPopover inView:self.view permittedArrowDirections:(UIPopoverArrowDirectionUp|UIPopoverArrowDirectionDown) animated:YES];
[contentViewController release];
}
Well, WEPopoverLabel is being created because it shows up in my window and also executes setContents because I've got a NSLog which is printing in my console.
However, the label is not being changed. This is the content of WEPopoverLabel:
#interface WEPopoverLabel : UIViewController{
IBOutlet UILabel * lContent;
}
-(void)setContents:(NSString *) theContent;
and .m
#implementation WEPopoverLabel
-(void)setContents:(NSString *) theContent{
lContent.text = theContent;
NSLog(#"texto fijado");
}
In the .xib, I've connected the lContent to File's owner.
Why is not being updated the text of UILabel?
In the UIViewController, have you connected the main view in the xib to the file owner as well as connecting the label?
Also have you added WEPopoverLabel to the view after it is created:
[currentView addSubview:contentViewControler]
I would give the label a background colour so you can tell if it is actually beng displayed.
-(void)setContents:(NSString *) theContent{
lContent = [[UILabel alloc] init]
lContent.text = theContent;
NSLog(#"texto fijado");
}
thats correct. check this:
http://forums.macrumors.com/showthread.php?t=1002736
Or
#property (nonatomic, retain) IBOutlet UILabel *lContent;
and in this method:
self.lContent.text = theContent