【问题标题】:Objective C : global methods textField目标 C:全局方法 textField
【发布时间】:2014-03-30 19:55:29
【问题描述】:

有没有办法让以下方法“全局”:

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

我解释一下,我有一个带有 ARC 和 Storyboard 的 Objective-C 项目,我的每个视图都有自己的视图控制器类。我的项目中有很多文本字段,有时当用户开始编辑时,键盘会隐藏内容。所以我在网上搜索以找到解决此问题的方法。本主题的答案:Scrolling content hidden by keyboard. xcode 4.3.2 帮了我很多,它正在工作,它滚动内容,所以用户总是能够看到视图的底部。

但现在这是我的问题,我想让这个功能(开始编辑时滚动内容)在我的项目的每个地方都处于活动状态。未优化的解决方案是在我的每个视图类中复制代码。但我想知道是否有任何方法可以导入包含这些方法或其他内容的类。

我的实际代码和这里几乎一样(答案):Scrolling content hidden by keyboard. xcode 4.3.2

我希望某个地方有一些 Objective-C 大师可以帮助我解决问题。

-编辑-

我在 Storyboard 中的每个视图都有自己的 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;
}

【问题讨论】:

    标签: ios iphone objective-c storyboard textfield


    【解决方案1】:

    最好的方法是为所有视图控制器创建一个基类,使用键盘动画代码实现这些方法。将现有的视图控制器转换为该基类的子类,并在这些方法的子类实现中向super 发送适当的消息。

    【讨论】:

      【解决方案2】:

      是的,从技术上讲,您可以使这些方法全球化。我会这样做:

      1. 创建一个响应 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;
        }
        
      2. 将所有UITextField 委托设置为该对象。

      编写所有在子类中发送这些消息时需要完成的代码。

      第 2 步还有更多方法。

      1. 可以简单地为所有 UITextField 对象设置:

        specificTextField.delegate = [MyTextFieldHandler shared];
        anotherSpecificTextField.delegate = [MyTextFieldHandler shared];
        
      2. 另一种方法是将 UITextField 子类化并覆盖 awakeFromNib 和 initWithFrame: 方法,现在将委托设置为:

        self.delegate = [MyTextFieldHandler shared];
        
      3. 第三种方式是最难的,但不需要任何额外的代码来添加新的 UITextField。您可以调配任何UITextField 方法来将委托设置为单例。阅读 Mattt Thompson 关于方法调配的帖子:http://nshipster.com/method-swizzling/

      哪种方式最好?取决于你的需求和你想做什么。

      【讨论】:

      • 您好 Legoless,感谢您的快速答复。不幸的是,我尝试了您的建议,但目前没有得到任何结果。我还没有尝试步骤 2 的选项 3。如果您查看代码,您会看到对 self.view 的引用,我应该对代码进行哪些更改以使 self.view 引用文本字段的视图。 “共享”是什么意思?它不是本机 xcode。我也试过: TextFieldScroll *myDelegate = [[TextFieldScroll alloc] init]; [self.usernameTextField setDelegate: (id)myDelegate];其中 TextFieldScroll 是我在步骤 1 中创建的 NSObject 类
      • 可以在Interface Builder中实现self.view引用textField。 Shared 是你的单例类中的一个静态方法,我已经添加了代码。
      • 我想我们已经接近尾声了,非常感谢。就是让 self.view 在 Interface Builder 中引用 textField 的事情阻止了我。我不明白,也没有通过我在网络上的搜索找到它。查看我的实际代码编辑
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-13
      • 1970-01-01
      • 2017-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多