UISearchDisplayController frame not show from top edge with auto layout - ios

I've UITableViewController with UISearchBar in headerView.
When typing some string to search the status bar doesn't show correctly.
All delegates and outlets are in place.
UPDATE:
Temporary fix which personally I don't like, but it still work (animation movement looks bad anyway):
- (void)resizeSeachBarBackground
{
for (UIView *view in self.searchDisplayController.searchBar.subviews)
{
if ([view respondsToSelector:#selector(subviews)])
{
for (UIView *view2 in view.subviews)
{
if ([view2 isKindOfClass:NSClassFromString(#"UISearchBarBackground")])
{
id UISearchBarBackground = view2;
if ([UISearchBarBackground respondsToSelector:#selector(frame)])
{
[UISearchBarBackground setFrame:CGRectMake(0, -20, CGRectGetWidth([UIScreen mainScreen].bounds), 64.0)];
break;
}
}
}
}
}
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
if (!self.navigationController.navigationBarHidden)
[self.navigationController setNavigationBarHidden:true animated:false];
[self resizeSeachBarBackground];
..
..
..
}

After hours of trying, I delete the previous code, deleted the search bar and outlets and connected all over again.

Instead of deleting the same, Disable the auto layout inside interface builder and then enable the same and do the proper connection of auto layout.

Putting the following line in the viewDidLoad fixed to it:
self.edgesForExtendedLayout = UIRectEdgeNone;

Related

Remove Next / Previous buttons (inputAccessoryView) for Custom Keyboard in iOS8 WebView

Please bear with me, I searched a lot over the internet and I couldn't find a solution since it's a new API.
I am trying to create a custom keyboard for iOS 8. It works perfectly fine except in WebView!
It has previous-next button, which are in inputAccessoryView. I know it's read-only property for webview but since iOS 8 allows the users to have custom keyboard I assume this view should be editable somewhere. Has anybody run into the same issue? Any help would be appreciated.
You may try and improve this. try call this function inside Your UIKeyboardDidShowNotification event handler.
-(void) removeKeyboard {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual : [UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
// Locate UIWebFormView.
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([[possibleFormView description] hasPrefix : #"<UIInputSetContainerView"]) {
for (UIView* peripheralView in possibleFormView.subviews) {
for (UIView* peripheralView_sub in peripheralView.subviews) {
// hides the backdrop (iOS 8)
if ([[peripheralView_sub description] hasPrefix : #"<UIKBInputBackdropView"] && peripheralView_sub.frame.size.height == 44) {
[[peripheralView_sub layer] setOpacity : 0.0];
}
// hides the accessory bar
if ([[peripheralView_sub description] hasPrefix : #"<UIWebFormAccessory"]) {
for (UIView* UIInputViewContent_sub in peripheralView_sub.subviews) {
CGRect frame1 = UIInputViewContent_sub.frame;
frame1.size.height = 0;
peripheralView_sub.frame = frame1;
UIInputViewContent_sub.frame = frame1;
[[peripheralView_sub layer] setOpacity : 0.0];
}
CGRect viewBounds = peripheralView_sub.frame;
viewBounds.size.height = 0;
peripheralView_sub.frame = viewBounds;
}
}
}
}
}
}
Hope this helps...
This is the level of views in accessory:
(UIWebFormAccessory) -> (UIToolbar) -> (UIImageView,UIToolbarButton,UIToolbarButton)
Removing or scaling to zero height the accessory bar will cause black area. You can play around the mainview's frame or bounds. or if You just want to get rid of the buttons, just try to have a 0 opacity on the UIToolbutton , the toolbutton is inside uitoolbar view
Use this , it works like a charm and it is much cleaner than the other solutions. It's hacking with the inputAccessoryView for UIWebBrowserView (inner UIWebView).
Good luck with coding!

Can't bring delete subview to front

I'm trying to bringtofront my subview because the delete button keeps disappearing.
#implementation MyCell : UITableViewCell
- (void)layoutSubviews
{
[super layoutSubviews];
for (UIView *subview in self.subviews) {
for (UIView *subview2 in subview.subviews) {
NSLog(#"HERE!");
if ([NSStringFromClass([subview2 class]) isEqualToString:#"UITableViewCellDeleteConfirmationView"]) {
NSLog(#"got inside the if!");
[subview2 sendSubviewToBack:subview];
[subview bringSubviewToFront:subview2];
[self.superview bringSubviewToFront:subview2];
}
}
}
}
#end
I subclassed UITableViewCell. Both the NSLogs are printing so I know it's getting in there, but I've tried all 3 of these methods to put the view in front. Any ideas why this wouldn't be working?
subview2 is a subview of subview, which is a subview of self. The receiver of the sendSubviewToBack: or bringSubviewToFront: message must be the superview of the view given as argument. Therefore only the second one of the calls you make is valid. The correct calls would be
[self.superview bringSubviewToFront:self];
[self bringSubviewToFront:subview];
[subview bringSubviewToFront:subview2];
(And the same for sendSubviewToBack:.)
As for your actual problem, I can't figure out the view hierarchy you are using from the code posted, but it seems that it is incorrect. You should probably not have your custom views as direct subviews of self, but rather as subviews of self.contentView (as per Apple's documentation).

IOS7 : uisearchdisplaycontroller always show scope bar

Basically what I'm trying to achieve is to have my scope bar to never disappear.
Environment : IOS 7, storyboard, inside a view controller I have a "search bar and search display controller" and a separate tableview (the searchbar is not inside the table)
Inside the view controller.h
#property (nonatomic, strong) IBOutlet UISearchBar *candySearchBar;
Inside the view controller.m
#synthesize candySearchBar;
What I tried : inside a custom search bar class
- (void) setShowsScopeBar:(BOOL) showsScopeBar
{
if ([self showsScopeBar] != showsScopeBar) {
[super invalidateIntrinsicContentSize];
}
[super setShowsScopeBar:showsScopeBar];
[super setShowsScopeBar: YES]; // always show!
NSLog(#"setShowsScopeBar searchbar");
NSLog(#"%hhd", showsScopeBar);
}
and
searchBarDidEndEditing
Same thing in the view controller, but then
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[candySearchBar setShowsScopeBar:YES];
[candySearchBar sizeToFit];
}
I hope my question is clear, I tried many solutions posted all over the internet, most of them talk about the setshowsscopebar, but it doesn't seem to work. The output of the log in setshowscopebar is 1, but the scopebar is still not shown.
I still consider myself to be new to the code, the fault can still be a newbie mistake.
edit : another piece of code in the view controller, as you can see i'm searching blind:
-(void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller{
self.searchDisplayController.searchBar.showsCancelButton = YES;
self.searchDisplayController.searchBar.showsScopeBar = YES;
controller.searchBar.showsScopeBar = TRUE;
controller.searchBar.frame = CGRectMake(0, 149, 768, 88);
UIButton *cancelButton;
UIView *topView = self.searchDisplayController.searchBar.subviews[0];
for (UIView *subView in topView.subviews) {
if ([subView isKindOfClass:NSClassFromString(#"UINavigationButton")]) {
cancelButton = (UIButton*)subView;
}
}
if (cancelButton) {
//Set the new title of the cancel button
[cancelButton setTitle:#"Cancel" forState:UIControlStateNormal];
[cancelButton setEnabled:YES];
controller.searchBar.showsScopeBar = YES;
//candySearchBar.scopeButtonTitles = [NSArray arrayWithObjects:#"Flags", #"Listeners", #"Stations", nil];
}
NSLog(#"%#",NSStringFromCGRect(controller.searchBar.frame));
NSLog(#"%#",NSStringFromCGRect(controller.searchBar.bounds));
NSLog(#"%hhd#",controller.searchBar.hidden);
}
The code you tried will not work in iOS7 onward because apple has changed it behavior of UISearchBar to hide the scope when return to normal view. Add this method to your custom searchBar class.
-(void)layoutSubviews
{
[super layoutSubviews];
if([[UIDevice currentDevice].systemVersion floatValue]>=7.0) {
//Get search bar with scope bar to reappear after search keyboard is dismissed
[[[[self.subviews objectAtIndex:0] subviews] objectAtIndex:0] setHidden:NO];
[self setShowsScopeBar:YES];
}
}
Directly accessing object at index may crash the app in iOS6 because of difference in view hierarchy between iOS6 and iOS7, to avoid this, add this inside if condition only when its iOS7.
In addition this is also required in the custom search bar class
-(void) setShowsScopeBar:(BOOL)showsScopeBar {
[super setShowsScopeBar:YES]; //Initially make search bar appear with scope bar
}
I have the same issue. Perhaps it is something that has changed in iOS7 since showing the scope bar is supposed to be the default behaviour. You can verify this in the section "Creating an Optional Scope Bar to Filter Results" of the following tutorial:
http://www.raywenderlich.com/16873/how-to-add-search-into-a-table-view
Hopefully someone has a solution for this; otherwise we will have to look for a workaround.
initialize set scope bar NO
[self.searchBar setShowsScopeBar:NO];
[self.searchBar sizeToFit];
//default scope bar selection
self.searchBar.selectedScopeButtonIndex=3;
unselect/remove tick from scopeBar checkbox
It's possible (but hacky) to do this without a custom searchBar, in a pretty similar way to what CoolMonster suggests.
In your TableViewController, this will show the ScopeBar after a search ends:
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
//Show the scopeBars
controller.searchBar.showsScopeBar = YES;
//Resize the searchBar to show ScopeBar
controller.searchBar.frame = CGRectMake(0, 0, 320, 88);
if([[UIDevice currentDevice].systemVersion floatValue]>=7.0) {
[[[[controller.searchBar.subviews objectAtIndex:0] subviews] objectAtIndex:0] setHidden:NO];
}
}
Then, since you probably want it to appear before you search, add this line to the TableViewController's viewDidLoad:
[self searchDisplayControllerDidEndSearch:self.searchDisplayController];
For the record, after getting this to work, I ended up using a separate segmented control instead of the approach above for several reasons, not least of which was that touching the ScopeBar of a SearchBar, once you get it to display, launches the search display tableView, which makes of sense if you're using it the recommended way. However, since I wanted the ScopeBar to work without launching the search tableview, for me it made more sense just to use my own segmented control and add it to my tableHeaderView under the searchBar.

ViewController moving up - iOS

This following code is to scroll view up. However, it is not shifting up my viewcontoller. I have debugged code and it hits every single line of code , but my view controller. is not shifting up
//DownViewController.m
-(BOOL) textFieldShouldBeginEditing:(UITextField *)textField
{
if (textField == self.hoursTextField) {
[textField resignFirstResponder];
taggy=self.hoursTextField.tag;
}
if (textField ==self.codeTextField) {
[textField resignFirstResponder];
taggy=self.codeTextField.tag;
}
return YES;
}
- (void)keyboardDidShow:(NSNotification *)notification
{
//Assign new frame to your view
sensorViewController =[[SensorsViewController alloc]initWithNibName:#"SensorsViewController" bundle:[NSBundle mainBundle]];
[sensorViewController setTag:taggy];
}
//SensorsViewController.m
-(void)setTag: (int)tag
{
if(tag==1)
{
a=-80;
[self.view setFrame:CGRectMake(0,a,1030,768)];
}
if(tag==2)
{
a=-260;
[self.view setFrame:CGRectMake(0,a,1030,768)];
}
}
Shift the call of setTag method inside viewDidLoad of SensorsViewController.
You are assigning a new value to sensorViewController every time the keyboard shows. That instance that you just assigned isn't onscreen, so of course the one that is onscreen won't be affected. You should keep a reference to the view controller that's already onscreen, maybe with an IBOutlet if you're using a storyboard or nib file.

Objective-C, how to Generally resignFirstResponder?

(my boss says) that I have to implement a "Done" button on a navBar so that the various items in the view (that contain an edit box) will dismiss their keyboard (if they were in focus).
It seems that I must iterate through all items and then call resignFirstResponder on each on the off-chance that one of them is in focus? This seems a bit messy (and hard to maintain if e.g. someone else adds more items in future) - is there a better way to do it?
I have found it!
Thanks to this
I discovered that all I need do is this:-
-(void) done {
[[self.tableView superview] endEditing:YES];
}
// also [self.view endEditing:YES]; works fine
[remark]
Also I learn how to do the equivalent of an "eventFilter" to stop UITableViewController from swallowing background touch events by intercepting them before they get there - from the same, wonderful post on that thread - see "DismissableUITableView".
[end of remark]
You don't have to iterate through the controls since only one can be first responder at the moment.
This will reset the responder to the Window itself:
[[self window] makeFirstResponder:nil]
One solution is to use a currentTextField Object,
In .h file have an instance variable as
UITextField *currentTextField;
Now in .m file.
Note : Dont forget to set the delegates of all the textField to this class
- (void)textViewDidBeginEditing:(UITextView *)textView
{
currentTextField = textField;
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
currentTextField = nil;
}
Now in your button action method
-(IBAction)buttonTap
{
if([currentTextField isFirstResponder])
[currentTextField resignFirstResponder];
}
This avoids iterating through all the text field.
I think best way to handle it by searching all subviews of main view with recursive function, check example below
- (BOOL)findAndResignFirstResponder {
if (self.isFirstResponder) {
[self resignFirstResponder];
return YES;
}
for (UIView *subView in self.subviews) {
if ([subView findAndResignFirstResponder]) {
return YES;
}
}
return NO;
}
and also you can put this method to your utility class and can use from tap gesture. All you have to do is simply adding to gesture to view.
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(hideEverything)];
[self.tableView addGestureRecognizer:gestureRecognizer];
and than you can call hideEverything method;
- (void) hideKeyboard {
[self.view findAndResignFirstResponder];
...
...
}

Resources