xcode UILabel 不显示 inputView

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12849146/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 01:47:33  来源:igfitidea点击:

UILabel doesn't show inputView

objective-ciosxcode

提问by massyc

I would use a UILabel to allow users to select a date with UIDatePicker.

我会使用 UILabel 来允许用户使用 UIDatePicker 选择日期。

To do this, I created an UILabel subclass overwriting the inputView and the inputAccessoryView properties making them writable; I also implemented the -(BOOL) canBecomeFirstResponder and the -(BOOL) isUserInteractionEnabled methods returning YES for both. Then I assigned an instance of UIDatePIcker to the inputView property.

为此,我创建了一个 UILabel 子类,覆盖 inputView 和 inputAccessoryView 属性,使它们可写;我还实现了 -(BOOL) canBecomeFirstResponder 和 -(BOOL) isUserInteractionEnabled 方法,两者都返回 YES。然后我将 UIDatePIcker 的一个实例分配给 inputView 属性。

At this point my expectation is that when the label is tapped an UIDatePicker should appear, but nothing happens.

在这一点上,我的期望是当标签被点击时 UIDatePicker 应该出现,但没有任何反应。

Any help?

有什么帮助吗?

This is the code:

这是代码:

YPInteractiveUILabel.h

@interface YPInteractiveUILabel : UILabel
    @property (readwrite) UIView *inputView;
    @property (readwrite) UIView *inputAccessoryView;

- (BOOL) canBecomeFirstResponder;
- (BOOL) isUserInteractionEnabled;
@end


YPInteractiveUILabel.h

#import "YPInteractiveUILabel.h"

@implementation YPInteractiveUILabel

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];

    if (self)
    {
        UIDatePicker *datePicker = [[UIDatePicker alloc] init];
        [self  setInputView:datePicker];
    }

    return self;
}

- (BOOL)isUserInteractionEnabled
{
    return YES;
}

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

@end

采纳答案by massyc

Thanks to the suggestions (especially the comment from NeverBe and the answer proposed by rdelmar) I found the problem in my code. In brief, in order to show the input label, a call to the becomeFirstResponder method when the user tap the label is needed.

感谢建议(尤其是来自 NeverBe 的评论和 rdelmar 提出的答案),我在我的代码中发现了问题。简而言之,为了显示输入标签,需要在用户点击标签时调用 becomeFirstResponder 方法。

Following the UILabel subclass implementation corrected (the header file remains the same):

在 UILabel 子类实现更正后(头文件保持不变):

@implementation YPInteractiveUILabel

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];

    if (self)
    {
        UIDatePicker *datePicker = [[UIDatePicker alloc] init];
        [self  setInputView:datePicker];

        UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(launchPicker:)];
        [self addGestureRecognizer:tapper];

    }

    return self;
}

- (BOOL)isUserInteractionEnabled
{
    return YES;
}

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

-(void)launchPicker:(UITapGestureRecognizer *) tapper
{
    [self becomeFirstResponder];
}


@end

回答by Dmitriy Kirakosyan

UILabel + UIDatePicker -- Swift version with Done button.

UILabel + UIDatePicker -- 带有完成按钮的 Swift 版本。

import UIKit

class DatePickerLabel: UILabel {

    private let _inputView: UIView? = {
        let picker = UIDatePicker()
        return picker
    }()

    private let _inputAccessoryToolbar: UIToolbar = {
        let toolBar = UIToolbar()
        toolBar.barStyle = UIBarStyle.Default
        toolBar.translucent = true

        toolBar.sizeToFit()

        return toolBar
    }()

    override var inputView: UIView? {
        return _inputView
    }

    override var inputAccessoryView: UIView? {
        return _inputAccessoryToolbar
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(doneClick))
        let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)

        _inputAccessoryToolbar.setItems([ spaceButton, doneButton], animated: false)

        let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(launchPicker))
        self.addGestureRecognizer(tapRecognizer)
    }

    override func canBecomeFirstResponder() -> Bool {
        return true
    }

    @objc private func launchPicker() {
        becomeFirstResponder()
    }

    @objc private func doneClick() {
        resignFirstResponder()
    }

}

回答by rdelmar

How about something like this. Rather than subclass the label, just add a gesture recognizer to it, and bring up the picker in the tap recognizer's handler. In the picker's action method, populate the label and dismiss the picker. This example works, but you'd probably want to add some animation to make it look better:

