简体   繁体   English

目标C:全局方法textField

[英]Objective C : global methods textField

Is there any way to make the following methods "global": 有没有什么办法让下面的方法“环球”:

- (void)textFieldDidBeginEditing:(UITextField *)textField{
     //some code here
}
- (void)textFieldDidEndEditing:(UITextField *)textField{
     //some code here
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
     //some code here
}

I explain, I have an Objective-C Project with ARC and Storyboard on and each of my views have their own View Controller Class. 我解释一下,我有ARC和故事板的Objective-C的项目和我的每一个观点都有自己的视图控制器类。 There is a lot of text field in my project and sometimes when the user start edit, the keyboard is hiding content. 有很多文本字段的在我的项目,有时,当用户开始编辑,键盘是隐藏的内容。 So I search on the web to find a way to handle this problem. 因此,我在网上搜索以找到解决此问题的方法。 The answer of this topic: Scrolling content hidden by keyboard. 本主题的答案: 滚动隐藏在键盘上的内容。 xcode 4.3.2 helped me a lot and it's working, it scrolls content so the user is always able to see the bottom of the view. xcode 4.3.2对我有很多帮助,它可以正常工作,它可以滚动内容,因此用户始终可以看到视图的底部。

But now here is my problem, I would like to make this functionnality (content scrolling when start editing) be active every where on my projet. 但是现在这是我的问题,我想使此功能(开始编辑时的内容滚动)在我的投影机上的每个位置都有效。 The unoptimized solution would be to copy the code in each of my views classes. 未优化的解决方案是将代码复制到我的每个视图类中。 But I am wondering if there is any way to import a class that contain thoses methods or something. 但我想知道是否有任何方法可以导入包含这些方法或某些内容的类。

My actual code is almost the same as here (answer): Scrolling content hidden by keyboard. 我的实际代码与此处(答案)几乎相同: 滚动隐藏在键盘上的内容。 xcode 4.3.2 xcode 4.3.2

I hope there is some Objective-C guru somewhere that could help me with my trouble. 我希望在某个地方可以找到一些Objective-C专家,可以帮助我解决我的麻烦。

-EDIT- -编辑-

Each of my views in Storyboard has his own UIViewControllerClass. 我的每个故事板中的观点有他自己的UIViewControllerClass。 Each of these with TextField have this code: 每个带有TextField的代码都具有以下代码:

VCExample.h VCExample.h

@interface VCExample : UIViewController

@property (weak, nonatomic) IBOutlet UITextField *oneTextField;

@end

VCExample.m 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 TextFieldScroll.h

#import <Foundation/Foundation.h>

@interface TextFieldScroll : NSObject <UITextFieldDelegate>

+ (id)shared;

@property CGFloat animatedDistance;

@end

TextFieldScroll.m 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;
}

The best way to do this would be to create a base class for all your view controllers that implements these methods with the keyboard animation code. 最好的方法是为所有视图控制器创建一个基类,该基类使用键盘动画代码实现这些方法。 Turn your existing view controllers into subclasses of that base class, and send the appropriate message to super in the subclasses' implementations of these methods. 将现有的视图控制器转换为该基类的子类,并向这些方法的子类的实现中的super发送适当的消息。

Yes, technically you could make these methods global. 是的,从技术上讲,您可以将这些方法设置为全局方法。 This is how I would do it: 这就是我要做的:

  1. Create a singleton NSObject subclass that responds to UITextFieldDelegate messages. 创建一个响应UITextFieldDelegate消息的单例NSObject子类。

    The code for MyTextFieldHandler.h file: MyTextFieldHandler.h文件的代码:

     @interface MyTextFieldHandler : NSObject + (id)shared; @end 

    The code for MyTextFieldHandler.m file: MyTextFieldHandler.m文件的代码:

     + (id)shared { static MyTextFieldHandler *sharedMyTextFieldHandler = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^ { sharedMyTextFieldHandler = [[self alloc] init]; }); return sharedMyTextFieldHandler; } 
  2. Set all UITextField delegates to this object. 将所有UITextField委托设置为此对象。

Write all the code that needs to be done when those messages are sent in the suclass. 编写在suclass中发送这些消息时需要完成的所有代码。

There are more ways to do the step 2. 有更多方法可以执行步骤2。

  1. One could simply set for all UITextField objects: 只需为所有UITextField对象设置一个即可:

     specificTextField.delegate = [MyTextFieldHandler shared]; anotherSpecificTextField.delegate = [MyTextFieldHandler shared]; 
  2. Another way would be subclassing the UITextField and override awakeFromNib and initWithFrame: methods, which would now set the delegate with: 另一种方法是将UITextField子类化,并覆盖awakeFromNib和initWithFrame:方法,这将通过以下方式设置委托:

     self.delegate = [MyTextFieldHandler shared]; 
  3. The third way would be the hardest, but would not require any additional code for new UITextField added. 第三种方法将是最困难的,但是不需要为添加的新UITextField添加任何其他代码。 You could swizzle any of the UITextField methods to set the delegate to singleton. 您可以修改任何UITextField方法以将委托设置为单例。 Read this post from Mattt Thompson about method swizzling: http://nshipster.com/method-swizzling/ 阅读Mattt Thompson撰写的有关方法混乱的帖子: http ://nshipster.com/method-swizzling/

Which way is the best? 哪种方法最好? Depends on your needs and what do you want to do. 取决于您的需求以及您想做什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM