【问题标题】:different ways of creating custom views / custom view not able to be interacted with when created from object library创建自定义视图的不同方式/从对象库创建时无法与之交互的自定义​​视图
【发布时间】:2013-07-20 02:42:15
【问题描述】:

编辑#1

请阅读问题底部的编辑#1;我试图弄清楚 nib 可用于创建自定义视图的所有方式,因此所有示例都处理 nib 文件。

结束

我一直在尝试找出在控制器中创建使用 nib 的自定义视图的所有技术。我已经在这个问题的底部列出了这些方法。

这是我的 TRtestview 的代码(我如何进行此设置的一个含义是总是会调用 initWithCoder):

// TRtestview.m
-(id)initWithCoder:(NSCoder *)aDecoder{
    self=[super initWithCoder:aDecoder];
    if (self) {
      if (self.subviews.count == 0) {
        UIView *myView=[[[NSBundle mainBundle] loadNibNamed:@"testview" owner:nil options:nil] lastObject];
        myView.userInteractionEnabled=YES;  // doesn't do anything
        [self addSubview:myView];
      }
    }
    NSLog(@"about to return here in initWithCoder");
    return self;
}

编辑 1

-(void)setup
{
       UIView *myView=[[[NSBundle mainBundle] loadNibNamed:@"testview" owner:nil options:nil] lastObject];
      [self addSubview:myView];
}


- (id)initWithFrame:(CGRect)frame
{
    NSLog(@"at top of initWithFrame");
    self = [super initWithFrame:frame];
    if (self) {
      [self setup];
    }
    return self;
}

在 TRViewController.m 中,我尝试将 thisView 设置为 userInteractionEnabled,但并没有改变:

- (void)viewDidLoad
{
  [super viewDidLoad];
  self.thisView.userInteractionEnabled=YES;

这适用于调用 initWithFrame(技术 #1)和 loadNibNamed(技术 #2)的场景。它将通过将视图从对象检查器中拖出然后在自定义类属性检查器中设置类来加载视图(技术 #3)。但是,按钮不起作用,因此这种方式不起作用。

如何使用技巧 #3 创建带有 nib 的自定义视图并允许用户交互?

谢谢

编辑 1

我真的很想了解创建和实例化自定义视图的所有方式。理想情况下,我希望能够拥有可以通过 initWithFrame、loadNibNamed 创建或从对象库中拖动的自定义视图。

场景似乎是:

  1. 来自 ViewController 的 initWithFrame;如果使用笔尖,我会在我的 initWithFrame 中调用 loadNibNamed - 我需要防止递归加载
  2. 从 ViewController(它将调用 initWithCoder)中加载NibNamed,并且只想加载一次
  3. 拖动 UIView 的实例,然后将自定义类设置为我的自定义 UIView(在本例中为 TRtestview)。这将调用 initWithCoder。

【问题讨论】:

    标签: ios ios6 uiview


    【解决方案1】:

    看起来您正在从 testview 类初始化器内部加载 testview,并对子视图进行了 hacky 检查,以防止它变得递归。由于外面的代码可能也加载了笔尖,所以你实际上在这里做的是加载笔尖两次,一次在另一个里面。如果您设置所有者,那么内部的将在外部设置插座。

    这只是一个猜测,因为这里没有足够的信息可以确定 - 但是如果您在视图类中为其中的某些子视图设置插座,那么您必须向 @987654322 提供一个 owner 对象@ 与您的班级类型。因此,您可以在代码中将 self 作为所有者传递,这可能会起作用。但是,将 nib 用于单视图确实是错误的方式。

    不要将 nib 文件中的单个视图作为 TRtestView 类,而是将单个视图作为其他内部视图的持有者,并将“文件所有者”占位符对象设置为具有 @ 类987654325@。为持有人创建一个出口并分配它,然后执行以下操作:

    TRtestview* testview = [[TRtestview alloc] initWithFrame:desiredFrame];
    [[NSBundle mainBundle] loadNibNamed:@"testview" owner:testview options:nil];
    

    现在testview 中的所有插座都将在加载笔尖时设置,包括您可以添加为子视图的支架。

    此外,如果您想在不同的 nib 中使用 TRtestview(例如 TestViewController),您可以通过在视图中拖动并将该对象的类设置为 TRtestview 来执行此操作 - 这将创建一个 TRtestview并将其命名为initWithCoder,您可以将其分配给TestViewController 中的一个名为testview 的插座。然后在awakeFromNib for TestViewController 中,您将放置上面的第二行代码,将testview 出口作为所有者对象传递。

    编辑: 很难确切地看到您要做什么,但是从任何视图的 init 方法中加载 nib 都是错误的(加载 nib 会创建视图对象,而不是相反)。我想我一开始误解了您要设置的IBOutlets 的位置,可能您正在寻找的答案实际上是您可以加载 nib,但可以从这样的类构造函数方法中加载:

    + (MyCustomView*)newCustomView
    {
        MyCustomView* view = [[NSBundle mainBundle] loadNibNamed:@"testview" owner:nil options:nil][0];
        // Do custom setup things to view here...
        // Perhaps based on additional inputs to this method.
        view.doStuff;
        return view;
    }
    

    【讨论】:

    • 谢谢,@jhabbott,我真的很感激。您提供的示例代码将在视图控制器中完成,对吗?或者同时在视图控制器和自定义视图中?我添加了一些编辑以添加更多源代码并尝试使其更清晰。
    • lmk 如果我的问题或我写的东西只是不好或过时(或两者兼而有之)。只是想找出正确的方法并感谢我能得到的任何帮助。
    • 像你一样用loadNibNamed 加载笔尖很好 - 但不是从视图本身的初始化程序中。看到你想要做什么是相当棘手的。您可以从类方法构造函数中加载 nib - 我将添加一些代码来演示。
    猜你喜欢
    • 1970-01-01
    • 2011-05-24
    • 2015-06-12
    • 1970-01-01
    • 2019-03-16
    • 2016-04-30
    • 1970-01-01
    相关资源
    最近更新 更多