iOS получает доступ к переменной представления из контроллера представления - PullRequest
2 голосов
/ 23 июня 2011

Я занимаюсь разработкой на 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 ]

2 голосов
/ 23 июня 2011

Ваше представление не узнает, что это за контроллер, пока не вернется метод -initRootView, но вы пытаетесь использовать контроллер из этого метода.

Тем не менее, было бы намного лучшеесли вы следовали обычному образцу Cocoa Touch для контроллера вида, создающего его вид.Предполагается, что контроллеры представлений лениво создают свои представления, то есть откладывают создание и инициализацию представлений до вызова метода -loadView.Вы можете переопределить -loadView для создания своего представления, а также переопределить -viewDidLoad для выполнения любой работы по настройке, которую необходимо выполнить после создания представления.

Кроме того, представлению, как правило, не рекомендуется знать о его представлении.контроллер.Контроллер должен сказать представлению, что делать, а не наоборот.Если вам нужно представление для отправки некоторой информации контроллеру, вы обычно предоставляете контроллер представлению в качестве делегата представления.Но если вам просто нужно, чтобы контроллер представления мог найти какое-то подпредставление, например, ваш ярлык, вероятно, было бы неплохо предоставить для этого некоторые средства доступа в представлении контейнера (чтобы контроллер представления мог просто сказать что-то вроде self.view.label.text = @"some text";Другой вариант - установить для свойства тега подпредставления какое-то уникальное значение и использовать контроллер для поиска подпредставления.

1 голос
/ 23 июня 2011

Проблема легко обнаруживается, но для ее решения требуется определенная работа.

Глядя на ваш код, я сразу хочу предложить добавить весь код инициализации RootView в метод loadView вашего RootViewController. Вот где это должно быть ( смотрите здесь, почему ).

Кроме того, если вам абсолютно необходимо, чтобы ваш RootView имел ссылку назад на RootViewController, вам, вероятно, следует сделать это в viewDidLoad. Но я бы не рекомендовал это делать.

При использовании шаблона MVC контроллер обязан инициализировать и обновлять представления. Строка self.rootViewController.rootViewLabel = testLabel; должна быть удалена из реализации RootView. Непонятно, каково ваше намерение, но если вы хотите обновить 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 голосов
/ 23 июня 2011

Не уверен, почему вы делаете это так, но вы, вероятно, могли бы заставить его работать, если передавали контроллер в init представления:

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

init представления:

- (id)initRootView:(UIViewController*)controller
{
     self.rootViewController = controller;
     self.rootViewController.rootViewLabel = testLabel;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...