UISearchBar with ScopeBar in Modal Form Sheet - objective-c

My ViewController is a custom UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate>. I have set up the UISearchBar to display a scope bar.
I instantiate the view controller once and then show the same view on demand via [self presentModalViewController:mySearchController fromView:self.view];
Now, when I configure the view controller to be displayed as a form sheet, the scope bar appears only the first time the view is shown. The next time the scope bar is not displayed.
Displaying the view as a page sheet works fine. However in this case I observe that the first time the scope bar is already in place, while thereafter it is animated into the search bar as soon as it becomes the first responder.
I fiddled around with the view and controller settings in the inspector without any success.
What is causing this behavior?
How can I make the scope bar appear in the form sheet the next time I am showing the view?
Is there a way to prevent the UISearchBar from going into a different state when its view is hidden/redisplayed?

Set the scope bar titles in search delegate for begin editing and make it nil when the search ends. And add the showScopeBar method right after this method. Try and check if that helps.
For eg:-
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
[searchBar setScopeButtonTitles:[NSArray arrayWithObjects:#"Title1", #"Title2", nil]];
[searchBar setShowsScopeBar:YES];
//...
}
And in didEndEditing,
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
[searchBar setScopeButtonTitles:nil];
[searchBar setShowsScopeBar:NO];
//..
}
In addition to this, whenever you want to display the scopebar you can use the above lines to show and hide it.

Related

Why UINavigationController keep popping out the top controller

I have UITabBarController, one of the tab points to a UINavigationController. The UINavigationController rootViewController is of class BGProfileView which shows users' profile
At viewDidAppear, I arranged that if users didn't logged in it will push a BGLogin view controller.
[BGLogin alreadyLoggedin:self.navigationController hideBackButton:YES anddoBlock:^{
[self whatToDoAfterLogin];
}];
Now everything is fine but with one minor issue. If I press the tab again, BGLogin will be poped out of UINavigationController.
I have no idea what makes that BGLogin poped out.
If I select a different tab and then click back to the BGProfile tab, this doesn't happen. It just happens when I click the same active tab. So I am in BGProfile tab, and I click that tab again. Basically it happens when I select the active tab that should simply do nothing. In fact, it does do nothing on others.
I put a breakpoint in viewWillDisappear and this is what I see:
As you see, viewDidAppear is called by the main loop. But why the hell the mainloop call viewDidAppear? Usually there is a code saying things like nav popViewController
Chances are there . that your tab bar controller is pushing new navigation controller with root view controller. and you interpreting that it's popping out. When same tab is selected you need to tell your tabBarController to not to do anything explicitly.
Example
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
UIViewController *tbSelectedController = self.tabBarController.selectedViewController;
if ([tbSelectedController isEqual:viewController]) {
return NO;
}
return YES;
}

Returning data from UIViewController in a UIPopoverController when popover is dismissed

I have a second view controller set to display in a UIPopoverController. I set up a delegate in the second view controller so when the user taps the button "Done", it passes the data back to the first view controller. The data is a list of selections the user makes, its not a single selection.
i'm having trouble figuring out a way to pass that data back to the first view controller if the user tap's outside of the pop over and is dismissed. right now, if the user taps out side of the pop over and it gets dismissed, i lose the data.
i suppose i could restrict them from dismissing the pop over by tapping outside of it, but i'd rather not.
any ideas?
When you present the UIPopoverController, set its delegate to be self
And then add to the class this function
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
YourViewController *controller = popoverController.contentViewController;
MyData *data = controller.yourData;
//Do something with data
}
This function will be called when the popover is dismissed

How to make a UITextView not take the focus when initializing?

