How to use Custom Picker View with search bar in ios - iphone

I am beginner in iOS In one of my activity I have created custom picker view with search bar .....Actually I am using YHCPicker class for custom picker view and search bar and apply this on TextField Code here.....
UITextField* StateId;
StateId=[[UITextField alloc]initWithFrame:CGRectMake(150,540,150,30)];
StateId.font = [UIFont boldSystemFontOfSize:12.0];
StateId.borderStyle = UITextBorderStyleLine;
StateId.delegate = self;
StateId.tag = 4;
[scrollview addSubview:StateId];
and I am using this delegate for this textfield....
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if (textField.tag==4)
{
View_StateID = [[NSMutable Array]allocinitWithArray:#"Delhi", #"Rajasthan"......, nil];
NSLog(#"dict is %#",View_StateID);
PickerView* objYHCPickerView = [[PickerView alloc] initWithFrame:CGRectMake(0, 0, 320, 480) ];
objYHCPickerView.delegate = self;
[self.view addSubview:objYHCPickerView];
[objYHCPickerView showPicker:View_StateID];
}
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
then call method ShowPicker in YHCPickerView and I show this picker with search bar on my view.....like as image
Now in this image when we search in search bar first time then get desired state successfully and click on done or search button(from keybord) then get value on StateID textfield but when we again tap on text field then my image as well as but tap on searchbar then get error like this....
-[CALayer keyboardWillShowNotification:]: unrecognized selector sent to instance 0xaad8950
So I don't know what problem ....so solve this problem...

Errors like this can be caused by non properly retaining objects:
The object is released and freed.
Its memory is reused for some random other object.
Then, when a selector is called on the original object -> boom.
One thing to check is if all your #properties that hold objects in your class are strong and not assign.
What's also smart to do is setting an exception breakpoint
Finally, try to find out to which object this pointer 0xaad8950 (did) belong(s): Place breakpoints further and further, before the app crashes and look around at the objects' address you're having.
Good luck!

Related

Creating a custom view in Interfacebuilder and using that in code

I have made a view in the application that shows a UITableView. It will be full of results (obviously) almost all the time, however when it does not have any results I want to show another view that inform the user about how he/she could populate the table.
I want to design that view in the interfacebuilder. I will have to check in the code whether the datasource is empty or not to toggle between the two different nibs. How do I instantiate and configure a view made in Interfacebuilder?
The easies way to do this is by adding the view in xib normally and make it visible
Design your both views, the table view and the other view, give the tableView a tag of 111 for example and give the otherview another tag 222 for example
Now in viewDidLoad
Get both the views
UIView *noDataView = [self.view viewWithTag:222];
UITableView *tableView = [self.view viewWithTag:111];
//Hide both of them or only the noDataView until you know if you have data from the dataSource or not
Check for your data source
//hasElements do you have any element to show?
if(hasElements)
{
noDatView.hidden = YES;
tableView.hidden = NO;
}
else
{
noDatView.hidden = NO;
tableView.hidden = YES;
}
You can load nib file based on condition.You can write category as follows:
self.view = (UIView *)[self loadNib:#"SecondView" inPlaceholder:self.view];
- (UIView *)viewFromNib:(NSString *)nibName
{
NSArray *xib = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil];
for (id view in xib) { // have to iterate; index varies
if ([view isKindOfClass:[UIView class]]) return view;
}
return nil;
}
- (UIView *)loadNib:(NSString *)nibName inPlaceholder:(UIView *)placeholder
{
UIView *nibView = [self viewFromNib:nibName];
[nibView setFrame:placeholder.frame];
self.view = nibView;
//[self.view insertSubview:nibView aboveSubview:placeholder];
//[placeholder removeFromSuperview];
return nibView;
}
The other answers give you possible technical solutions but I would propose that if you are using the standard Apple design guidelines, you probably don't even need to worry about it. For instance, somewhere on your screen you should have a bar button item with the identifier "Add" (which shows the plus icon). Then rather than giving a long (often poorly localised) description of how to add items, just have a header for an empty section which says "No items" replacing items with whatever pluralised noun is appropriate for your table's items. For example, for an Archery related app I am working on:
Notice how the Edit button is currently disabled too, thus no explanation is needed as the only thing they can do at this point is tap the Add button (screenshots on the Appstore will have shown them what they can expect to see after this point).

UITableViewCell with TextField and checks input

I am currently create a UITableViewCell with a UITextField in it.
On click of the text field, I want to bring up a number keyboard that I created. And as I type, the textfield should check the input for me; on click of other place, the keypad should be dismissed.
Code:
UITableViewCell *sizeCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"sizeCell"];
sizeCell.textLabel.text = #"Size";
UITextField* sizeField = [[UITextField alloc] initWithFrame:CGRectMake(185, 10, 100, 28)];
sizeField.text = #"0";
sizeField.textAlignment = UITextAlignmentRight;
sizeField.textColor = [UIColor colorWithRed:50.0/255.0 green:79.0/255.0 blue:133.0/255.0 alpha:1.0f];
sizeField.backgroundColor = [UIColor clearColor];
sizeField.keyboardType = UIKeyboardTypeDecimalPad;
[sizeCell.contentView addSubview:sizeField];
rows = [[NSArray arrayWithObjects:switchCell, typeCell, sizeCell, nil] retain];
I tried to implement UITextFieldDelegate like:
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[sizeField resignFirstResponder];
return YES;
}
but the keyboard doesn't go away...
How do I validate the input and dismiss the keyboard?
You never set the delegate on your textfield so that textFieldShouldReturn: gets called. Make sure your class conforms to UITextFieldDelegate and then do the following:
...
UITextField* sizeField = [[UITextField alloc] initWithFrame:CGRectMake(185, 10, 100, 28)];
sizeField.delegate = self; //This is important!
sizeField.text = #"0";
...
A few observations:
As another poster suggested, make sure you set the keyboard's delegate correctly.
If you want to dismiss the keyboard on keyboard return, make sure you have one on your custom keyboard and it's correctly set up to call the ...ShouldReturn method.
If you want to dismiss on taps outside, you'll have to do that on your own.
You are declaring sizeField inside the method where you are setting it up, then calling it from another method outside that scope. I assume you have a class variable called sizeField or you'd be getting a compiler error. However, declaring it again when you're setting it up like you do shadows the class variable declaration so it never gets set up. Incidentally, that's a memory leak.
This shouldn't affect the actual running of the program if all else is correct (but it will if, e.g. 4 is the problem and not fixed), but I think it's better form to call [textField resign...] instead of [sizeField resign...]. At the least you should assert(textField == sizeField).

