Skip to content

Commit

Permalink
Added IQKeyboardReturnKeyHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
hackiftekhar committed Aug 28, 2014
1 parent 6efa523 commit c1e185b
Show file tree
Hide file tree
Showing 7 changed files with 311 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//
// IQKeyboardReturnKeyHandler.h
// https://github.com/hackiftekhar/IQKeyboardManager
// Copyright (c) 2013-14 Iftekhar Qurashi.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#import <Foundation/NSObject.h>
#import "IQKeyboardManagerConstants.h"

#import <UIKit/UITextInputTraits.h>

@class UITextField,UIView;

@interface IQKeyboardReturnKeyHandler : NSObject

/*!
@method initWithViewController
@abstract Add all the textFields available in UIViewController's view.
*/
-(id)initWithViewController:(UIViewController*)controller;

/*!
@property toolbarManageBehaviour
@abstract It help to choose the lastTextField instance from sibling responderViews. Default is IQAutoToolbarBySubviews.
*/
@property(nonatomic, assign) IQAutoToolbarManageBehaviour toolbarManageBehaviour;

/*!
@property lastTextFieldReturnKeyType
@abstract Set the last textfield return key type. Default is UIReturnKeyDefault.
*/
@property(nonatomic, assign) UIReturnKeyType lastTextFieldReturnKeyType;

/*!
@method addTextFieldView
@abstract Should pass UITextField/UITextView intance. Assign textFieldView delegate to self, change it's returnKeyType.
*/
-(void)addTextFieldView:(UIView*)textFieldView;

/*!
@method removeTextFieldView
@abstract Should pass UITextField/UITextView intance. Restore it's textFieldView delegate and it's returnKeyType.
*/
-(void)removeTextFieldView:(UIView*)textFieldView;

/*!
@method addResponderFromView
@abstract Add all the UITextField/UITextView responderView's.
*/
-(void)addResponderFromView:(UIView*)view;

/*!
@method removeResponderFromView
@abstract Remove all the UITextField/UITextView responderView's.
*/
-(void)removeResponderFromView:(UIView*)view;

@end
189 changes: 189 additions & 0 deletions KeyboardTextFieldDemo/IQKeyBoardManager/IQKeyboardReturnKeyHandler.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
//
// IQKeyboardReturnKeyHandler.m
// https://github.com/hackiftekhar/IQKeyboardManager
// Copyright (c) 2013-14 Iftekhar Qurashi.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#import "IQKeyboardReturnKeyHandler.h"

#import "IQUIView+Hierarchy.h"
#import "IQNSArray+Sort.h"

#import <Foundation/NSSet.h>

#import <UIKit/UITextField.h>
#import <UIKit/UITextView.h>
#import <UIKit/UITableView.h>

NSString *const kIQTextField = @"kIQTextField";
NSString *const kIQTextFieldDelegate = @"kIQTextFieldDelegate";
NSString *const kIQTextFieldReturnKeyType = @"kIQTextFieldReturnKeyType";


@interface IQKeyboardReturnKeyHandler ()<UITextFieldDelegate,UITextViewDelegate>

@end

@implementation IQKeyboardReturnKeyHandler
{
NSMutableSet *textFieldInfoCache;
}


-(id)initWithViewController:(UIViewController*)controller
{
self = [super init];

if (self)
{
textFieldInfoCache = [[NSMutableSet alloc] init];
[self addResponderFromView:controller.view];
}

return self;
}

-(NSDictionary*)textFieldCachedInfo:(UITextField*)textField
{
for (NSDictionary *infoDict in textFieldInfoCache)
if ([infoDict objectForKey:kIQTextField] == textField) return infoDict;

return nil;
}

#pragma mark - Add/Remove TextFields
-(void)addResponderFromView:(UIView*)view
{
NSArray *textFields = [view deepResponderViews];

for (UITextField *textField in textFields) [self addTextFieldView:textField];
}

-(void)removeResponderFromView:(UIView*)view
{
NSArray *textFields = [view deepResponderViews];

for (UITextField *textField in textFields) [self removeTextFieldView:textField];
}

