如何在不使用Nib的情况下实例化和调用UIView子类

时间:2010-02-05 11:12:25

标签: iphone objective-c uiview uiviewcontroller uibutton

不使用Interface builder或xib文件,实例化从UIView继承的两个类的正确方法是什么,以便它们可以使用位于视图本身的UIButtons在它们之间切换?

我认为这涉及从app委托设置一个UIViewController并添加我的类的两个实例,它们将UIView实现到控制器中(可能来自控制器内部?)

我也不确定如何在自定义UIViews上从UIButton引发事件以切换视图。我怀疑我需要向视图控制器添加一个方法,但我不确定如何从我的UIView范围内获取对视图控制器的引用。

另外,我想知道,如果需要使用UIViewController,那么switch方法是否应该在主app代理的范围内?

一些代码示例会很棒!

3 个答案:

答案 0 :(得分:7)

您的主要问题是您在概念上不了解UIViewControllers与UIViews的作用。大多数人一开始就没有。

视图是愚蠢的,理想情况下,它们应该由通用对象组成。它们几乎不包含接口的逻辑。他们不了解或不关心其他观点的存在。您在视图中放置的唯一逻辑是与视图本身的即时和通用功能相关的逻辑,无论它显示的数据或应用程序的其他部分的状态如何。你很少需要子类UIView。这就是为什么可以在Interface builder中完全配置视图而不使用任何代码。

ViewControllers包含接口的逻辑并将接口连接到数据(但它们不包含或逻辑地操纵数据。)它们是“智能的”并且高度定制。 viewControllers确实理解了应用程序上下文中视图的位置。 viewControllers从nib或以编程方式加载和配置视图。 viewControllers控制何时显示或隐藏视图以及它的顺序。 viewControllers确定响应事件采取的操作以及在哪里显示哪些数据。

VictorB的示例代码显示了如何以务实的方式完成这一切。需要注意的重要一点是viewController和view是两个完全独立的类的完全独立的对象。没有重叠,也没有必要继承UIView。所有自定义都在控制器中。

这一切都是因为MVC设计模式。它将接口与数据模型分离,使它们既模块化又相互独立。这使得设计,调试和重用每个独立模块变得容易。

答案 1 :(得分:4)

如果你想在代码中完成它,这里有一个例子我只是使用延迟加载的UI元素。我只在这里制作一个按钮,并在任何一个活动视图之间交换它。这有点尴尬,但它减少了证明这一点所需的代码量。

我创建了两个UIView来表示你的自定义类,一个用蓝色背景,一个用红色。按钮在两者之间交换。如果每个自定义视图中都有一个唯一的按钮,则只需要将这些按钮公开为UIView子类的属性,以便视图控制器可以访问它们,或者将视图控制器作为按钮的操作目标从内部添加你的UIView的加载代码。

我已经在我的模拟器中测试了这段代码,它似乎运行正常,但你真的应该尝试了解这里发生了什么,这样你就可以自己实现了。

ToggleViewController.h:

#import <UIKit/UIKit.h>
@interface ToggleViewController : UIViewController {
    UIView *firstView;
    UIView *secondView;
    UIButton *button;
}
- (void)addButton;
- (void)toggleViews;
@property (nonatomic, readonly) UIView* firstView;
@property (nonatomic, readonly) UIView* secondView;
@property (nonatomic, readonly) UIButton* button;
@end

ToggleViewController.m:

#import "ToggleViewController.h"
@implementation ToggleViewController

// assign view to view controller
- (void)loadView {
    self.view = self.firstView;
}

// make sure button is added when view is shown
- (void)viewWillAppear:(BOOL)animated {
    [self addButton];

}

// add the button to the center of the view
- (void)addButton {
    [self.view addSubview:self.button];
    button.frame = CGRectMake(0,0,150,44);
    button.center = self.view.center;
}

// to toggle views, remove button from old view, swap views, then add button again
- (void)toggleViews {
    [self.button removeFromSuperview];
    self.view = (self.view == self.firstView) ? self.secondView : self.firstView;
    [self addButton];
}

// generate first view on access
- (UIView *)firstView {
    if (firstView == nil) {
        firstView = [[UIView alloc] initWithFrame:CGRectZero];
        firstView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        firstView.backgroundColor = [UIColor redColor];
    }
    return firstView;
}

// generate second view on access
- (UIView *)secondView {
    if (secondView == nil) {
        secondView = [[UIView alloc] initWithFrame:CGRectZero];
        secondView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        secondView.backgroundColor = [UIColor blueColor];
    }
    return secondView;
}

// generate button on access
- (UIButton *)button {
    if (button == nil) {

        // create button
        button = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];

        // set title
        [button setTitle:@"Toggle Views" 
                forState:UIControlStateNormal];

        // set self as a target for the "touch up inside" event of the button
        [button addTarget:self 
                   action:@selector(toggleViews) 
         forControlEvents:UIControlEventTouchUpInside];
    }
    return button;
}

// clean up
- (void)dealloc {
    [button release];
    [secondView release];
    [firstView release];
    [super dealloc];
}

@end

答案 2 :(得分:-2)

使用Interface Builder。这是有原因的。