【问题标题】:Need help in understanding programmatically created UIView and UIViewController需要帮助理解以编程方式创建的 UIView 和 UIViewController
【发布时间】:2011-06-17 23:48:07
【问题描述】:

我一直在尝试理解视图控制器和视图,即使在观看了 iTunesU 上的一些类之后,我仍然无法以编程方式实现它们。我希望有人能澄清一下。

所以我正在尝试创建一个 UIViewController 来创建它的视图。

该程序分为以下几类: ProgramNameAppDelegate.h 和 .m ApplicationRootViewController.h 和 .m

从 AppDelegate,我创建了 UIWindow 和 UIViewController。部分代码如下:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    _window = [ [UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    if (!_window)
    {
        [self release];
        return NO;
    }

    _rootViewController = [ [ApplicationRootViewController alloc] init];
    if (!_rootViewController)
    {
        NSLog(@"No _rootViewController");
        [self release];
        return NO;
    }

    [_window addSubview:[_rootViewController view]];
    [_window makeKeyAndVisible];

    return YES;
}

在 ApplicationRootViewController 我调用 init。我的 UIView 是在 loadView 中创建的:

- (void)loadView
{
    NSLog(@"In loadView");

    [super loadView];

    CGRect _frame = [[UIScreen mainScreen] applicationFrame];

    UIView* _rootView = [[UIView alloc] initWithFrame:_frame];

    [_rootView setBackgroundColor:[UIColor redColor]];

    self.view = _rootView;

    return;

}

我遇到的问题显然是程序正在创建视图,但是,在应用程序退出活动之前,它永远不会显示我创建的视图。一旦我退出应用程序并返回,视图就在那里。我尝试了其他几种方法,但它的行为总是相同的。

我最终希望控制器从子类 UIView.h 和 .m 文件创建视图。

谢谢,

凯文

【问题讨论】:

  • 有些东西你没有发布或提到,因为你的代码对我来说很好用。顺便说一句,您在这里有泄漏: self.view = _rootView;你必须释放 _rootView
  • 是的,我发现了内存泄漏。其余的代码是相当罐头的东西。我解决了这个问题,但我仍然不知道发生了什么。我正在使用最新的 XCode 预览版(尽管我认为这与它无关)。我废弃了代码并在当前的 XCode 中重写了它,现在一切正常。我花了一天时间拔头发。感谢您查看它。
  • 您的 loadView 何时何地被调用?
  • 你为什么在名字中使用所有这些下划线?
  • dasdom,这只是一个命名约定。我很容易知道我通过下划线创建了哪些变量。

标签: iphone model-view-controller ios uiview uiviewcontroller


【解决方案1】:

来自docs:

loadView 的自定义实现 方法不应调用 super。

所以,去掉[super loadview],它应该可以工作;)

此外,如果您想使用自定义视图(UIView 的子类)。 Alloc/Init 使用initWithFrame: 并且当从 uiviewcontroller 引用 self.view 时,您必须像这样进行转换:

[(MyView *)self.view myMethod];

就这么简单;)

编辑: 假设你创建一个这样的类:

//MyView.h
@interface MyView : UIView{
    ...
}
- (void) doSomething:(NSString *)string;
@end
//MyView.m
#import MyView.h
@implementation MyView
... write your implementation here
@end

然后在 UIViewController 中, 在加载视图中 做:

//don't forget to #import "MyView.h"
-(void) loadView{
    MyView *myView = [[MyView alloc] initWithFrame:CGRectMake(...)];
    self.view = (UIView *)myView;
    [myView release];
}

然后在控制器中的其他地方引用您的视图时:

- (void) viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    [(MyView *)self.view doSomething:@"something"];//1
    [self.view setBackgroundColor:[UIColor greenColor]];//2
}

//1 中你应该强制转换,因为你正在调用doSomething: 方法(或者它也可以是一个属性),它在MyView 中声明/定义,而不是在UIView 中。如果你不施放,你会收到警告,但它会起作用。 在//2 中,您不需要强制转换,因为setBackgroundColor: 是在UIView 类中定义的方法;)

Objective-C 非常灵活,可以转换很多东西,所以你必须小心,因为转换就像告诉编译器:“相信我,不是 UIView,是 MyVIew”,编译器会服从你。但是如果你错了,你的应用程序会在尝试调用doSomething: 时崩溃,因为它在UIView 中不存在。

【讨论】:

  • 谢谢纳乔!我解决了,但不知道怎么解决。当我重写代码时,我“不小心”遗漏了 [super loadview]。现在我明白了为什么它有效与为什么无效。另外,我看到 Matt Stoker 在处理视图时做了很多转换,但不完全理解为什么。
猜你喜欢
  • 2012-09-01
  • 2011-06-08
  • 1970-01-01
  • 2021-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-04
  • 2012-06-24
相关资源
最近更新 更多