-(void)removeTextFieldView:(UITextField*)textField
{
NSDictionary *dict = [self textFieldCachedInfo:textField];

if (dict)
{
textField.keyboardType = [[dict objectForKey:kIQTextFieldReturnKeyType] integerValue];
textField.delegate = [dict objectForKey:kIQTextFieldDelegate];
[textFieldInfoCache removeObject:textField];
}
}

-(void)addTextFieldView:(UITextField*)textField
{
NSMutableDictionary *dictInfo = [[NSMutableDictionary alloc] init];

[dictInfo setObject:textField forKey:kIQTextField];
[dictInfo setObject:[NSNumber numberWithInteger:[textField returnKeyType]] forKey:kIQTextFieldReturnKeyType];
if (textField.delegate) [dictInfo setObject:textField.delegate forKey:kIQTextFieldDelegate];

//Adding return key as Next
{
UITableView *tableView = [textField superTableView];

//If there is a tableView in view's hierarchy, then fetching all it's subview that responds, Otherwise fetching all the siblings.
NSArray *textFields = (tableView) ? [tableView deepResponderViews] : [textField responderSiblings];

//If needs to sort it by tag
if (_toolbarManageBehaviour == IQAutoToolbarByTag) textFields = [textFields sortedArrayByTag];

//If it's the last textField in responder view, else next
textField.returnKeyType = ([textFields lastObject] == textField) ? self.lastTextFieldReturnKeyType : UIReturnKeyNext;
}

[textField setDelegate:self];
[textFieldInfoCache addObject:dictInfo];
}

#pragma mark - Overriding lastTextFieldReturnKeyType
-(void)setLastTextFieldReturnKeyType:(UIReturnKeyType)lastTextFieldReturnKeyType
{
_lastTextFieldReturnKeyType = lastTextFieldReturnKeyType;

for (NSDictionary *infoDict in textFieldInfoCache)
{
UITextField *textField = [infoDict objectForKey:kIQTextField];

UITableView *tableView = [textField superTableView];

//If there is a tableView in view's hierarchy, then fetching all it's subview that responds, Otherwise fetching all the siblings.
NSArray *textFields = (tableView) ? [tableView deepResponderViews] : [textField responderSiblings];

//If needs to sort it by tag
if (_toolbarManageBehaviour == IQAutoToolbarByTag) textFields = [textFields sortedArrayByTag];

//If it's the last textField in responder view, else next
textField.returnKeyType = ([textFields lastObject] == textField) ? self.lastTextFieldReturnKeyType : UIReturnKeyNext;
}
}

#pragma mark - Goto next or Resign.

-(void)goToNextResponderOrResign:(UIView*)textField
{
UITableView *tableView = [textField superTableView];

//If there is a tableView in view's hierarchy, then fetching all it's subview that responds, Otherwise fetching all the siblings.
NSArray *textFields = (tableView) ? [tableView deepResponderViews] : [textField responderSiblings];

//If needs to sort it by tag
if (_toolbarManageBehaviour == IQAutoToolbarByTag) textFields = [textFields sortedArrayByTag];

if ([textFields containsObject:textField])
{
//Getting index of current textField.
NSUInteger index = [textFields indexOfObject:textField];

//If it is not last textField. then it's next object becomeFirstResponder.
(index < textFields.count-1) ? [[textFields objectAtIndex:index+1] becomeFirstResponder] : [textField resignFirstResponder];
}
}

#pragma mark - TextField delegate
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[self goToNextResponderOrResign:textField];

return YES;
}

#pragma mark - TextView delegate
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if ([text isEqualToString:@"\n"])
{
[self goToNextResponderOrResign:textView];

return NO;
}

return YES;
}

