0

How can I get the textfield in this method to call textfieldshouldreturn? I'm guessing its not working beause the UIView doesn't have a delegate property, but I'm not sure how to make a UIView I've created within a method conform to a protocol. I've seen several posts regarding delegation but everything I've tried hasn't worked. I'm sure its something simple. Thanks in advance.

- (void) launchCreateNewListActionSheet{
    self.listActionSheet= [[UIActionSheet alloc] initWithTitle:@"Create A New List"
                                                  delegate:self
                                         cancelButtonTitle:nil
                                    destructiveButtonTitle:nil
                                         otherButtonTitles:nil];

    UIView *addToNewList = [[UIView alloc] initWithFrame:CGRectMake(0, 44, 320, 464)];
    addToNewList.backgroundColor = [UIColor whiteColor];

    UILabel *addToNewListLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 23, 100, 20)];
    addToNewListLabel.text = @"List Name: ";

    UITextField *enterNewListName = [[UITextField alloc] initWithFrame:CGRectMake(100, 20, 180, 30)];
    enterNewListName.layer.borderWidth = 1;
    enterNewListName.layer.borderColor = [[UIColor blackColor] CGColor];
    enterNewListName.delegate = self;

    [addToNewList addSubview:addToNewListLabel];
    [addToNewList addSubview:enterNewListName];


    UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc]     initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(addToExistingList)];

    UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelListPicker)];

    UIBarButtonItem *fixedCenter = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
fixedCenter.width = 180.0f;

    UIToolbar* toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
    toolbar.barStyle = UIBarStyleBlackOpaque;
    [toolbar sizeToFit];

    [toolbar setItems:@[cancelBtn, fixedCenter, doneBtn] animated:YES];

    [self.listActionSheet addSubview:toolbar];
    [self.listActionSheet addSubview:addToNewList];
    [self.listActionSheet showInView:self.view];
    [self.listActionSheet setBounds:CGRectMake(0,0,320, 464)];
} 

Here is my .h file. I have implemented as it is working for text fields in other methods.

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "ZBarSDK.h"
#import "ProgressView.h"

@class ScannerViewController;

@protocol ScanViewDelegate <NSObject>;
@required
-(void)postURL:(NSURL*)url selectedAction:(NSString*)action;
@end

@interface ScannerViewController : UIViewController <ZBarReaderViewDelegate,        UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate, UIWebViewDelegate,    UIPickerViewDelegate, UIActionSheetDelegate>

    id <ScanViewDelegate> delegate;
}
@property (weak, nonatomic) IBOutlet ZBarReaderView *readerView;
@property (weak, nonatomic) IBOutlet UITableView *scannerList;
@property (retain) id delegate;

@property (strong) NSMutableArray* barCodeArray;
@property (strong) NSMutableArray* quantityArray;
@property (strong) NSURL* url;
@property (strong) NSString* action;
@property NSString *listItems;
@property NSString *listItemNames;
@property NSArray *listItemNamesArray;
@property NSArray *hrefArray;
@property int pickerViewRow;
@property (strong) UIWebView *webView;
@property (strong) ProgressView* loading;
@property BOOL isLoading;
@property (strong) UITextField *enterNewListName;
@property (strong) UITextField *addToNewListDescription;
@property (strong) NSMutableArray *textFieldArray;

-(IBAction)sendToCart:(id)sender;
-(IBAction)sendToList:(id)sender;
-(void)startLoadingURL;
@end

Here is the textfieldshouldreturn method:

-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
    if([self.textFieldArray containsObject:textField])
    {
        NSUInteger index = [self.textFieldArray indexOfObject:textField];
        NSNumber *newQuantity = [NSNumber numberWithInteger:[textField.text integerValue]];
        [self.quantityArray replaceObjectAtIndex:index withObject:newQuantity];
        NSLog(@"Your new quantity is: %@", newQuantity);
    }
    [textField resignFirstResponder];
    return YES;
}

4 Answers4

2

The key point here is that Andres would like to use UiTextField on an UIActionSheet. UIActionSheet has a little bit different behaviour eating taps, actually it prevents a healthy use of UiTextField added to the actionsheet.

Please see this SO answer where it was found that using a custom solution is better: keyboard in UIActionSheet does not type anything

Basically it is better to use UIAlertView for a modal text input view form (please see this link) a custom view imitating UIActionSheet with more space for customisation (search eg. github as a starting point) but there's one solution for UIActionSheet too.

