I have a programatically created UITextField added to the NavigationController as below (within a UITableViewController since I wanted a custom fixed search bar at the top).
In .h file
#property (nonatomic, strong) UITextField *searchText;
In .m file
#synthesize searchText;
self.searchText = [[UITextField alloc] init];
self.searchText.frame = CGRectMake(35, 234, 250, 27);
self.searchText.backgroundColor = Rgb2UIColor(255, 255, 255);
[self.navigationController.view addSubview:self.searchText];
self.searchText.delegate = self;
However none of the following methods get triggered
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
}
-(void)textFieldDidBeginEditing:(UITextField *)textField{
self.searchText.returnKeyType = UIReturnKeySearch;
}
- (void)textFieldDidEndEditing:(UITextField *)textField{
}
Can someone point me to the right direction on why my delegate does not work?
Better use uiseachbar from the objects panel. This comes with default search bar style and effects but is similar to uitextfield. You can set the delegate and listen to it the same way as you do for textview.
Related
I have a tableviewcontroller and a custom headerview (uiview)
Headerview interface
#interface HMDiscoveryHeaderView : UIView <UISearchBarDelegate>
#property (nonatomic, strong) UISearchBar *searchBar;
#end
the searchbar is initialized in the layoutSubviews method
- (void)layoutSubviews {
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(20, 20, 250, 50)];
[self addSubview:self.searchBar];
}
and I'm able to get the text in it like so
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
NSLog(#"search text %#", searchBar.text);
}
in my tableview, the interface is this
#interface HMDiscoveryViewController () <UISearchBarDelegate>
#property (nonatomic, strong) NSString * stuff;
#property (nonatomic, strong) HMDiscoveryHeaderView *headerView;
#end
and i set the header in viewdidload like so
- (void)viewDidLoad {
[super viewDidLoad];
self.headerView = [[HMDiscoveryHeaderView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 100)];
[[self.headerView searchBar] setDelegate:self];
[self.tableView setTableHeaderView:self.headerView];
NSString *testy = [[self.headerView searchBar] text];
// this prints null
NSLog(#"test %#", testy);
}
and these 2 methods to attempt to get the text are never called
- (void)setStuff:(NSString *)stuff
{
_stuff = stuff;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[self setStuff:searchBar.text];
NSLog(#"lol shit %#", self.stuff);
}
How do i get the input text in the UISearchBar in the headerview in the tableviewcontroller?
"My headerview has a UISearchbar as a subview initialized in the viewdidload"
this isn't possible since the headerView is a UIview as you stated, and UIViews don't have a "viewDidLoad" method, however, I digress ... assuming that you meant that the UITAbleViewController declares the headerview in the view did load then you need to do something like this:
HeaderView.h
#interface HeaderView : UIView
#property (nonatomic) UISearchBar *searchBar
#end
Now you have exposed the UISearchBar to other classes by declaring the UISearchBar in the headerViews header file. then do this
headerview *headerView = [[headerview alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 100)];
self.tableView.tableHeaderView = headerView;
[headerview searchBar].text <==this is the search bar text!
Now, in order to force this Text into the table view, do this:
in the header file to your tableView declare an NSString property
#property (nonatomic) NSString * stuff;
Then, in the tableview implmentaiton file do this:
- (void)setStuff:(NSString *)stuff
{
_stuff = stuff;
}
Now _stuff holds a string value
In your table view controller, in this method:
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
NSLog(#"search text %#", searchBar.text);
}
change it to this:
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
[tableView setStuff:searchBar.text];
}
then, in your tableView you can screw around with the text form the search bar
Delegation is for those who don't know how to use setters and getters correctly, you don't have to use delegation almost ever, and I'd stay away form it because it will turn your app into a beast of of nightmare after you reach 10s of thousands of lines of code.
setters & getters with subclasses is about 4 trillion times better than delegation, use delegation when using UIKit elements that require you to know stuff about the object you are subclassing, otherwise, setters and getters mixed with block operations are bar far the simplest, easiest to read, and most portable ways to code. Pure encapsulation is what you want.
Oh yeah, and make your UITableViewController a UISearchBarDelegte so that you can use the above function in your UITableViewController, that's why you might be scratching your head right now, so this goes into your UITableViewController:
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
[tableView setStuff:searchBar.text];
}
troubles, you are having, this:
Implementation file for UITableViewController:
#interface CustomSuperStarTableViewController () <UISearchBarDelegate, UITableViewDataSource, UITableViewDelegate>
#end
#implementation CustomSuperStarTableViewController
{
SuperNiftyHeaderView * iLikeCats;
}
-(void)viewDidLoad
{
iLikeCats = [SuperNiftyHeaderView new];
[[iLikeCats iLikeCatsSearchBar] setDelegate:self];
[self.tableView setTableHeaderView:iLikeCats];
// you can now access the searchBar!
//here's how you access the searchBar
NSString * bubbleGum = [[iLikeCats iLikeCatsSearchBar] text]; <=== search bar text
UIColor * hello = [[iLikeCats iLikeCatsSearchBar] backGroundColor]; <=== search bar backGroundColor
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
}
I should also note, that this assumes that you actually created a separate .h and .m file that is a subclassed UITableView, correct? and that this subclass has in it's header file an exposed property like this:
#property (nonatomic) MyNiftyCustomHeaderView * customHeaderView
Okay, so different scenario:
headerView is custom and it contains the UISearchBar, right ? Right, excellent, so let's declare the headerview right now!
SuperNiftyHeaderView.h
#interface SuperNiftyHeaderView : UIView
#property (nonatomic) UISearchBar * iLikeCatsSearchBar;
#end
SuperNiftyHeaderView.m
#implementation SuperNiftyHeaderView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
_iLikeCatsSearchBar = [[UISearchBar alloc] init];
[_iLikeCatsSearchBar setPlaceholder:#" Search ..."];
[_iLikeCatsSearchBar setTranslucent:TRUE];
[_iLikeCatsSearchBar setBarStyle:UIBarStyleDefault];
[_iLikeCatsSearchBar setSearchBarStyle:UISearchBarStyleProminent];
[_iLikeCatsSearchBar setBackgroundColor:[UIColor blueColor]];
[_iLikeCatsSearchBar setTranslatesAutoresizingMaskIntoConstraints:FALSE];
[self addSubView:_iLikeCatsSearchBar];
/// do more work, and then more work
/// add constraints because you are going to learn to do all subviews programmatically from here on out and you love to program IOS so much that 1000s of lines of code are better than storyboard easy street
}
return self;
}
#end
Now, relook at the stuff I did for the CustomSuperStarTableViewController
And what's more, is that we could have had access to the search by text by just adding to the UITableViewController and forcing the SearchBar to be a delegate of the ViewController, BUT, we misunderstood each other at first, so the point is:
1. table view controller = search bar delegate
2. intercept text
3. send this text to the tableview to do as you wish, and if it's to use this to filter the tablview then there's about 1 billion tutorials out there on using predicates and arrays to make this magic happen, but of course it will be easier for you to do this because you used a UITableViewController instead of a UIViewController, excellent and have a good day.
this is where you capture goodness from the SearchBar:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
[_categories removeAllObjects];
_searchText = searchText;
NSArray * ss = [test copy];
_categories = [NSMutableArray arrayWithArray:[ss filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF contains[c] %#", _searchText]]];
if (_categories.count ==0 && _searchText.length ==0) {
_categories = [NSMutableArray arrayWithArray:test];
}
[[[self contentView] tableView] reloadData];
}
don't freak out about the method calls in this call, they aren't important to what you are doing, just worry about this:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
_searchText = searchText;
}
and _searchText is declared in the implementation file like this, it's an IVAR
#implementation WhatEverYouWanttoNameItTableViewController
{
NSString * _searchText;
}
I have a text field named "fieldPassword" declared as an IBOutlet
#property (strong, nonatomic) IBOutlet UITextField *fieldPassword;
I synthesize it later on and then, in an attempt to have the return key dismiss the keyboard, I have:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
fieldPassword.delegate = self;
[fieldPassword resignFirstResponder];
[self.view endEditing:YES];
return YES;
}
The problem is that when I run the simulator and hit the return key in the designated text field, nothing happens. Previously, I also had fieldPassword.delegate = self; in -viewDidLoad and that crashed the simulator with an unrecognized selector error.
Any help is much appreciated!
It should be [self.fieldPassword resignFirstResponder]; instead of [fieldPassword resignFirstResponder];
Also self.fieldPassword.delegate = self; should be in viewDidLoad or viewDidAppear
If you don't set the delegate earlier, you won't get the delegate callback. Try this in viewDidLoad:
self.fieldPassword.delegate = self;
You might have been missing the self before.
Follow the below things
1.Go to xib or storyboard where you have set that your view.
2.Right Click the TextField.If you click that you can see the
Outlets->Delegate with Empty Circle
3.Just connect with File's Owner.It is Yellow Color.
Once you do this,the circle is not empty.It is filled now.
4.Then go to declaration or .h part
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITextFieldDelegate>
5.Then in .m
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
Looks like I have a problem with UITextFieldDelegate.
I just created a view controller that responds to UITextFieldDelegate protocol, and easily added the field to the xib, then set delegate field...you know.
But when I trying to press the field (to start editing, the program crashes).
Same thing happens when I trying to create field programmatically.
Here is call stack:
Here is full code:
.h
#import <UIKit/UIKit.h>
#interface TopBar : UIViewController <UITextFieldDelegate>
{
IBOutlet UITextField * field_top;
}
.m
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
NSLog(#"textFieldShouldBeginEditing");
textField.backgroundColor = [UIColor colorWithRed:220.0f/255.0f green:220.0f/255.0f blue:220.0f/255.0f alpha:1.0f];
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
NSLog(#"textFieldDidBeginEditing");
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
NSLog(#"textFieldShouldEndEditing");
textField.backgroundColor = [UIColor whiteColor];
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
NSLog(#"textFieldDidEndEditing");
}
Delegate is set by IB.
Error screenshot:
Any help please.
Ensure you have this in your .h
#interface TopBar : UIViewController <UITextFieldDelegate> {
}
#property (nonatomic, weak) IBOutlet UITextField *field_top;
and remove from the #interface
IBOutlet UITextField * field_top;
It sounds like your field_top is being released and you're trying to access it later, thats why it's crashing.
I found the answer.
The solution is ti also use addChildViewConroller, not only addSubview.
Hope it will help to someone...
I have UITextFields in tableviewcells. When you swipe over the cell not part of the textfield, the delete action comes up as expected. If you swipe over the textfield, it stops the delete from popping up.
How do I fix this so that you can swipe over the inputs and the cell will trigger the delete action?
I think the issue here is that the touch on the text field is interfering with your swipe gesture recognizer (presumably attached to the parent view). I had a similar problem with a text field that was placed in a UIScrollView.
I got around this problem by overlaying a clear UIView on top of my UITextField. I then assigned a UITapGestureRecognizer to this clear view to set the text field as the first responder when the user taps on the field. Otherwise, the swiped is sent to the parent view (a scroll view) which recognizes the swipe without any issues. It's kind of lame but it works.
This scenario is a bit different from yours, but I think it's the same problem. Here is what my code looks like, hopefully it helps:
// UIView subclass header
#interface LSAddPageView : UIView
#property (weak, nonatomic) IBOutlet UITextField *textField; // Connected to the UITextField in question
#property (strong, nonatomic) UIView *textFieldMask;
#property (assign, nonatomic) BOOL textFieldMaskEnabled;
#end
// UIView subclass implementation
#implementation LSAddPageView
- (void)awakeFromNib
{
[super awakeFromNib];
_textFieldMask = [UIView new];
_textFieldMask.backgroundColor = [UIColor clearColor];
[self insertSubview:_textFieldMask aboveSubview:self.textField];
}
- (void)layoutSubviews
{
[super layoutSubviews];
_textFieldMask.frame = self.textField.frame;
}
- (BOOL)textFieldMaskEnabled
{
return _textFieldMask.hidden == NO;
}
- (void)setTextFieldMaskEnabled:(BOOL)textFieldMaskEnabled
{
_textFieldMask.hidden = !textFieldMaskEnabled;
}
#end
And then in the controller:
- (void)viewDidLoad
{
[super viewDidLoad];
_addPageView = (LSAddPageView*)self.view;
_maskGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(didTapMask:)];
_maskGestureRecognizer.numberOfTapsRequired = 1;
_maskGestureRecognizer.numberOfTouchesRequired = 1;
[_addPageView.textFieldMask addGestureRecognizer:_maskGestureRecognizer];
self.textField.delegate = self; // Set delegate to be notified when text field resigns first responder
}
- (void)didTapMask:(UIGestureRecognizer*)recognizer
{
_addPageView.textFieldMaskEnabled = NO;
[self.textField becomeFirstResponder];
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
_addPageView.textFieldMaskEnabled = YES;
return YES;
}
Sounds like you need to set the cancelsTouchesInView property
yourGestureRecognizer.cancelsTouchesInView = NO;
from UIButton & UITextField will block UITableViewCell being swipe to delete
self.tableView.panGestureRecognizer.delaysTouchesBegan = YES;
this will make the textfield not stop left swipe guestures
I'm trying to move the view up when the keyboard shows so it wont cover up the screen, but for some reason its the -(void)DidBeginEditing: (UITextField *)textfield is not working.
- (void)textFieldDidBeginEditing:(UITextField *)ga1
{
/* should move views */
self.view.center = CGPointMake(self.view.center.x, self.view.center.y + 220);
}
- (void)textFieldDidEndEditing:(UITextField *)ga1
{
/* should move views */
self.view.center = CGPointMake(self.view.center.x, self.view.center.y - 220);
}
its nor going into the method, can anyone tell me why?
In the interface of the class add the line , so in the .m file you would put above where it says #implementation...
#interface MyClassName () <UITextFieldDelegate>
// properties can also go here
// for example dragging the IBOutlet for the textfield from the storyboard
#end
You then in viewDidLoad should set the delegate of the UITextField like so...
-(void)viewDidLoad {
// whatever code
self.textField.delegate = self;
}
Alternatively, and more cleanly, you can do this in the story board by control clicking the text field and dragging the indicator to the view controller class icon (the icon to the furthest left) in the lower bar.
Also, why are you calling the argument to the textField in your implementation "ga1"? Best practice you should call it
- (void)textFieldDidBeginEditing:(UITextField *)textField
One final note is that if you have multiple textFields you should set the delegate for each of them in the way described above. This is why the storyboard way of doing it is "cleaner," because it keeps you from having multiple delegate declarations in your code.
If implemented, it will get called in place of textFieldDidEndEditing
#interface MyViewController :UIVieController <UITextFieldDelegate>
#property UITextField *myTextField
#end
#implementation MyViewController{
}
- (void)viewDidLoad {
[super viewDidLoad];
self.myTextfield.delegate=self;
}
-(void)textFieldDidEndEditing:(UITextField *)textField reason:(UITextFieldDidEndEditingReason)reason{
if(reason==UITextFieldDidEndEditingReasonCommitted)
{
NSLog(#"Committed");
}
}
Implement <UITextFieldDelegate> Protocol for your class. And set the delegate to self. Here is Apple's document UITextFieldDelegate Protocol