iOS 6 UISearchBar in UINavigationBar not work - ios6

I put my search bar in the navigation bar with these code:
UISearchBar* searchBar = [[UISearchBar alloc] init];
searchBar.delegate = self;
[searchBar setShowsSearchResultsButton:YES];
self.navigationItem.titleView = searchBar;
When I run the same code in iOS 7, it works as I want.
But the search bar cannot work in iOS 6: when I touch it, the keyboard doesnot appear; when I click the result list button in the search bar, nothing happens, too.
Help!
(The base SDK is iOS 7.0)
Edit1
Solving the problem like this:
Just cover the search bar on the navigation bar.
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 7.0)
// Left Cancel button.
UIBarButtonItem *barbtnCancel = [[UIBarButtonItem alloc] initWithTitle:#"Cancel" style:UIBarButtonItemStyleBordered target:self action:#selector(cancel:)];
self.navigationItem.leftBarButtonItem = barbtnCancel;
// Right Search button.
UIBarButtonItem *barbtnSearch = [[UIBarButtonItem alloc] initWithTitle:#"Search" style:UIBarButtonItemStyleBordered target:self action:#selector(search:)];
self.navigationItem.rightBarButtonItem = barbtnSearch;
// Navigation bar.
UINavigationBar* navBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 44)];
[navBar pushNavigationItem:self.navigationItem animated:YES];
[self.view addSubview:navBar];
// Search bar.
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(53, 0, SCREEN_WIDTH-53-53, 44)];
self.searchBar.delegate = self;
[self.searchBar setBarStyle:UIBarStyleDefault];
[self.searchBar setKeyboardType:UIKeyboardTypeDefault];
[self.searchBar setPlaceholder:#"Search Something"];
[self.searchBar setShowsSearchResultsButton:NO];
[self.view addSubview:self.searchBar];
}

You need to initialize the search bar with a frame that is not CGRectZero.

Related

Restoring first responder after dismissing popoverview