In order to place the UITextField in the view hierarchy where UIActionSheet doesn't steel pushes use after showing the UIActionSheet this code snippet:

    [self.listActionSheet addSubview:toolbar];
    // [self.listActionSheet addSubview:addToNewList];  // please comment-delete this line
    [self.listActionSheet showInView:self.view];
    [self.listActionSheet setBounds:CGRectMake(0,0,320, 464)];
    // this is the 2 new lines below
    UIWindow *appWindow = [UIApplication sharedApplication].keyWindow;
    [appWindow insertSubview:addToNewList aboveSubview:listActionSheet];  // you add custom view here
Community
  • 1
  • 1
nzs
  • 3,252
  • 17
  • 22
  • So - question for poster - does the code generate a UITextField that actually accepts the selection / become first responder. If not, then it's not surprise it doesn't send its delegate any messages. Can original poster comment. – Obliquely Jul 15 '13 at 17:49
  • Hmmm...this might be the problem. So do you mean my enterNewListName.becomeFirstResponder = YES? No, I haven't done that. I just tried it and it's telling me no setter method for setBecomeFirstResponder for assignment to property. – Andres Quesada Jul 15 '13 at 17:57
  • I tried your code now and found a solution. To place your texfield in the view hierarchy in order to force uiactionsheet not stealing pushes you have to do that AFTER showing the uialerview : UIWindow *appWindow = [UIApplication sharedApplication].keyWindow; [appWindow insertSubview:addToNewList aboveSubview:listActionSheet]; – nzs Jul 15 '13 at 18:12
  • I will update my answer.. it works for me but I had to modify alerview's frame in order to see textfield (keyboard hides it for me in simulator) – nzs Jul 15 '13 at 18:12
  • Yes I noticed the keyboard was being hidden when I resized the actionsheet. – Andres Quesada Jul 15 '13 at 18:15
  • If you adjust the listActionSheet's frame after setbounds you can see the texfield (as you probably already know :) – nzs Jul 15 '13 at 18:23
  • The author of that link uses private methods that will not be accepted in the app store. Also, the other method show the View at the Top of the screen now instead of inside the action sheet – Andres Quesada Jul 15 '13 at 18:57
  • Haven't tested but you can adjust addToNewList's frame to perfectly fit into actionsheet's layout. I will check in detail the link I provided and modify my SO answer properly. – nzs Jul 15 '13 at 19:36
0

Have you enabled the respective class to be compatible with UITextFieldDelegate?

Please goto the .h file of the current class, and make it compatible to UITextFieldDelegate.

Eg: If your ClassName is HomeController

I am assuming you are getting a warning something similar to this:

Assigning to id<UITextFieldDelegate> from incompatible type "HomeController"

Solution:

@interface HomeController : UIViewController <UITextFieldDelegate>
    // YOur Class Variable.
@end
Roshit
  • 1,589
  • 1
  • 15
  • 37
0

First of all if your class doesn't conform to a protocol that has methods required it will generate a warning at the line that sets the delegate to be the class.

Nwo, if you want to make a custom class a delegate of a UITextField you will have to declare that and implement the required method. In your case you have to do the following:

In YourCustomView.h

@interface YourCustomView : UIView (or other class) <UITextFieldDelegate> // this will show that this class conforms to UITextFieldDelegate protocol
//other methods or properties here
@end

In YourCustomView.m

@implementation YourCustomView 

-(void)launchCreateNewListActionSheet {
   //some code here 
    UITextField *textField = //alloc init methd
    textField.delegate = self;
}

#pragma mark - UITextFieldDelegate //this is optional only if you want to structure the code
- (BOOL)textFieldShouldReturn:(UITextField *)textField { 
     //method called when the text field resign first responder
}

//and you can add more delegate methods depending on your needs. @end

danypata
  • 9,895
  • 1
  • 31
  • 44
0

Your UIView does not need delegate property. It just needs to implement the UITextField delegate methods. They are all optional, so the compiler won't complain if you don't implement them.

Your code looks OK. But to see if things are hooked up right implement textFieldDidBeginEditing: in your UIView subclass to generate a log and see if the log comes up when you select your text field.

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
   NSLog(@"textFieldDidBeginEditing: %@ (delegate: %@)", textField, [textField delegate]);
}

If that works fine then log on textFieldShouldReturn: etc. If that doesn't work, then something has gone awry elsewhere. The code you've posted looks OK on quick glance.

Obliquely
  • 7,002
  • 2
  • 32
  • 51