I have a TableViewController, a SearchResultsController and a WebViewController. When I click on a cell in the TableViewController it pushes the WebViewController opening a url that is related to the cell.
The TableViewController has a UISearchController which filters the results into the SearchResultsController however when a cell is clicked in the SearchResultsController the WebViewController doesn't get pushed.
Here is the code for the didSelectRowAtIndexPath for the SearchResultsController:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
WebViewController *webViewController = [[WebViewController alloc] init];
NSString *extensionURL = (self.searchResults[indexPath.row])[#"url"];
NSURL *baseURL = [NSURL URLWithString:#"http://www.baseurl.com"];
NSURL *URL = [NSURL URLWithString:extensionURL relativeToURL:baseURL];
webViewController.title = (self.searchResults[indexPath.row])[#"title"];
NSLog(#"%#", URL);
webViewController.URL = URL;
[self.navigationController pushViewController:webViewController
animated:YES];
}
I included the NSLog to see if anything happened when a cell was clicked and it does display the url in the console. This makes me think the problem is with the navigationController.
Looking online it seems that the UISearchController should be wrapped in a UISearchContainerViewController which should then be put in the navigationController. I'm still new to app development and can't figure out how or where to do this.
I call my SearchResultsController in the viewDidLoad of my TableViewController like so:
- (void)viewDidLoad
{
[super viewDidLoad];
SearchResultsViewController *controller = [[SearchResultsViewController alloc] initWithStyle:UITableViewStylePlain];
[self addObserver:controller forKeyPath:#"results" options:NSKeyValueObservingOptionNew context:nil];
self.searchController = [[UISearchController alloc] initWithSearchResultsController: controller];
self.searchController.searchResultsUpdater = self;
self.searchController.hidesNavigationBarDuringPresentation = NO;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.delegate = self;
self.definesPresentationContext = YES;
UISearchBar *searchBar = [[UISearchBar alloc] init];
searchBar = self.searchController.searchBar;
searchBar.searchBarStyle = UISearchBarStyleMinimal;
UITextField *searchField = [searchBar valueForKey:#"_searchField"];
searchBar.barTintColor = [UIColor whiteColor];
searchBar.tintColor = [UIColor whiteColor];
self.navigationItem.titleView = searchBar;
}
Is this where I should be embedding my SearchResultsController?
When doing search you will present the NewModalViewController so its simple all you need to do is some steps for pushing viewcontroller when you present search controller
1)self.definesPresentationContext = YES;
After this you should push your viewcontroller like
2) [self.presentingViewController.navigationController pushViewController:sec animated:YES];
Note:Present modalviewcontroller doesnt have Navigation controller so normal push coding wont work as it is not allocated to navigation.
Enjoy.....
You can create a property in your SearchResultsController:
#property (nonatomic, strong) UINavigationController *navController;
Then in your updateSearchResultsForSearchController in your TableViewController set the navController = self.navigationController.
Then you can do this in your SearchResultsController's didSelectRowForIndexPath:
[self.navController pushViewController:webViewController
animated:YES];
This approach worked for me after failing to get Arun's above mentioned solution to work.
Related
I have embedded a UITabBarController inside a UINavigationController. The UITabBarController contains 3 different tabs which leads to 3 different UIViewControllers which displays UITableView. I implemented all these through storyboard. In the first UIViewController, I have implemented a UISearchController for the UITableView programatically which is working. The View turns black when I search for a particular cell and then if I switch tabs.
I believe that the issue has some relation to SearchController because before including the SearchController, I didn't have any issues.
I have gone through few other questions in here, but none could solve my issue.
Edited :
Below is my code related to SearchController.
#interface
#property (nonatomic, strong) UISearchController *searchController;
#property BOOL searchControllerWasActive;
#property BOOL searchControllerSearchFieldWasFirstResponder;
#implementation
viewDidAppear()
self.searchController = [[UISearchController alloc]initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
[self.searchController.searchBar sizeToFit];
self.tblContactsTable.tableHeaderView = self.searchController.searchBar;
self.searchController.delegate = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.searchBar.delegate = self;
self.definesPresentationContext = YES;
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
//reloads table view according to what is searched.
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
self.searchController.searchBar.showsCancelButton = NO;
UITabBarController should be the top most element on window from your storyboard/code and you can add the Navigation Controllers and View Controllers to UITabBarController view controllers.
https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITabBarController_Class/index.html
use this sample code it will surely help you here chatlist, contactlist and findfriends are 3 UIViewControllers
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// self.navigationItem.hidesBackButton=YES;
self.navigationController.navigationBar.backgroundColor = [UIColor blueColor];
_chatlist = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"ChatListVC"];
_contactlist = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"ContactListVc"];
_findfriends = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"FindfriendsVC"];
self.tabbarcontroller = [[UITabBarController alloc]init];
self.viewControllers = [NSArray arrayWithObjects:_chatlist,_contactlist,_findfriends, nil];
self.tabBar.frame =CGRectMake(0,44,self.view.frame.size.width,50);
UITabBarItem *item0 = [self.tabBar.items objectAtIndex:0];
UITabBarItem *item1 = [self.tabBar.items objectAtIndex:1];
UITabBarItem *item2 = [self.tabBar.items objectAtIndex:2];
item0.title = #"Chat List";
item1.title = #"Contacts";
item2.title = #"Find Friends";
[item0 setFinishedSelectedImage:[UIImage imageNamed:#"chatlist.png"] withFinishedUnselectedImage:[UIImage imageNamed:#"chatlist.png"]];
[item1 setFinishedSelectedImage:[UIImage imageNamed:#"contacts.png"] withFinishedUnselectedImage:[UIImage imageNamed:#"contacts.png"]];
[item2 setFinishedSelectedImage:[UIImage imageNamed:#"findfriends.png"] withFinishedUnselectedImage:[UIImage imageNamed:#"findfriends.png"]];
}
Figured out the answer myself. I don't know if its the exact right way of doing it but now the App seems working.
I place my UITabBarController as the Initial View and separate UINavigationControllers for each tabs.
My task is to implement inside UIViewController (Not TableVC) search bar with UISegmentedControl. I want to make something like
But my result is
How to prevent UINavigationBar from hiding (iOS 8)? And how to place UISearchBar below segmentedControl?
Inside viewDidLoad
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
self.searchController.searchResultsUpdater = self;
self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x,
self.searchController.searchBar.frame.origin.y,
self.searchController.searchBar.frame.size.width, 44.0);
self.tableView.tableHeaderView = self.searchController.searchBar;
#pragma mark - UISearchControllerDelegate & UISearchResultsDelegate
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
NSString *searchString = self.searchController.searchBar.text;
[self updateFilteredContentForAirlineName:searchString];
if (self.searchController.searchResultsController) {
UINavigationController *navController = (UINavigationController *)self.searchController.searchResultsController;
MBQuestionsSearchResultVC *vc = (MBQuestionsSearchResultVC *)navController.topViewController;
vc.searchResults = self.searchResults;
[vc.tableView reloadData];
}
}
I also try to make constraints programmatically
- (void)updateViewConstraints
{
[self.searchController.searchBar mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.segmentedControl.mas_bottom).with.offset(10.f);
make.leading.mas_equalTo(self.view);
make.trailing.mas_equalTo(self.view);
make.height.mas_equalTo(44.f);
}];
[super updateViewConstraints];
}
But the result is not good
Thanks in advance :(
I am trying to add a search bar programmatically to an UIView (not a UITableView). For the moment, I am just trying to set the delegates properly so that when I click the "enter" button, a message is printed:
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
NSLog(#"enter button clicked");
[searchBar resignFirstResponder];
}
I already have some code working for an UITableViewController that I am trying to adapt. It looks like this (I am skipping all the parts of the code that are not relevant to the present discussion):
#property (nonatomic, strong) UISearchController *searchController;
#property (nonatomic, strong) UITableViewController *resultsTableController;
- (void)viewDidLoad {
[super viewDidLoad];
self.resultsTableController = [[SearchResultsController alloc] init];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:self.resultsTableController];
self.searchController.searchResultsUpdater = self;
[self.searchController.searchBar sizeToFit];
self.searchController.delegate = self;
self.searchController.searchBar.delegate = self;
self.definesPresentationContext = YES;
self.tableView.tableHeaderView = self.searchController.searchBar;
}
Now the only line that doesn't transpose to the UIViewController case is the last one
self.tableView.tableHeaderView = self.searchController.searchBar;
My UIViewController is defined with a xib which contains a UIView called myView and a UISearchBar called searchBar. So I tried doing
self.myView = self.searchController.searchBar;
or
self.searchBar = self.searchController.searchBar;
but in the first case the searchBardoesn't even show and in the second case the delegation to self seems lost (nothing happens when I click enter).
What am I doing wrong ?
This is how you would add a UISearchBar to a UIViewController programmatically:
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0, 0.0, kScreenWidth, 40.0)];
self.searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
self.searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
self.searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.searchBar.tintColor = kRunnerSearchBarTintColor;
if ([RunnerUtilities isIOS7orAbove]) {
self.searchBar.searchBarStyle = UISearchBarStyleProminent;
[self.searchBar setBarTintColor:[UIColor colorWithRed:185.0/255.0 green:195.0/255.0 blue:202.2/255.0 alpha:0]];
}
self.searchBar.delegate = self;
[self.view addSubview:self.searchBar];
Well, this is no more different than adding it from XIB file. First, search bar is a added as a subview to view of view controller and should be connected to search bar outlet defined in ViewController. Second, UIViewController must be set as delegate of the search bar. Please ensure you are following this and this should work.
EDIT::
If you are trying to use UISearchController within UIViewController, please try with following code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any custom init from here...
// Create a UITableViewController to present search results since the actual view controller is not a subclass of UITableViewController in this case
UITableViewController *searchResultsController = [[UITableViewController alloc] init];
// Init UISearchController with the search results controller
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
// Link the search controller
self.searchController.searchResultsUpdater = self;
// This is obviously needed because the search bar will be contained in the navigation bar
self.searchController.hidesNavigationBarDuringPresentation = NO;
// Required (?) to set place a search bar in a navigation bar
self.searchController.searchBar.searchBarStyle = UISearchBarStyleMinimal;
// This is where you set the search bar in the navigation bar, instead of using table view's header ...
self.navigationItem.titleView = self.searchController.searchBar;
// To ensure search results controller is presented in the current view controller
self.definesPresentationContext = YES;
// Setting delegates and other stuff
searchResultsController.tableView.dataSource = self;
searchResultsController.tableView.delegate = self;
self.searchController.delegate = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.searchBar.delegate = self;
}
I am working on an app for iOS6 and iOS7. I just found a weird behavior that varies between the two versions.
My app has a UITabbarController with 3 tabs and each tab as UINavigationController in it.
On iOS6 when I do a push on any of these navControllers the 2nd ViewController after the root does not show a back button in the navigationBar. However any subsequent pushes show the back button.
On iOS7, however, I see a back button with no title after 1st push and a back button with title "Back" after subsequent push.
Is this behavior normal? I can't understand why this is happening. How do I make sure I have a back button after every push irrespective of the OS version.
EDIT
Here is some code for clarity :
This is how I am initiating the UITabBarController
- (id)init {
self = [super init];
if (self) {
NSMutableArray *vcs = #[].mutableCopy;
JBNavigationVC *navVC = nil;
if ([JBUser sharedInstance].isLoggedIn) {
_productCategoryVC = [[JBProductCategoryVC alloc] init];
_productCategoryVC.title = #"Products";
navVC = [[JBNavigationVC alloc] initWithRootViewController:_productCategoryVC];
[vcs addObject:navVC];
_triviaVC = [[JBTriviaVC alloc] init];
_triviaVC.title = #"Trivia";
navVC = [[JBNavigationVC alloc] initWithRootViewController:_triviaVC];
[vcs addObject:navVC];
_infoVC = [[JBInfoVC alloc] init];
_infoVC.title = #"Info";
navVC = [[JBNavigationVC alloc] initWithRootViewController:_infoVC];
[vcs addObject:navVC];
}
self.viewControllers = vcs;
}
return self;
}
JBNavigationVC is a subclass of UINavigationController. This is how I transition to the tabbarVC in AppDelegate
_tabBarVC = [[JBTabBarVC alloc] init];
[_tabBarVC setSelectedIndex:0];
[self.window setRootViewController:_tabBarVC];
This sets the first VC to front. This VC is has a UITableView in it and in - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath I do this:
if (!_productsListVC) {
_productsListVC = [[JBProductsListVC alloc] init];
}
_productsListVC.category = category;
[self.navigationController pushViewController:_productsListVC animated:YES];
I want to create a UIView for a UITabBarController
Here is my code for the .h file :
#interface TE : UIViewController <UITabBarControllerDelegate>{
UITabBarController *tabBarController;
}
#property (nonatomic,retain) UITabBarController *tabBarController;
#end
The viewDidLoad method:
UIViewController *testVC = [[T1 alloc] init];
UIViewController *otherVC = [[T2 alloc] init];
NSMutableArray *topLevelControllers = [[NSMutableArray alloc] init];
[topLevelControllers addObject: testVC];
[topLevelControllers addObject: otherVC];
tabBarController = [[UITabBarController alloc] init];
tabBarController.delegate = self;
[tabBarController setViewControllers:topLevelControllers animated:NO];
tabBarController.selectedIndex = 0;
self.view = tabBarController.view;
This creates the tab bar controller, but when I click on a tab bar item, I get an error:
Thread1:Program receive signal: SIGABRT
Edit: I solved the problem by downloading and modifying the version of http://www.iphonedevcentral.com/create-uitabbarcontroller/
You say above that you don't want to create the tabBarController in the appDelegate. Why not? Where else would you create it? The tabBarController has to be the root view controller and cannot be a child of any other view controller.
Btw, make sure you implement:
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
NSUInteger tabIndex = [tabBarController.viewControllers indexOfObject:viewController];
if (viewController == [tabBarController.viewControllers objectAtIndex:tabIndex] ) {
return YES;
}
return NO;
}
Subclass UITabBarController
Override the - (void) loadView method and include the following code
MyCustomViewControllerOne* ctrl1 = [[[MyCustomViewControllerOne alloc] initWithNibName#"MyViewControllerOne" bundle: nil] autorelease];
UIViewController* ctrl2 = [[[UIViewController alloc] init] autorelease];
MyCustomControllerTwo* ctrl3 = [[[UIViewController alloc] initWithObject: myObj] autorelease];
ctrl1.title = #"First tab";
ctrl2.title = #"Second tab";
ctrl3.title = #"Third tab";
ctrl1.tabBarItem.image = [UIImage imageNamed:#"tab_image1.png"];
ctrl2.tabBarItem.image = [UIImage imageNamed:#"tab_image2.png"];
ctrl3.tabBarItem.image = [UIImage imageNamed:#"tab_image3.png"];
[self setViewControllers: #[ctrl1, ctrl2, ctrl3]];
That's pretty much it.
Change self.view = tabBarController.view; to
[self.view addSubview:tabBarController.view]; And it works correctly
Trying changing
self.view = tabBarController.view;
to
[self.view addSubview:tabBarController.view];
See if that helps.
Also try placing this in your -(void)loadView method
- (void)loadView {
UIView *mv = [[UIView alloc] initWithFrame:CGRectMake(0.0, 100.0, 320.0, 480.0)];
self.view = mv;
[mv release];
}
The reason you probably are experiencing a black screen is because you haven't initialized your UIView properly.
#Mehdi, just make your TE a UITabBarController instead of a UIViewController which then has a TabBarController in it. Makes it all the more easy to manage your TabBarController. To respond to some others who have indicated that you can have only one TabBarController as the window's rootViewController. That is not the case. A UITabBarController can be instantiated in multiple places where you need a second level menu navigation. Have a TabBar within a TabBar would not make sense, but having a left Navigation Menu and then having a TabBar on each menu item would make sense.