Objective-C自定义类操作和出口

时间:2013-08-29 20:49:06

标签: ios objective-c class uiview iboutlet

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

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

enter image description here

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操作不会触发。

2 个答案:

答案 0 :(得分:1)

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

Interface-Builder: "combine" NSView-class with .xib

您的安排是:

  • Mainstoryboard.storyboard
  • MyViewController.h
  • MyViewController.m

  • CustomPickerView.xib

  • CustomPickerView.h
  • CustomPickerView.m

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

在您的示例中,您将在代码中创建customPickerView,但另一个有用的方案是将其添加到Interface Builder中的故事板。此解决方案适用于两种情况。

在CustomViewPicker.h中

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

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

在CustomViewPicker.xib

  • 在Identity Inspector中将文件的所有者类设置为CustomViewPicker。
  • 将xib中的顶级视图设置为默认的UIView类( NOT CustomViewPicker)。
  • 将您的IBOutlets从文件所有者:viewdatePickerdoneButton连接到各自的IB对象
  • 将您的IBAction从文件所有者buttonDonePush连接到doneButton IB对象

在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.customPickerView IBOutlet。

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

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

如果你想从customPickerView中取出你的按钮推送动作,你可以考虑使用一个委托,它可能比你使用NSNotification更自包含(但这个问题超出了原来的问题)。

答案 1 :(得分:0)

编辑:

上面的答案指出了这一点,但是在init方法中你设置了self,但这是在self初始化之前发生的。如果您可以显示创建此特定视图的代码,那么它将会有很大帮助。这是我的建议。

在控制此自定义视图部署的类中:

//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

在CustomPickerView.m文件中,删除init方法。

以前的答案:

您在此实现中使用NSNotificationCenter。当用户触摸完成按钮时,会发布NSNotification。您必须明确“选择加入”并“收听”这些通知。您可以通过注册通知中心来完成此操作。

在viewDidLoad中:

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

然后你需要实现你在那里指定的选择器:

-(void)receivedNotification:(NSNotification *)note {
    NSDictionary *obj = [note object];
    NSLog(@"%@",obj);
    //dismiss the date picker here...
    //etc...
}