iPhone MVC. Нужна помощь в понимании того, как правильно передавать данные из контроллера в представление - PullRequest
0 голосов
/ 13 ноября 2009

Немного фона:

Я разработчик на C #, начинающий связываться с iPhone (есть идея для простой 2D-игры). Единственное программирование MVC, которое я делал, было для сети (ASP.NET MVC), поэтому, хотя у меня есть понимание в MVC, я не могу сосредоточиться на одном. Вот пример для иллюстрации.

Скажем, у меня есть простое приложение, где все, что я хочу сделать, это отобразить большой круг на экране. Я создал «View Based Application», и он дал мне базовые классы для начала:

MVCConfusionAppDelegate MVCConfusionViewController

Теперь, так как я буду делать некоторые пользовательские рисунки (я знаю, что могу добавить подпредставление и показать круг таким образом, но это всего лишь образец большего фрагмента), я добавил класс с именем MyCustomView и в Interface Builder установил представление MVCConfusionViewController как MyCustomView.

Теперь вот проблема. Я хочу иметь возможность установить в коде размер шарика в пользовательском представлении. Итак, у меня есть свойство на MyCusomView, как это:

#import <Foundation/Foundation.h>

@interface MyCustomView : UIView {
    NSNumber *ballSize;
}

@property(nonatomic,retain)IBOutlet NSNumber *ballSize;

@end

#import "MyCustomView.h"


@implementation MyCustomView

@synthesize ballSize;

-(void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    [[UIColor redColor]set];

    float floatValue = [self.ballSize floatValue];
    CGRect ballRect = CGRectMake(50.0f, 50.0f,floatValue , floatValue);
    CGContextFillEllipseInRect(context, ballRect);

}

@end

Тогда вот мой MVCConfusionViewController:

#import <UIKit/UIKit.h>
#import "MyCustomView.h"

@interface MVCConfusionViewController : UIViewController {
    NSNumber *ballSize;
}

@property(nonatomic,retain)IBOutlet NSNumber *ballSize;

@end

#import "MVCConfusionViewController.h"
#import "MyCustomView.h"

@implementation MVCConfusionViewController

@synthesize ballSize;

- (void)viewDidLoad {
    [super viewDidLoad];
    MyCustomView *myView = (MyCustomView *)self.view;
    myView.ballSize = self.ballSize;
}

И, наконец, MVCConfusionAppDelegate:

#import <UIKit/UIKit.h>

@class MVCConfusionViewController;

@interface MVCConfusionAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    MVCConfusionViewController *viewController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet MVCConfusionViewController *viewController;

@end

#import "MVCConfusionAppDelegate.h"
#import "MVCConfusionViewController.h"
#import "MyCustomView.h"

@implementation MVCConfusionAppDelegate

@synthesize window;
@synthesize viewController;


- (void)applicationDidFinishLaunching:(UIApplication *)application {    

    viewController.ballSize = [NSNumber numberWithInt:200];
    [window addSubview:viewController.view];

    [window makeKeyAndVisible];
}


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


@end

Как видите, в моем методе viewDidLoad есть уродливое приведение. Я надеялся, что смогу связать свойства ballSize в IB, но это мне не дало.

Так что мой вопрос просто заключается в том, как правильно передать эти данные из моего контроллера представления в мое представление без выполнения этого приведения? Я знаю, что упускаю что-то фундаментальное, но я просто не вижу этого. Любая помощь будет принята с благодарностью!

РЕДАКТИРОВАТЬ: Вот исходный код. http://bit.ly/uKyp9 Может быть, кто-то может посмотреть и посмотреть, если я делаю что-то не так.

Ответы [ 3 ]

3 голосов
/ 13 ноября 2009

Вы пытаетесь подключить один IBOutlet (в контроллере) к другому IBOutlet (в представлении)? К сожалению, я не думаю, что это так просто: -)

Вы также храните данные (ballSize) в контроллере и представлении.

Я бы сделал MVCConfusionViewController источником данных для MyCustomView, а затем позволил MyCustomView запросить у своего источника данных ballSize внутри метода -drawRect:

@class MyCustomView;

@protocol MyCustomViewDataSource
- (NSNumber *)ballSizeForMyCustomView:(MyCustomView *)view;
@end

@interface MyCustomView {
    id<MyCustomViewDataSource> dataSource;
}
@property (nonatomic, assign) IBOutlet id<MyCustomViewDataSource> dataSource;
@end

@implementation MyCustomView
- (void)drawRect:(CGRect) rect {
    if (self.dataSource == nil) {
        // no data source, so we don't know what to draw
        return;
    }

    float floatValue = [[self.dataSource ballSizeForMyCustomView:self] floatValue];
    // ...
}
@end

В Интерфейсном Разработчике подключите MVCConfusionViewController к свойству dataSource представления. Затем реализовать протокол:

@interface MVCConfusionViewController : UIViewController <MyCustomViewDataSource> {
    [...]
}
[...]
@end

@implementation MVCConfusionViewController
- (NSNumber *)ballSizeForMyCustomView:(MyCustomView *)view {
    return self.ballSize;
}
@end

Таким образом, контроллер представления также может быть источником данных для нескольких MyCustomView с, поскольку метод протокола принимает MyCustomView в качестве аргумента.

Если вам нужно более одного шара, взгляните на UITableViewDataSource и реализуйте похожие методы, например:

-(NSInteger)numberOfBallsInMyCustomView:(MyCustomView *)view;
-(NSNumber *)myCustomView:(MyCustomView *) ballSizeAtIndex:(NSInteger)index;
1 голос
/ 13 ноября 2009

Один из способов избежать приведения - добавить отдельное свойство выхода для пользовательского представления на контроллере и ссылаться на него вместо этого.

В Интерфейсном Разработчике создайте экземпляр MyCustomView и перетащитев существующее представление, чтобы сделать его подпредставлением, а затем подключить его к собственной розетке на контроллере.

1 голос
/ 13 ноября 2009

Ваш вид уже должен быть установлен в IB, так что вы можете использовать его как есть. Если вы хотите использовать MyCustomView, вы можете сделать это так:

- (void)viewDidLoad {
    [super viewDidLoad];
    CGRect frame = CGRectMake(0, 0, 320, 480);
    MyCustomView *myView = [[MyCustomView alloc] initWithFrame:frame];
    myView.backgroundColor = [UIColor greenColor];
    self.view = myView;
    [myView release];
    CGRect rectangle = CGRectMake(20, 20, 20, 20);
    [self.view drawRect:rectangle];
}

Я не мог заставить твой код рисования работать, я мало что знаю об этом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...