[英]Objective C : global methods textField
有没有什么办法让下面的方法“环球”:
- (void)textFieldDidBeginEditing:(UITextField *)textField{
//some code here
}
- (void)textFieldDidEndEditing:(UITextField *)textField{
//some code here
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
//some code here
}
我解释一下,我有ARC和故事板的Objective-C的项目和我的每一个观点都有自己的视图控制器类。 有很多文本字段的在我的项目,有时,当用户开始编辑,键盘是隐藏的内容。 因此,我在网上搜索以找到解决此问题的方法。 本主题的答案: 滚动隐藏在键盘上的内容。 xcode 4.3.2对我有很多帮助,它可以正常工作,它可以滚动内容,因此用户始终可以看到视图的底部。
但是现在这是我的问题,我想使此功能(开始编辑时的内容滚动)在我的投影机上的每个位置都有效。 未优化的解决方案是将代码复制到我的每个视图类中。 但我想知道是否有任何方法可以导入包含这些方法或某些内容的类。
我的实际代码与此处(答案)几乎相同: 滚动隐藏在键盘上的内容。 xcode 4.3.2
我希望在某个地方可以找到一些Objective-C专家,可以帮助我解决我的麻烦。
-编辑-
我的每个故事板中的观点有他自己的UIViewControllerClass。 每个带有TextField的代码都具有以下代码:
VCExample.h
@interface VCExample : UIViewController
@property (weak, nonatomic) IBOutlet UITextField *oneTextField;
@end
VCExample.m
#import "VCExample.h"
#import "TextFieldScroll.h"
@interface VCExample ()
@end
@implementation VCExample
- (void)viewDidLoad
{
[super viewDidLoad];
TextFieldScroll *myTextFieldClass = [[TextFieldScroll alloc] init];
[self.usernameTextField setDelegate: myTextFieldClass];
self.usernameTextField.delegate = [TextFieldScroll shared];
}
@end
TextFieldScroll.h
#import <Foundation/Foundation.h>
@interface TextFieldScroll : NSObject <UITextFieldDelegate>
+ (id)shared;
@property CGFloat animatedDistance;
@end
TextFieldScroll.m
#import "TextFieldScroll.h"
@implementation TextFieldScroll
@synthesize animatedDistance;
static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162;
+ (id)shared
{
static TextFieldScroll *sharedMyTextFieldHandler = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
sharedMyTextFieldHandler = [[self alloc] init];
});
return sharedMyTextFieldHandler;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGRect textFieldRect = [self.my.window convertRect:textField.bounds fromView:textField];
CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];
CGFloat midline = textFieldRect.origin.y + 0.5 * textFieldRect.size.height;
CGFloat numerator =
midline - viewRect.origin.y
- MINIMUM_SCROLL_FRACTION * viewRect.size.height;
CGFloat denominator =
(MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION)
* viewRect.size.height;
CGFloat heightFraction = numerator / denominator;
if (heightFraction < 0.0)
{
heightFraction = 0.0;
}
else if (heightFraction > 1.0)
{
heightFraction = 1.0;
}
UIInterfaceOrientation orientation =
[[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait ||
orientation == UIInterfaceOrientationPortraitUpsideDown)
{
animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
}
else
{
animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
}
CGRect viewFrame = self.view.frame;
viewFrame.origin.y -= animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
CGRect viewFrame = self.view.frame;
viewFrame.origin.y += animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
最好的方法是为所有视图控制器创建一个基类,该基类使用键盘动画代码实现这些方法。 将现有的视图控制器转换为该基类的子类,并向这些方法的子类的实现中的super
发送适当的消息。
是的,从技术上讲,您可以将这些方法设置为全局方法。 这就是我要做的:
创建一个响应UITextFieldDelegate
消息的单例NSObject子类。
MyTextFieldHandler.h文件的代码:
@interface MyTextFieldHandler : NSObject + (id)shared; @end
MyTextFieldHandler.m文件的代码:
+ (id)shared { static MyTextFieldHandler *sharedMyTextFieldHandler = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^ { sharedMyTextFieldHandler = [[self alloc] init]; }); return sharedMyTextFieldHandler; }
将所有UITextField
委托设置为此对象。
编写在suclass中发送这些消息时需要完成的所有代码。
有更多方法可以执行步骤2。
只需为所有UITextField对象设置一个即可:
specificTextField.delegate = [MyTextFieldHandler shared]; anotherSpecificTextField.delegate = [MyTextFieldHandler shared];
另一种方法是将UITextField子类化,并覆盖awakeFromNib和initWithFrame:方法,这将通过以下方式设置委托:
self.delegate = [MyTextFieldHandler shared];
第三种方法将是最困难的,但是不需要为添加的新UITextField添加任何其他代码。 您可以修改任何UITextField
方法以将委托设置为单例。 阅读Mattt Thompson撰写的有关方法混乱的帖子: http ://nshipster.com/method-swizzling/
哪种方法最好? 取决于您的需求以及您想做什么。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.