这样的事情怎么样。而不是将标签子类化,只需向其添加一个手势识别器,并在点击识别器的处理程序中调出选择器。在选择器的操作方法中,填充标签并关闭选择器。此示例有效,但您可能希望添加一些动画以使其看起来更好:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.label.userInteractionEnabled = YES;
    UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(launchPicker:)];
    [self.label addGestureRecognizer:tapper];
}

-(void)launchPicker:(UITapGestureRecognizer *) tapper {
    UIDatePicker *picker = [[UIDatePicker alloc] initWithFrame:CGRectMake(5, 150, 300, 200)];
    [picker addTarget:self action:@selector(updateLabel:) forControlEvents:UIControlEventValueChanged];
    [self.view addSubview:picker];
}

-(IBAction)updateLabel:(UIDatePicker *)sender {
    self.label.text = [NSString stringWithFormat:@"%@",sender.date ];
    [sender removeFromSuperview];
}

回答by ims

You can just ovveride inputView getter method, like explained in Apple documentation:

您可以只覆盖 inputView getter 方法,如Apple 文档中所述

- (UIView *)inputView {
    return myInputView;
}
- (BOOL)canBecomeFirstResponder {
    return YES;
}

Then add a gesture or a button to call becomeFirstResponder:

然后添加一个手势或按钮来调用 becomeFirstResponder:

- (void)showInputView:(id)sender {
     [self becomeFirstResponder];
}

回答by Adobels

This is a code snipet of @dmitriy-kirakosyan updated to Swift 5

这是更新到 Swift 5 的 @dmitriy-kirakosyan 的代码片段

class DatePickerLabel: UILabel {

    private let _inputView: UIView? = {
        let picker = UIDatePicker()
        return picker
    }()

    private let _inputAccessoryToolbar: UIToolbar = {
        let toolBar = UIToolbar()
        toolBar.barStyle = UIBarStyle.default
        toolBar.isTranslucent = true

        toolBar.sizeToFit()

        return toolBar
    }()

    override var inputView: UIView? {
        return _inputView
    }

    override var inputAccessoryView: UIView? {
        return _inputAccessoryToolbar
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItem.Style.plain, target: self, action: #selector(doneClick))
        let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)

        _inputAccessoryToolbar.setItems([ spaceButton, doneButton], animated: false)

        let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(launchPicker))
        self.addGestureRecognizer(tapRecognizer)
    }

    override var canBecomeFirstResponder: Bool {
        return true
    }

    @objc private func launchPicker() {
        becomeFirstResponder()
    }

    @objc private func doneClick() {
        resignFirstResponder()
    }

}

回答by onmyway133

Here is the UILabelthat shows PickerView, in Swift 4

这是在 Swift 4UILabel中显示的PickerView

final class DatePickerLabel: UILabel {
  private let pickerView: UIPickerView
  private let toolbar: UIToolbar

  required init(pickerView: UIPickerView, toolbar: UIToolbar) {
    self.pickerView = pickerView
    self.toolbar = toolbar
    super.init(frame: .zero)

    let recogniser = UITapGestureRecognizer(target: self, action: #selector(tapped))
    addGestureRecognizer(recogniser)
  }

  required init?(coder aDecoder: NSCoder) {
    fatalError()
  }

  override var inputView: UIView? {
    return pickerView
  }

  override var inputAccessoryView: UIView? {
    return toolbar
  }

  override var canBecomeFirstResponder: Bool {
    return true
  }

  @objc private func tapped() {
    becomeFirstResponder()
  }
}

回答by Rok Jarc

I know this is an old question but this might still be useful to someone.

我知道这是一个老问题,但这可能对某人仍然有用。

There is another way to solve this - there is no need to complicate things with gesture recognizers...

还有另一种方法可以解决这个问题 - 无需使用手势识别器使事情复杂化......

GTPDateLabel.h

GTPDateLabel.h

@interface GTPDateLabel : UILabel

@property (readonly, retain) UIView *inputView;

@end

GTPDateLabel.m

GTPDateLabel.m

#import "GTPDateLabel.h"

@implementation GTPDateLabel

@synthesize inputView = _inputView;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];

    if (self)
    {
        self.userInteractionEnabled = YES;
    }

    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];

    if (self)
    {
        self.userInteractionEnabled = YES;
    }

    return self;
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];

    [self becomeFirstResponder];
}

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

-(UIView *)inputView
{
    if (!_inputView)
    {
        UIDatePicker *datePicker = [[UIDatePicker alloc] init];

        _inputView = datePicker;
    }

    return _inputView;
}

@end

Note that you should also set the delegateand in case of custom UIPickeralso dataSource...

请注意,您还应该设置delegate和 在自定义的情况下UIPickerdataSource...