master
  1//
  2//  BlockTextPromptAlertView.m
  3//  BlockAlertsDemo
  4//
  5//  Created by Barrett Jacobsen on 2/13/12.
  6//  Copyright (c) 2012 Barrett Jacobsen. All rights reserved.
  7//
  8
  9#import "BlockTextPromptAlertView.h"
 10
 11#define kTextBoxHeight      31
 12#define kTextBoxSpacing     5
 13#define kTextBoxHorizontalMargin 12
 14
 15#define kKeyboardResizeBounce         20
 16
 17@interface BlockTextPromptAlertView()
 18@property(nonatomic, copy) TextFieldReturnCallBack callBack;
 19@end
 20
 21@implementation BlockTextPromptAlertView
 22@synthesize textField, callBack;
 23
 24
 25
 26+ (BlockTextPromptAlertView *)promptWithTitle:(NSString *)title message:(NSString *)message defaultText:(NSString*)defaultText {
 27    return [self promptWithTitle:title message:message defaultText:defaultText block:nil];
 28}
 29
 30+ (BlockTextPromptAlertView *)promptWithTitle:(NSString *)title message:(NSString *)message defaultText:(NSString*)defaultText block:(TextFieldReturnCallBack)block {
 31    return [[[BlockTextPromptAlertView alloc] initWithTitle:title message:message defaultText:defaultText block:block] autorelease];
 32}
 33
 34+ (BlockTextPromptAlertView *)promptWithTitle:(NSString *)title message:(NSString *)message textField:(out UITextField**)textField {
 35    return [self promptWithTitle:title message:message textField:textField block:nil];
 36}
 37
 38
 39+ (BlockTextPromptAlertView *)promptWithTitle:(NSString *)title message:(NSString *)message textField:(out UITextField**)textField block:(TextFieldReturnCallBack) block{
 40    BlockTextPromptAlertView *prompt = [[[BlockTextPromptAlertView alloc] initWithTitle:title message:message defaultText:nil block:block] autorelease];
 41    
 42    *textField = prompt.textField;
 43    
 44    return prompt;
 45}
 46
 47- (void)addComponents:(CGRect)frame {
 48    [super addComponents:frame];
 49    
 50    if (!self.textField) {
 51        UITextField *theTextField = [[UITextField alloc] initWithFrame:CGRectMake(kTextBoxHorizontalMargin, _height, frame.size.width - kTextBoxHorizontalMargin * 2, kTextBoxHeight)];
 52        
 53        [theTextField setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];
 54        [theTextField setAutocapitalizationType:UITextAutocapitalizationTypeWords];
 55        [theTextField setBorderStyle:UITextBorderStyleRoundedRect];
 56        [theTextField setTextAlignment:NSTextAlignmentCenter];
 57        [theTextField setClearButtonMode:UITextFieldViewModeAlways];
 58        
 59        theTextField.autoresizingMask = UIViewAutoresizingFlexibleWidth;
 60        
 61        theTextField.delegate = self;
 62        
 63        self.textField = theTextField;
 64    }
 65    else {
 66        self.textField.frame = CGRectMake(kTextBoxHorizontalMargin, _height, frame.size.width - kTextBoxHorizontalMargin * 2, kTextBoxHeight);
 67    }
 68    
 69    [_view addSubview:self.textField];
 70    _height += kTextBoxHeight + kTextBoxSpacing;
 71    
 72}
 73
 74- (id)initWithTitle:(NSString *)title message:(NSString *)message defaultText:(NSString*)defaultText {
 75    
 76    self = [super initWithTitle:title message:message];
 77    
 78    if (self) {
 79        maxLength = 0;
 80        buttonIndexForReturn = 1;
 81        
 82        [[NSNotificationCenter defaultCenter] addObserver:self
 83                                                 selector:@selector(keyboardWillShow:)
 84                                                     name:UIKeyboardWillShowNotification
 85                                                   object:nil];
 86        
 87        if ([self class] == [BlockTextPromptAlertView class])
 88            [self setupDisplay];
 89    }
 90    
 91    return self;
 92}
 93
 94- (id)initWithTitle:(NSString *)title message:(NSString *)message defaultText:(NSString*)defaultText block: (TextFieldReturnCallBack) block {
 95    
 96    self = [self initWithTitle:title message:message defaultText:defaultText];
 97    
 98    if (self) {
 99        self.callBack = block;
100    }
101    
102    return self;
103}
104
105- (void)show {
106    [[NSNotificationCenter defaultCenter] addObserver:self
107                                             selector:@selector(keyboardWillShow:)
108                                                 name:UIKeyboardWillShowNotification
109                                               object:nil];
110    
111    [super show];
112    
113    [[NSNotificationCenter defaultCenter] addObserver:textField selector:@selector(becomeFirstResponder) name:@"AlertViewFinishedAnimations" object:self];
114}
115
116- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated {
117    if (self.shouldDismiss) {
118        if (!self.shouldDismiss(buttonIndex, self))
119            return;
120    }
121    
122    [super dismissWithClickedButtonIndex:buttonIndex animated:animated];
123    
124    [self.textField resignFirstResponder];
125    
126    [[NSNotificationCenter defaultCenter] removeObserver:textField];
127    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
128}
129
130- (void)keyboardWillShow:(NSNotification *)notification {
131    CGFloat keyboardHeight = 0;
132    CGFloat animationDuration = 0.3;
133    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
134    
135    if(notification) {
136        NSDictionary* keyboardInfo = [notification userInfo];
137        CGRect keyboardFrame = [[keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
138        animationDuration = [[keyboardInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
139        
140        if(UIInterfaceOrientationIsPortrait(orientation))
141            keyboardHeight = keyboardFrame.size.height;
142        else
143            keyboardHeight = keyboardFrame.size.width;
144    }
145    
146    CGFloat screenHeight = 0;
147    
148    if(UIInterfaceOrientationIsPortrait(orientation))
149        screenHeight = [UIScreen mainScreen].bounds.size.height;
150    else
151        screenHeight = [UIScreen mainScreen].bounds.size.width;
152    
153    
154    __block CGRect frame = _view.frame;
155    
156    if (frame.origin.y + frame.size.height > screenHeight - keyboardHeight) {
157        
158        frame.origin.y = screenHeight - keyboardHeight - frame.size.height - 10;
159        
160        if (frame.origin.y < 0)
161            frame.origin.y = 0;
162        
163        _cancelBounce = YES;
164        
165        [UIView animateWithDuration:animationDuration
166                              delay:0.0
167                            options:UIViewAnimationCurveEaseOut | UIViewAnimationOptionBeginFromCurrentState
168                         animations:^{
169                             _view.frame = frame;
170                         }
171                         completion:nil];
172    }
173
174}
175
176
177- (void)setAllowableCharacters:(NSString*)accepted {
178    unacceptedInput = [[[NSCharacterSet characterSetWithCharactersInString:accepted] invertedSet] retain];
179    self.textField.delegate = self;
180}
181
182- (void)setUnacceptedInput:(NSCharacterSet*)charSet {
183    unacceptedInput = [charSet copy];
184}
185
186
187- (void)setMaxLength:(NSInteger)max {
188    maxLength = max;
189    self.textField.delegate = self;
190}
191
192- (void)setButtonIndexForReturn:(NSInteger)index {
193    buttonIndexForReturn = index;
194}
195
196-(BOOL)textFieldShouldReturn:(UITextField *)_textField{
197    if(callBack){
198        return callBack(self);
199    }
200    else {
201        [self dismissWithClickedButtonIndex:buttonIndexForReturn animated:YES];
202    }
203    return NO;
204}
205
206- (void)textFieldDidBeginEditing:(UITextField *)aTextField {
207    if (self.selectAllOnBeginEdit) {
208        [aTextField selectAll:self];
209    }
210}
211
212
213- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
214    
215    NSUInteger newLength = [self.textField.text length] + [string length] - range.length;
216    
217    if (maxLength > 0 && newLength > maxLength)
218        return NO;
219    
220    if (!unacceptedInput)
221        return YES;
222    
223    if ([[string componentsSeparatedByCharactersInSet:unacceptedInput] count] > 1)
224        return NO;
225    else 
226        return YES;
227}
228
229- (void)dealloc {
230    if (unacceptedInput)
231        [unacceptedInput release];
232    self.callBack = nil;
233    [super dealloc];
234}
235
236@end