I'm using code to create a detailed view pushed when you press a row of an UITableView, but theres a problem.
The detailed view contain an UITextView and when a detailedView is called (only first time) this make the UITableView row pressed to lose its pressed state. It shouldn't ! It should lose the pressed state only when returning from the detailed view to the list view.
As soon as I remove the UITextView from my code, no problem !
I think it's something like UITextView taking focus?
Is there any way to avoid this ? By subclassing or such?
Hmmm not seeing this in the sandbox I just wrote.
Created a simple navigation-based project.
Added a view controller to the project with XIB; added a UITextField to the XIB.
Made following code changes to the root view controller:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
in cellForRowAtIndexPath:
cell.text = #"Push me";
in didSelectRowAtIndexPath:
SimpleViewController *detailViewController = [[SimpleViewController alloc] initWithNibName:#"SimpleView" bundle:nil];
in viewDidLoad:
self.navigationItem.title = #"Home";
Selecting the "Push me" row highlights the row and pushes the SimpleViewController onto the stack. Selecting the "Home" back button pops the view off the stack, returning to the table view and deselecting/un-highlighting the selected row. This is true whether or not the textfield in the SimpleViewController is the first responder at the time of the back navigation.

Why is it that my UITableViewController setEditing:animated: method is not called?

I must be doing stupid, but I can't see what: my UITableViewController subclass is never called when the edit button of my navigation is pressed.
What could be causing that?
My view hierarchy is loaded from a Nib file and put inside a popover. The [+] button is connected to the insertNewObject action of my UITableViewController subclass. It works fine.
The [Edit] button however has no action to connect to. The doc says it will automatically call the setEditing:animated: method of the view controller, which I override.
The nib file is set up pretty much as usual AFAICT. And in fact, I'm not sure what additional detail I can give that would suggest my mistake.
What is the control flow from the click on the [Edit] button to the call of the setEditing:animated method?
I feel like we must be missing the same thing.
Whatever the case, I made it work by doing the following.
IBOutlet UIBarButtonItem *editButton;
-(IBAction)editButtonPressed:(id)sender {
[self setEditing:YES animated:YES];
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animate
{
if(self.tableView.isEditing)
{
self.editButton.style = UIBarButtonItemStylePlain;
self.editButton.title = #"Edit";
}
else
{
//self.editButton.style = UIBarButtonSystemItemDone;
self.editButton.style = UIBarButtonSystemItemEdit;
self.editButton.title = #"Done";
}
// Toggle table view state
[super setEditing:!self.tableView.isEditing animated:animate];
}
I hooked the editButton up to the button I added to the nav bar and it's action to the editButtonPressed IBAction. After doing that my setEditing: is called (obviously) and the super call toggles the table view's editing state.
I'd like to use the system defined button styles, but the appropriate one is commented out because while it did change style I couldn't figure out how to change the text from "Edit" to "Done" so I had to do it all manually (that only worked if I left the button as Custom and set the style generically). This has the downside of not being localized (for free), etc.

TabBarController NAvigationController and UIViewController

I have the next question:
In my project I have the next:
UItabbarController
....Some UINAvigationControllers....
*(1) UINavigationController
UIViewController (UItableView) - When select one row it goes to...(by push) to:
UIViewController (UItableView) - And here the same than before, for each row i open a new tableview....
My problem is when i click in the tab bar item, I see the viewController view like last time that i saw this, and no reload to the *(1) first view another time( like i would like)
Where I need to write sth for each time that i click in a tab bar item i reload the first view of this tab bar item.
PD: I have the call: [theTableView reloadData]; in method "viewWillAppear".
The thing I'm doing is:
In my navigation Controller I have a View Controller (like tableview) and when i click in one row, in the "didSelectRowAtIndexPath" method I create another View Controller calling "myController" and i push this element like this ( [[self navigationController] pushViewController:myController animated:YES];)
And this for each time i click in one row in the next tables.
Then I think the problem is not to reload the table view in the method viewWillAppear, it's to take out from the screen the next views controller that I inserted to the root one.
I'm rigth?
IN RESUME:
My app has the next:
Tab bar to move between screens
Navigation inside each tab bar (as far as you want), why? because all the tabBarItems show Tables, and if you click in one row you open another table,.....
My problem then is that I would like to come back to the 1st Main table when i click in the tab bar. For the moment the app doesn't do this, it continue in the scree(table view) that was the last visit in this tab. (Is not completely true, because if i click two time, Yes, it comes back but don't enter in the "viewWillLoad" or "didSelectViewController" methods, because i made NSLogs and it doesn't show them).
The sketche can be this:
AppDelegate -> WelcomeScreen ->VideosTableViewController ->RElatedVideosTableViewController -> ..... ..... ....
The 1st thing is to show the Welcome screen (not so important, only some buttons) and in this class i have the TabBArController initialized with "localViewControllersArray" that is a NSMutableArray of NavigationControllers each initialized with one ViewController .
Then when i press one of the buttons in this welcome Screen i sho the tab bar Controller (Shows the VideosTableViewController)
In the next step, when I click in one row, in "DidSelectRowAtIndexPath" I create a RElatedVideosTableViewController, and I push this by "[[self navigationController] push....: "The relatedvideo table view i create" animated:YES];
AND I ALSO HAVE:
Add: UITabBarControllerDelegate
Add:
(void)tabBarController:(UITabBarController*)tabBarController
didEndCustomizingViewControllers:
(NSArray*)viewControllers
changed:(BOOL)changed { }
(void)tabBarController:(UITabBarController*)tabBarController
didSelectViewController:(UIViewController*)viewController
{ if ([viewController
isKindOfClass:[UINavigationController
class]])
{ [(UINavigationController *)viewController popToRootViewController:NO];
[theTableView reloadData];
NSLog(#"RELOAD");
} }
And at the initialization of the class:
[super.tabBarController setDelegate:self];
But in the console I don't see the NSLog I'm making then is not going in this method.
Make your app delegate the tab bar controller's delegate, either in Interface Builder or in code:
- (void)applicationDidFinishLaunching
{
...
self.tabBarController.delegate = self;
}
Then, when the tab bar switches to a different view, you get notified, at which point you pop to the root of the selected nav controller thus:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
if ([viewController isKindOfClass:[UINavigationController class]])
{
[(UINavigationController *)viewController popToRootViewController:NO];
}
}
Each view controller should have its own table view, so I don't know what you are trying to do by the reload.