2011-06-23 127 views
2

我在iOS上開發,並以編程方式構建我的視圖。我注意到,當我嘗試訪問必須在視圖中從視圖控制器更改的變量時,它們爲空。我會後雙方的觀點和看法控制器: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); 
    [email protected]"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;」

回答

2

您的視圖直到它的-initRootView方法返回後才找出它的控制器,但是您試圖從該方法中使用該控制器。

也就是說,如果您按照通常的Cocoa Touch模式創建視圖的視圖控制器,會更好。視圖控制器應該懶惰地創建他們的視圖,也就是說他們推遲視圖創建和初始化,直到調用-loadView方法。您可以覆蓋-loadView以創建視圖,還可以覆蓋-viewDidLoad以執行創建視圖後需要完成的任何設置工作。

此外,通常不建議您瞭解其控制器。控制器應該告訴視圖做什麼,而不是相反。如果您需要視圖向控制器發送一些信息,則通常將視圖的控制器作爲視圖的代表提供給視圖。但是,如果你只是需要視圖控制器能夠找到一些子視圖,比如你的標籤,那麼在容器視圖中提供一些訪問器可能是個好主意(這樣視圖控制器就可以說類似self.view.label.text = @"some text";之類的東西)。選項是將子視圖的標籤屬性設置爲某個唯一的值,並讓控制器使用它來查找子視圖。

+0

對不起,我沒有得到它。如果我理解得很好,我想要做的是在我的視圖控制器中根據MVC和視圖控制器在我的視圖控制器中設置插口,我想更改標籤的屬性是否可以?我試圖添加一個按鈕,當我按下按鈕時,我嘗試更改標籤的文本,但它不起作用。似乎參考標籤爲null ..任何建議?! – ubiAle

+0

我希望我的編輯有助於澄清事情,但是您還需要閱讀文檔中的[瞭解視圖管理週期](http://tinyurl.com/6cw5352)。 – Caleb

+0

因此,根據通常的可可觸摸模式,我應該在loadview方法中構建視圖嗎?如果是這樣,將視圖放在單獨的文件中是否與我一樣錯誤,並在loadview方法中實例化視圖?這與我做過或沒做過的事有什麼不同嗎?!謝謝 – ubiAle

0

不確定你爲什麼這樣做,但如果你通過控制器,你可能會使它工作到視圖的init:

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

視圖的init:

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

這樣做,而不是我做了什麼區別?!它不一樣嗎? – ubiAle

+0

在你的initRootView中,你有'self.rootViewController.rootViewLabel = testLabel;'但self.rootViewController還沒有指向你的控制器。 – meggar

+0

哦,這是真的!我知道了!!!謝謝 – ubiAle

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 

我希望這給你如何組織你的觀點初始化代碼的想法......

(聲明,我現在不能測試此代碼,請指出任何錯誤!謝謝)

+0

感謝您的文章,這個想法是爲視圖有一個單獨的文件,因爲我必須寫很多行我寧願有單獨的文件,我認爲這不是一個問題,你有寫你的行您在加載視圖中調用的initwithframe方法中的viewDidLoad是不是?如果我將視圖和視圖控制器分開,控制器如何知道它的插座。我的意思是,如果我必須刪除此行「self.rootViewController.rootViewLabel = testLabel」我如何更改我的網點,以防萬一我有兩個不同的文件一個爲視圖和一個爲其viewcontroller? – ubiAle

+0

是的,在這種情況下,你會實現該UILabel作爲你的RootView的屬性。我會更新我的答案中的代碼以反映這一點。然後,控制器將通過屬性點符號訪問它:'self.rootView.rootViewLabel'。 – octy

+0

答覆已更新。 – octy

相關問題