iOS从视图控制器访问视图的变量

时间:2011-06-23 15:50:19

标签: iphone ios variables view uiviewcontroller

我正在iOS上开发,我正在以编程方式构建我的视图。我注意到当我尝试从视图控制器访问我的视图中必须更改的变量时,它们为空。我将发布视图及其视图控制器:

RootViewController.h

 #import <UIKit/UIKit.h>

@class RootView;

@interface RootViewController : UIViewController {
    RootView *rootView;
}

@property (nonatomic,retain) RootView *rootView;


@end

RootViewController.m

    #import "RootViewController.h"
#import "RootView.h"

@implementation RootViewController

@synthesize rootView;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}



- (void)dealloc
{
    [rootView release];
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)loadView{
    RootView *rootV = [[RootView alloc] initWithFrame:CGRectMake(10, 10, 100, 50)];
    rootV.rootViewController = self;
    self.view = rootV;
    [rootV release];
}

- (void)viewDidLoad{
    NSLog(@"TEXT: %@",self.rootView.label.text);
    self.rootView.label.text=@"HELLO!";
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    [self setRootView:nil];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end

RootView.h

   #import <UIKit/UIKit.h>

@class RootViewController;

@interface RootView : UIView {
    RootViewController *rootViewController;
    UILabel *label;
}

@property (nonatomic,assign) RootViewController *rootViewController;
@property (nonatomic,retain) UILabel *label;


@end

RootView.m

   #import "RootView.h"
#import "RootViewController.h"

@implementation RootView
@synthesize rootViewController;
@synthesize label;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        //Create the label
        UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 100,100, 50)];
        //Set the font bold 
        testLabel.font = [UIFont boldSystemFontOfSize:20.0];
        //Set the backgroundcolor of the label to transparent
        testLabel.backgroundColor = [UIColor clearColor];
        //Set the text alignment of the text label to left
        testLabel.textAlignment = UITextAlignmentLeft;
        //Set the text color of the text label to black
        testLabel.textColor = [UIColor blackColor];
        testLabel.text = @"01:30";

        self.label = testLabel;

        [self addSubview:label];
        [testLabel release];
    }
    return self;
}


- (void)dealloc
{
    [label release];
    rootViewController = nil;
    [super dealloc];
}

@end

我更改了代码,但似乎无法正常工作.....

好的解决了我忘了这行“self.rootView = rootV;”

3 个答案:

答案 0 :(得分:2)

在-initRootView方法返回之后,您的视图无法找到其控制器的内容,但您尝试在该方法中使用该控制器。

也就是说,如果你按照通常的Cocoa Touch模式创建视图的视图控制器会好得多。视图控制器应该懒惰地创建它们的视图,也就是说它们推迟视图创建和初始化,直到调用-loadView方法。您可以覆盖-loadView来创建视图,还可以覆盖-viewDidLoad来执行创建视图后需要完成的任何设置工作。

此外,通常不建议视图了解其控制器。控制器应该告诉视图要做什么,而不是相反。如果需要视图将一些信息发送到控制器,通常会将控制器作为视图的委托提供给视图。但是如果你只是需要视图控制器能够找到一些子视图,比如你的标签,那么在容器视图中为它提供一些访问器可能是个好主意(这样视图控制器就可以说{{1}另一个选项是将子视图的标记属性设置为某个唯一值,并让控制器使用它来查找子视图。

答案 1 :(得分:1)

问题很容易发现,但需要一些工作来解决。

查看代码,我立即想要建议的是将所有RootView初始化代码放在RootViewController的loadView方法中。那应该是(see here why)。

另外,如果您绝对需要RootView在RootViewController上提供引用,那么您应该在viewDidLoad中执行此操作。但我不建议这样做。

使用MVC模式时,控制器负责初始化和更新视图。应该从RootView的实现中删除行self.rootViewController.rootViewLabel = testLabel;。目前还不清楚你的意图是什么,但如果你想更新rootViewLabel,你应该让控制器这样做。

总结一下:

// RootViewController.m

- (id)initRootViewController{

    self = [super init];

    if(self){
        // other init code here
    }

    return self;
}

- (void)loadView {
    RootView *rootV = [[RootView alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];        
    self.view = rootV;
    [rootV release];     
}

- (void)viewDidLoad {
    [super viewDidLoad];        
    // etc...
}

// etc.

现在,对于RootView,它的外观如下:

<强> RootView.h

#import <UIKit/UIKit.h>

@interface RootView : UIView {    
    UILabel *rootViewLabel;
}

// moved from RootViewController
@property (nonatomic, retain) UILabel *rootViewLabel;

@end

<强> RootView.m

#import "RootView.h"

@implementation RootView

@synthesize rootViewLabel;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Whatever initialization code you might have
        //Create the label
        UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 100,100, 50)];
        //Set the font bold 
        testLabel.font = [UIFont boldSystemFontOfSize:20.0];
        //Set the backgroundcolor of the label to transparent
        testLabel.backgroundColor = [UIColor clearColor];
        //Set the text alignment of the text label to left
        testLabel.textAlignment = UITextAlignmentLeft;
        //Set the text color of the text label to black
        testLabel.textColor = [UIColor blackColor];
        testLabel.text = @"01:30";

        self.rootViewLabel = testLabel;      
        [testLabel release];

        // add rootViewLabel as a subview of your this view
        [self addSubView:rootViewLabel];
    }
    return self;
}

- (void)dealloc
{
    [rootViewLabel release];
    [super dealloc];
}

@end

我希望这能让您了解如何构建视图初始化代码......

(免责声明,我现在无法测试此代码,请指出任何错误!谢谢)

答案 2 :(得分:0)

不确定为什么你这样做,但如果你将控制器传递给视图的init,你可能会使它工作:

RootView *rootV = [[RootView alloc] initRootView:self];

view的init:

- (id)initRootView:(UIViewController*)controller
{
     self.rootViewController = controller;
     self.rootViewController.rootViewLabel = testLabel;