@end
10 changes: 10 additions & 0 deletions KeyboardTextFieldDemo/IQKeyboard.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@
9DFD564E18BCAA26001007A2 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0B63BA31781FAB1008D3B64 /* CoreGraphics.framework */; };
AF4301BA179E92C400FADAC6 /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = AF4301B9179E92C400FADAC6 /* [email protected] */; };
AFF236C117CA224400760F6C /* IQKeyboardManager.m in Sources */ = {isa = PBXBuildFile; fileRef = AFF236BE17CA224400760F6C /* IQKeyboardManager.m */; };
C05BE5E519AF97E2000B332C /* IQKeyboardReturnKeyHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = C05BE5E319AF97E2000B332C /* IQKeyboardReturnKeyHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
C05BE5E619AF97E2000B332C /* IQKeyboardReturnKeyHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = C05BE5E419AF97E2000B332C /* IQKeyboardReturnKeyHandler.m */; };
C05BE5E719AF97E2000B332C /* IQKeyboardReturnKeyHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = C05BE5E419AF97E2000B332C /* IQKeyboardReturnKeyHandler.m */; };
C07E20B51858FF54001699A8 /* ScrollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C07E20B41858FF54001699A8 /* ScrollViewController.m */; };
C07E20BE18590085001699A8 /* WebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C07E20BA18590085001699A8 /* WebViewController.m */; };
C07E20C3185900BD001699A8 /* TextFieldViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C07E20C1185900BD001699A8 /* TextFieldViewController.m */; };
Expand Down Expand Up @@ -143,6 +146,8 @@
AFF236BD17CA224400760F6C /* IQKeyboardManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IQKeyboardManager.h; sourceTree = "<group>"; };
AFF236BE17CA224400760F6C /* IQKeyboardManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IQKeyboardManager.m; sourceTree = "<group>"; };
C00EAA6B1858D5A500968DE2 /* ScrollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollViewController.h; sourceTree = "<group>"; };
C05BE5E319AF97E2000B332C /* IQKeyboardReturnKeyHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IQKeyboardReturnKeyHandler.h; sourceTree = "<group>"; };
C05BE5E419AF97E2000B332C /* IQKeyboardReturnKeyHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IQKeyboardReturnKeyHandler.m; sourceTree = "<group>"; };
C07E20B41858FF54001699A8 /* ScrollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScrollViewController.m; sourceTree = "<group>"; };
C07E20B918590085001699A8 /* WebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewController.h; sourceTree = "<group>"; };
C07E20BA18590085001699A8 /* WebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewController.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -305,6 +310,8 @@
9D0BB88518BB293D00667349 /* IQNSArray+Sort.h */,
9D0BB88618BB293D00667349 /* IQNSArray+Sort.m */,
9D94D34018D1811000CE5ED0 /* KeyboardManager.h */,
C05BE5E319AF97E2000B332C /* IQKeyboardReturnKeyHandler.h */,
C05BE5E419AF97E2000B332C /* IQKeyboardReturnKeyHandler.m */,
);
path = IQKeyBoardManager;
sourceTree = "<group>";
Expand Down Expand Up @@ -396,6 +403,7 @@
9D94D34118D1811000CE5ED0 /* KeyboardManager.h in Headers */,
9DF8A9E118BB5ED8008E93B8 /* IQKeyboardManager.h in Headers */,
9DF8A9E918BB5ED8008E93B8 /* IQKeyboardManagerConstants.h in Headers */,
C05BE5E519AF97E2000B332C /* IQKeyboardReturnKeyHandler.h in Headers */,
9DF8A9E718BB5ED8008E93B8 /* IQSegmentedNextPrevious.h in Headers */,
9D18420A18C7015A00CF17FF /* IQTextView.h in Headers */,
9DF8A9EA18BB5ED8008E93B8 /* IQUIView+IQKeyboardToolbar.h in Headers */,
Expand Down Expand Up @@ -577,6 +585,7 @@
9DF8A9EF18BB5ED8008E93B8 /* IQUIWindow+Hierarchy.m in Sources */,
9DF8A9F118BB5ED8008E93B8 /* IQNSArray+Sort.m in Sources */,
9D18420C18C7015A00CF17FF /* IQTextView.m in Sources */,
C05BE5E719AF97E2000B332C /* IQKeyboardReturnKeyHandler.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -606,6 +615,7 @@
9D0BB88718BB293D00667349 /* IQNSArray+Sort.m in Sources */,
9D0BB88418BB261500667349 /* IQUIWindow+Hierarchy.m in Sources */,
9D03F06F18BDC19400F4970D /* SpecialCaseViewController.m in Sources */,
C05BE5E619AF97E2000B332C /* IQKeyboardReturnKeyHandler.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Loading

0 comments on commit c1e185b

Please sign in to comment.