I have a text view on the main view controller. I have a bar button item on the view controller's navigation bar. When the app starts, I perform the following actions:
Tap the text view to begin editing and to show the keyboard.
Tap the bar button to show a popover view.
Without dismissing the popover view, I dismiss the keyboard.
Dismiss the popover view by tapping any other view on the screen.
Before iOS 11, the keyboard will NOT show up again after Step 4. However, in iOS 11, it will show up. It seems that in iOS 11, it restores the first responder after dismissing the popover view.
Here are my questions:
Is it a bug, or some changes in iOS 11?
If it is new, then how can I prevent the keyboard from showing after dismissing the popover view?
Also see the following videos:
For iOS 11:
https://www.dropbox.com/s/88wyv0y0idsmu5c/iOS%2011.mov?dl=0
For iOS 10.3:
https://www.dropbox.com/s/11gg6h39mcgb0fs/iOS%2010.3.mov?dl=0
Here are some codes:
#import "MainViewController.h"
#interface MainViewController ()
#property(nonatomic, retain)UITextView *textView;
#end
#implementation MainViewController
#synthesize textView = _textView;
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
self.textView = [[UITextView alloc] init];
self.textView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.textView];
self.textView.backgroundColor = [UIColor blueColor];
NSDictionary *dict = #{#"textView" : self.textView};
NSArray *vCons = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|-3-[textView]-3-|" options:0 metrics:nil views:dict];
NSArray *hCons = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-3-[textView]-3-|" options:0 metrics:nil views:dict];
[self.view addConstraints:vCons];
[self.view addConstraints:hCons];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end
#import "ViewController.h"
#import "MainViewController.h"
#interface ViewController ()
#property(retain,nonatomic)MainViewController *mainVC;
#end
#implementation ViewController
#synthesize mainVC = _mainVC;
- (void)viewDidLoad {
[super viewDidLoad];
self.mainVC = [[MainViewController alloc] init];
UINavigationController *navigCon = [[UINavigationController alloc] initWithRootViewController:self.mainVC];
self.mainVC.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Button" style:UIBarButtonItemStylePlain target:self action:#selector(showPopover)];
[self.view addSubview:navigCon.view];
}
-(void)showPopover {
UIAlertController *alertCon = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *action1 = [UIAlertAction actionWithTitle:#"Action 1" style:UIAlertActionStyleDefault handler:nil];
UIAlertAction *action2 = [UIAlertAction actionWithTitle:#"Action 2" style:UIAlertActionStyleDefault handler:nil];
[alertCon addAction:action1];
[alertCon addAction:action2];
[alertCon setModalPresentationStyle:UIModalPresentationPopover];
UIPopoverPresentationController *popPresenter = [alertCon popoverPresentationController];
popPresenter.barButtonItem = self.mainVC.navigationItem.rightBarButtonItem;
[self presentViewController:alertCon animated:YES completion:nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end
I just had this issue on iOS 11 with a swift app. Calling [textView resignFirstResponder] any time before dismissing the new controller was the only fix. [view endEditing] was not enough.

Why can't I see the text when I type in a UITextField embedded in a UIPopover?

I have an iPad app (XCode 4.6, ARC, Storyboards) where I want a popover to appear with a UITextField in it when the user taps a UIButton.
The popover appears, the keyboard appears, but nothing appears in the UITextField. What am I missing?
Here is the code:
// make the popover
UIViewController* popoverContent = [[UIViewController alloc] init];
UIView* popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 450, 500)];
popoverView.backgroundColor = [UIColor colorWithWhite:(CGFloat)1.0 alpha:(CGFloat)1.0]; // frame color?
popoverContent.view = popoverView;
//resize the popover view shown in the current view to the view's size
popoverContent.contentSizeForViewInPopover = CGSizeMake(450, 500);
// add the UITextfield to the popover
UITextField *tf = [[UITextField alloc]init];
[tf becomeFirstResponder];
[popoverView addSubview:tf];
//create a popover controller
popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContent];
[popoverController presentPopoverFromRect:((UIButton *)oSendFeedback).frame inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
The text field should be created with
UITextField *tf = [[UITextField alloc] initWithFrame:...]
to specify the origin and size of the field.

How to dismiss a popover in iPhone 5 iOS 6?

When my iPhone 5 app starts up I present no view controller because of the following:
- (void) viewDidAppear:(BOOL)animated {
}
The first thing the user will do is touch a button that is on the initial screen
that opens up a menu for retrieving a picture either from the user's
photo library, camera, or a picture of obama. The method that is called when that button is touched by the user is:
- (IBAction) pickImage {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Image Source"
delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil
otherButtonTitles:#"Photo Library", #"Camera", #"Obama", nil];
[actionSheet showInView:scrollView];
[actionSheet release];
}
Now the actionSheet eventually calls:
[self presentViewController:imagePicker animated:TRUE completion:nil];
For the iPhone 5 everything works and the user is given 3 options with the presentViewController. After the user picks an image then I call:
[[picker presentingViewController] dismissViewControllerAnimated:YES completion:nil];
and the View Controller goes away. Now what I WOULD LIKE TO DO IS make the view controller appear initially so the user doesn't have to touch the button connected to pickImage by adding a line to the viewDidAppear method like so:
- (void) viewDidAppear:(BOOL)animated {
[self pickImage]; // makes the image picker pop up when app intializes
}
HOWEVER, when I test this, the imagePicker automatically appears like I expected but then after I finish picking my image and dismiss it, it reappears after I have chosen my image. HOW CAN I FIX THIS???
The following is the class I am talking about:
MainViewController.h FILE: http://db.tt/Vgm3w0gs
MainViewController.m FILE: http://db.tt/uN8YdNGN
Or you can just look at the following relevant methods:
- (void) actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
switch (buttonIndex) {
case 0: { //photo library
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:imagePicker animated:TRUE completion:nil];
} else {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Photo library is empty or unavailable" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
break;
}
case 1: //camera option has it's view controller dismissed after image is taken. The rest of ActionSheet doesn't really matter...
HERE is the method that dismisses the ViewController except when imagePicker is called from within viewDidAppear. QUESTION: How can I get the viewController to dismiss when imagePicker is called from within viewDidAppear?
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
// loads image into main screen
[self loadImage:[info objectForKey:UIImagePickerControllerOriginalImage]];
[[picker presentingViewController] dismissViewControllerAnimated:YES completion:nil];
} [picker release];
}
Your current problem seems to be that you want pickImage to be called when the view first appears, but not when it reappears as a result of a popup window closing.
One possibilty would be to move the pickImage call from the viewDidAppear callback into the viewDidLoad callback.
However, if that is being called too soon, the other option would be to add a boolean variable that you check in viewDidAppear to make sure that pickImage is only called once.
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (firstAppearance) {
firstAppearance = NO;
[self pickImage];
}
}
And set that boolean to true in the viewDidLoad callback.
- (void) viewDidLoad {
[super viewDidLoad];
firstAppearance = YES;
}
Obviously you would also need to declare the bool in your header file somewhere.
BOOL firstAppearance;