UIPopoverController memory question

I'm creating a UIPopoverController and setting "Editor1" as the content view controller.
When the caller receives the didDismissPopover I'm releasing the UIPopoverController.
This is the code:
- (IBAction)open1:(id)sender {
Editor1 *editor = [[Editor1 alloc] initWithNibName:#"Editor1" bundle:nil];
_popoverController = [[UIPopoverController alloc] initWithContentViewController:editor];
_popoverController.delegate = self;
[editor release];
[self.popOverController presentPopoverFromRect:self.open1Button.bounds inView:self.open1Button permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
}
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController{
NSLog(#"popoverControllerShouldDismissPopover");
return YES;
}
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController{
NSLog(#"popvoerControllerDidDismissPopover");
[_popoverController release];
}
In my editor I have a UITextField where the user changes text and I save it when I get the message "editingDidEnd"
- (IBAction)editingDidEnd:(id)sender {
NSLog(#"Editing did End");
// SAVE PROCEDURE
}
My question regards the order in which the methods get called.
The order is:
2011-09-07 12:35:21.628 iosTest[1967:b603] popoverControllerShouldDismissPopover
2011-09-07 12:35:21.629 iosTest[1967:b603] popvoerControllerDidDismissPopover
2011-09-07 12:35:21.983 iosTest[1967:b603] Editing did End
2011-09-07 12:35:21.985 iosTest[1967:b603] viewWill Disappear
As you can see the popoverControllerDidDismissPopover gets called before editingDidEnd:, so this means I'm releasing the popover before I do my save procedure. This could bring me a crash problem.
Also, in my save procedure I need to ask the user for confirmation in some cases. I'm using a UIAlertView for this.
Do you have any recommendations?
Usually views are well-behaved and don't send events after they're off-screen. You can check for potential problems by enabling zombies (set the environment variable NSZombieEnabled=YES).
If there is a crash, the correct place to fix it is in -[Editor1 dealloc] (and possibly -viewDidUnload): just do textField.delegate = nil and you should stop receiving callbacks. This is not usually necessary except for web views and scroll views where it seems to be problematic (the scroll animation continues even if the VC is off-screen).
In your case, you can probably make saving happen in -popoverControllerShouldDismissPopover:, returning NO if you need to display a UIAlertView (and dismissing the popover when the button is pressed).
it seems, that _popoverController is the instance-property. in this case you can release it in viewDidUnload method of parent-controller.
Why don't you use UITextFieldDelegate protocol? Usage:
aTextField.delegate = self;
(...)
- (void)textFieldDidEndEditing:(UITextField *)textField {
NSLog(#"Editing did End");
// SAVE PROCEDURE
}
Read the documentation for more info.

Can I hook into UISearchBar's Clear Button?

I've got a UISearchBar in my interface and I want to customise the behaviour of the the small clear button that appears in the search bar after some text has been entered (it's a small grey circle with a cross in it, appears on the right side of the search field).
Basically, I want it to not only clear the text of the search bar (which is the default implementation) but to also clear some other stuff from my interface, but calling one of my own methods.
I can't find anything in the docs for the UISearchBar class or the UISearchBarDelegate protocol - it doesn't look like you can directly get access to this behaviour.
The one thing I did note was that the docs explained that the delegate method:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText;
is called after the clear button is tapped.
I initially wrote some code in that method that checked the search bar's text property, and if it was empty, then it had been cleared and to do all my other stuff.
Two problems which this though:
Firstly, for some reason I cannot fathom, even though I tell the search bar to resignFirstResponder at the end of my method, something, somewhere is setting it back to becomeFirstResponder. Really annoying...
Secondly, if the user doesn't use the clear button, and simply deletes the text in the bar using the delete button on the keyboard, this method is fired off and their search results go away. Not good.
Any advice or pointers in the right direction would be great!
Thanks!
Found the better solution for this problem :)
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
if ([searchText length] == 0) {
[self performSelector:#selector(hideKeyboardWithSearchBar:) withObject:searchBar afterDelay:0];
}
}
- (void)hideKeyboardWithSearchBar:(UISearchBar *)searchBar{
[searchBar resignFirstResponder];
}
The answer which was accepted is incorrect. This can be done, I just figured it out and posted it in another question:
UISearchbar clearButton forces the keyboard to appear
Best
I've got this code in my app. Difference is that I don't support 'live search', but instead start searching when the user touches the search button on the keyboard:
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
if ([searchBar.text isEqualToString:#""]) {
//Clear stuff here
}
}
Swift version handling close keyboard on clear button click :
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.characters.count == 0 {
performSelector("hideKeyboardWithSearchBar:", withObject:searchBar, afterDelay:0)
}
}
func hideKeyboardWithSearchBar(bar:UISearchBar) {
bar.resignFirstResponder()
}
You could try this:
- (void)viewDidLoad
{
[super viewDidLoad];
for (UIView *view in searchBar.subviews){
for (UITextField *tf in view.subviews) {
if ([tf isKindOfClass: [UITextField class]]) {
tf.delegate = self;
break;
}
}
}
}
- (BOOL)textFieldShouldClear:(UITextField *)textField {
// your code
return YES;
}
I would suggest using the rightView and rightViewMode methods of UITextField to create your own clear button that uses the same image. I'm assuming of course that UISearchBar will let you access the UITextField within it. I think it will.
Be aware of this from the iPhone OS Reference Library:
If an overlay view overlaps the clear button, however, the clear button always takes precedence in receiving events. By default, the right overlay view does overlap the clear button.
So you'll probably also need to disable the original clear button.
Since this comes up first, and far as I can see the question wasn't really adequately addressed, I thought I'd post my solution.
1) You need to get a reference to the textField inside the searchBar
2) You need to catch that textField's clear when it fires.
This is pretty simple. Here's one way.
a) Make sure you make your class a , since you will be using the delegate method of the textField inside the searchBar.
b) Also, connect your searchBar to an Outlet in your class. I just called mine searchBar.
c) from viewDidLoad you want to get ahold of the textField inside the searchBar. I did it like this.
UITextField *textField = [self.searchBar valueForKey:#"_searchField"];
if (textField) {
textField.delegate = self;
textField.tag = 1000;
}
Notice, I assigned a tag to that textField so that I can grab it again, and I made it a textField delegate. You could have created a property and assigned this textField to that property to grab it later, but I used a tag.
From here you just need to call the delegate method:
-(BOOL)textFieldShouldClear:(UITextField *)textField {
if (textField.tag == 1000) {
// do something
return YES;
}
return NO;
}
That's it. Since you are referring to a private valueForKey I can't guarantee that it will not get you into trouble.
Best solution from my experience is just to put a UIButton (with clear background and no text) above the system clear button and than connect an IBAction
- (IBAction)searchCancelButtonPressed:(id)sender {
[self.searchBar resignFirstResponder];
self.searchBar.text = #"";
// some of my stuff
self.model.fastSearchText = nil;
[self.model fetchData];
[self reloadTableViewAnimated:NO];
}
Wasn't able to find a solution here that didn't use a private API or wasn't upgrade proof incase Apple changes the view structure of the UISearchBar. Here is what I wrote that works:
- (void)viewDidLoad {
[super viewDidLoad];
UITextField* textfield = [self findTextFieldInside:self.searchBar];
[textfield setDelegate:self];
}
- (UITextField*)findTextFieldInside:(id)mainView {
for (id view in [mainView subviews]) {
if ([view isKindOfClass:[UITextField class]]) {
return view;
}
id subview = [self findTextFieldInside:view];
if (subview != nil) {
return subview;
}
}
return nil;
}
Then implement the UITextFieldDelegate protocol into your class and overwrite the textFieldShouldClear: method.
- (BOOL)textFieldShouldClear:(UITextField*)textField {
// Put your code in here.
return YES;
}
Edit: Setting the delegate on the textfield of a search bar in iOS8 will produce a crash. However it looks like the searchBar:textDidChange: method will get called on iOS8 on clear.

Set First Responder in MFMailComposeViewController?

I'm using Apple's MailComposer example application to send email from within my application (OS 3.0 functionality). Is it possible to set the To, Subject, or Body fields as first responder with MFMailComposeViewController?
In other words, the behavior would be: the user presses a button which presents the mail view (presentModalViewController). When the mail view is presented, the cursor is placed in one of the fields and the keyboard opens.
I notice the MFMailComposeViewController documentation says:
"Important: The mail composition interface itself is not customizable and must not be modified by your application. In addition, after presenting the interface, your application is not allowed to make further changes to the email content. The user may still edit the content using the interface, but programmatic changes are ignored. Thus, you must set the values of content fields before presenting the interface."
However, I don't care about customizing the interface. I just want to set that firstResponder. Any ideas?
You are able to make these fields become the first responder.
if you add the following method to your class...
//Returns true if the ToAddress field was found any of the sub views and made first responder
//passing in #"MFComposeSubjectView" as the value for field makes the subject become first responder
//passing in #"MFComposeTextContentView" as the value for field makes the body become first responder
//passing in #"RecipientTextField" as the value for field makes the to address field become first responder
- (BOOL) setMFMailFieldAsFirstResponder:(UIView*)view mfMailField:(NSString*)field{
for (UIView *subview in view.subviews) {
NSString *className = [NSString stringWithFormat:#"%#", [subview class]];
if ([className isEqualToString:field])
{
//Found the sub view we need to set as first responder
[subview becomeFirstResponder];
return YES;
}
if ([subview.subviews count] > 0) {
if ([self setMFMailFieldAsFirstResponder:subview mfMailField:field]){
//Field was found and made first responder in a subview
return YES;
}
}
}
//field not found in this view.
return NO;
}
Then, after you present the MFMailComposeViewController, pass the MFMailComposeViewController's view into the function along with the field you want to become first responder.
MFMailComposeViewController *mailComposer = [[MFMailComposeViewController alloc] init];
mailComposer.mailComposeDelegate = self;
/*Set up the mail composer*/
[self presentModalViewController:mailComposer animated:YES];
[self setMFMailFieldAsFirstResponder:mailComposer.view mfMailField:#"RecipientTextField"];
[mailComposer release];
In iOS 6, it is no longer possible to set first responder on any of the text fields AFAICT. Navigating the view hierarchy eventually reveals a UIRemoteView and the subviews within here are obfuscated away.
You can try just calling becomeFirstResponder on the controller itself. If that doesn't work, you can try in the debugger getting the list of subviews of the mail compose view until you find a familiar textfield or textview which you can then code specifically to set the responder status in code, which might look something like this (i don't know if this will work but it's an example):
[[[[mailcomposer.view.subviews objectAtIndex:3] subviews] objectAtIndex:2] becomeFirstResponder]
I like to simplify the code and make it easy to understand.
Just put the follow code after:
[self presentModalViewController:mailComposer animated:YES];
for (UIView *subview in mailComposer.view.subviews) {
NSString *className = [NSString stringWithFormat:#"%#", [subview class]];
//NSLog(#"%#", className); // list the views - Use this to find another view
//The view I want to set as first responder: "_MFMailRecipientTextField"
if ([className isEqualToString:#"_MFMailRecipientTextField"]){
[subview becomeFirstResponder];
break; // Stop search.
}
}