2

我正在尝试创建 UIView 的自定义子类,如下所示:

我创建了一个带有 UIView 的 .xib,其中包含 Picker 对象和 Toolbar 对象,连接了 Outlets 和操作。

在此处输入图像描述

CustomPickerView.h

#import <UIKit/UIKit.h>

@interface CustomPickerView : UIView

@property (strong, nonatomic) IBOutlet UIDatePicker* datePicker;
@property (strong, nonatomic) IBOutlet UIBarButtonItem* doneButton;

-(IBAction) buttonDonePush:(id)sender;

@end

CustomPickerView.m

#import "CustomPickerView.h"

@implementation CustomPickerView

-(id) init
{
    self=[[[NSBundle mainBundle] loadNibNamed:@"CustomPickerView" owner:self options:nil] objectAtIndex:0];
    return self;
}

-(void) buttonDonePush:(id)sender
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"CustomPickerViewDoneButtonPush" object:nil userInfo:[NSDictionary dictionaryWithObject:self.datePicker.date forKey:@"date"]];
}

@end

最后,在我的 ViewController 中,我在 viewDidLoad 方法中实例化对象。

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.customPickerView=[[CustomPickerView alloc] init];
    self.customPickerView.datePicker.datePickerMode=UIDatePickerModeTime;

    self.dateField.inputView=self.customPickerView;
}

当用户点击 self.dateField 时,我的 CustomPickerView 会很好地弹出来代替标准键盘。

问题是当用户从我的 CustomPickerView 类中点击 Done 按钮时, buttonDonePush 操作不会触发。

4

2 回答 2

2

这个答案可以被认为是我最近为 iOSX 提供的类似解决方案的 iOS 伴侣:

Interface-Builder:将 NSView 类与 .xib “组合”

你的安排是这样的:

  • Mainstoryboard.storyboard
  • MyViewController.h
  • 我的视图控制器.m

  • CustomPickerView.xib

  • CustomPickerView.h
  • CustomPickerView.m

您希望将 customPickerView 用作 MyViewController.view 的子视图,并希望能够从包含的上下文中访问它的控件小部件。

在您的示例中,您正在代码中创建 customPickerView,但另一个有用的场景是将其添加到 Interface Builder 中的情节提要中。此解决方案适用于这两种情况。

在 CustomViewPicker.h

  • 为您的界面元素声明 IBOutlets。您已经为 datePicker 和 doneButton 完成了此操作,但您还需要一个 IBOutlet 到 UIView,这将是这些项目的包含视图。

    @property (strong, nonatomic) IBOutlet UIView* view;
    

在 CustomViewPicker.xib

  • 在 Identity Inspector 中将文件的所有者类设置为 CustomViewPicker。
  • 将 xib 中的顶级视图设置为默认 UIView 类(不是CustomViewPicker)。
  • 将文件所有者的 IBOutlets: view, datePicker,doneButton连接到它们各自的 IB 对象
  • 将您的 IBAction 从文件所有者连接buttonDonePushdoneButtonIB 对象

在 CustomViewPicker.m 中:

- (id)initWithFrame:(CGRect)frame
{
    //called when initialising in code
    self = [super initWithFrame:frame];
    if (self) {
        [self initialise];
    }
    return self;
}

  - (void)awakeFromNib
  {
      //called when loading from IB/Storyboard
      [self initialise];
  }

- (void) initialise
{
    NSString* nibName = NSStringFromClass([self class]);
    if ([[NSBundle mainBundle] loadNibNamed:nibName
                                      owner:self
                                    options:nil]) {
        [self.view setFrame:[self bounds]];
        [self addSubview:self.view];
    }

}
-(void) buttonDonePush:(id)sender
{
   //button push actions
}

如果您想在代码中初始化(如您所做的那样),您的 MyViewController 将包含如下内容:

- (void)viewDidLoad
{
    [super viewDidLoad];
    CGRect frame = CGRectMake(0, 50, 320, 300);
    self.customPickerView=[[CustomPickerView alloc] initWithFrame:frame];

    self.customPickerView.datePicker.datePickerMode=UIDatePickerModeTime;
    self.dateField.inputView=self.customPickerView;
}

[编辑删除了这个多余的行:[self.view addSubview:self.customPickerView];]

或者,您可以直接在情节提要中创建您的 CustomPickerView - 并设置它的框架。只需将自定义视图添加到 MyViewController 的故事板场景,并将其类更改为 CustomPickerView。将其链接到您的self.customPickerViewIBOutlet。

在这种情况下initWithFrame不会被调用,而是awakeFromNib在 MyViewController 加载它的 CustomPickerView 子视图时调用。您的 MyViewControllerviewDidLoad将如下所示:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.customPickerView.datePicker.datePickerMode=UIDatePickerModeTime;
    self.dateField.inputView=self.customPickerView;
}

如果您想从 customPickerView 中获取按钮推送操作,您可以考虑使用委托,它可能比您使用 NSNotification 更加独立(但该问题超出了您的原始问题)。

于 2013-08-29T23:21:42.480 回答
0

EDIT:

An answer above pointed this out, but in the init method you are setting self, but this happens before self is ever initialized. If you could show the code where you are creating this specific view, it would help a lot. Here's my suggestion.

In your class that is controlling the deployment of this custom view:

//to invoke your view
CustomPickerView *myView;
NSArray *xibContents = [[NSBundle mainBundle]loadNibNamed:@"CustomPickerView" owner:nil options:nil];
for (id xibObject in xibContents) {
    if ([xibObject isKindOfClass:[CustomPickerView class]]) {
        myView = (CustomPickerView *)xibObject;
        break;
    }
}
//now *myView is instantiated as your custom picker view
//do what you want here, add to subview, set frame, etc

In the CustomPickerView.m file, remove the init method.

PREVIOUS ANSWER:

You are using NSNotificationCenter in this implementation. When a user touches the done button, an NSNotification is posted. You must explicitly "opt in" and "listen" for these notifications. You do that by registering with the notification center.

In viewDidLoad:

 [[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(receivedNotification:) 
    name:@"CustomPickerViewDoneButtonPush"
    object:nil];

Then you need to implement the selector you specified up there:

-(void)receivedNotification:(NSNotification *)note {
    NSDictionary *obj = [note object];
    NSLog(@"%@",obj);
    //dismiss the date picker here...
    //etc...
}
于 2013-08-29T20:56:41.823 回答