How to mimic UIAlertView modal behavior with custom view?

I have a view that pops up a UIAlertView if the name field for an item entry isn't populated when you attempt to save. I wanted to display my own custom alert view instead. I load it with a xib:
- (void)enterNameAlert {
NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:#"AddNameAlertView" owner:self options:nil];
enterNameAlertView = [subviewArray objectAtIndex:0];
enterNameAlertView.frame = CGRectMake(232, 417, 303, 171);
enterNameAlertView.alpha = 0.0;
[self.view addSubview:enterNameAlertView];
[self.view bringSubviewToFront:enterNameAlertView];
//fade view in
[UIView animateWithDuration:.50f delay:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^(void) {
enterNameAlertView.alpha = 1.0;
} completion:NULL];
[UIView commitAnimations];
}
However, you can still click on all the other elements on the view while the alert is displayed. Ideally, I'd like to make the alertview modal. As a hack, I just set xxxx.enabled = NO to all the other elements while the alertview is up, and switch them back to xxxx.enabled = YES when you press OK on the alert.
There has to be a better way to cancel all touches to self.view but not to self.enterNameAlertView.
If I do self.view.userInteractionEnabled = NO it cancels all touches to self.view as well as self.enterNameAlertView.
Any ideas?
I think the solution for your problem is that you have to introduce one more view in between your custom alert view and orignal view, once the alert comes you need to bring that view on your self.view and hide (or remove) it when your alert is dismissed, i have already done this and it work like charm for me. Hope this helps you too :)
Got it. I used a UIScrollView with interaction enabled. That stops touches from outside the custom alertview from being passed to the main view underneath.
- (void)enterNameAlert {
//pop a UIScrollView behind the alert so that the user can't touch the controls behind it
shadowScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 768, 1024)];
shadowScrollView.userInteractionEnabled = YES;
shadowScrollView.backgroundColor = [UIColor blackColor];
shadowScrollView.alpha = 0.0;
[self.view addSubview:shadowScrollView];
[self.view bringSubviewToFront:shadowScrollView];
//put the alertview in front of the disabled view to make it act like a modal view
NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:#"AddNameAlertView" owner:self options:nil];
enterNameAlertView = [subviewArray objectAtIndex:0];
enterNameAlertView.frame = CGRectMake(232, 417, 303, 171);
enterNameAlertView.alpha = 0.0;
[self.view addSubview:enterNameAlertView];
[self.view bringSubviewToFront:enterNameAlertView];
//animate view in
[UIView animateWithDuration:.50f delay:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^(void) {
shadowScrollView.alpha = .6;
enterNameAlertView.alpha = 1.0;
} completion:NULL];
[UIView commitAnimations];
}

UITapGestureRecognizer won't trigger in IOS 6

The following code worked fine is IOS 5, but now handleTapGesture doesn't even get called in IOS 6. What changed?
- (id)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapGesture:)];
[self addGestureRecognizer:tap];
}
return self;
}
- (void)handleTapGesture:(UITapGestureRecognizer *)recognizer
{
MessageNib *cell = self;
MessageView *view = (MessageView *)[[[NSBundle mainBundle] loadNibNamed:#"MessageView" owner:self options:nil] objectAtIndex:0];
view.message = cell.message;
[[NSNotificationCenter defaultCenter] postNotificationName:NEW_SUB_PAGE object:view];
}
I guess you have to set the numberOfTaps after alloc init
tap.numberOfTapsRequired = 1;
Or the other possibility is initWithCoder was not called.
Ended up just putting a "phantom" button (aka button with no content) over my item I wanted tappable and attached a Touch Up Inside event to the button which calls my tap gesture code.
This is a decent momentary hack anyway.

Resources