在运行时实现代理?

时间:2012-01-25 15:27:06

标签: iphone objective-c ios cocoa-touch delegates

我有一个通用视图控制器类,我的应用程序中的所有视图控制器类都继承了以下loadView方法:

- (void) loadView
{
    if (viewType == UIStandardViewControllerViewTypeUIView)
    {
        UIView *view = [[UIView alloc] initWithFrame: [[UIScreen mainScreen] applicationFrame]];
        [self setView: view];
        [view release];
    }
    else if (viewType == UIStandardViewControllerViewTypeUIScrollView)
    {
        UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame: [[UIScreen mainScreen] applicationFrame]];
        [self setView: scrollView];
        [scrollView release];
    }
    else if (viewType == UIStandardViewControllerViewTypeUITableViewPlain || viewType == UIStandardViewControllerViewTypeUITableViewGrouped)
    {
        UITableViewStyle tableViewStyle; 

        if (viewType == UIStandardViewControllerViewTypeUITableViewPlain)
        {
            tableViewStyle = UITableViewStylePlain;
        }
        else 
        {
            tableViewStyle = UITableViewStyleGrouped;
        }

        UITableView *tableView = [[UITableView alloc] initWithFrame: [[UIScreen mainScreen] applicationFrame] style: tableViewStyle];
        [self setView: tableView];
        [tableView release];
    }

    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStylePlain target:nil action:nil];
    [[self navigationItem] setBackBarButtonItem: backButton];
    [backButton release];
}

我有这样做的原因很多,我不想进入。无论如何,正如您将注意到的,要实现的视图类型之一是tableview。众所周知,tableview需要delegatedatasource。我想知道在运行时是否可以实现<UITableViewDelegate, UITableViewDataSource>,当我知道tableView是做出的选择时?

如果没有,是否有其他人有任何想法我怎么能这样做而不必在继承视图控制器类中手动实现我的委托和数据源?如果我在编译时(通常)在我的UIStandardViewController类中实现数据源和委托,那么我会收到警告,因为我需要在标准视图控制器类中实现强制数据源和委托方法。你会实现这些,然后在子类中覆盖它们吗?或者任何人都知道如何干净利落地做到这一点?

UPDATE:想知道,如果我刚刚在我的UIStandardViewController类中实现了委托和数据源,并且还实现了所需方法的空版本,那么当我不使用tableview时,这会是一个额外的开销吗? / p>

1 个答案:

答案 0 :(得分:3)

您可以编写一个实现数据源和表视图委托的控制器(只是控制器,而不是视图控制器)。您只会在需要时创建实例。

另请注意,您正在使用Factory模式。您应该使用类方法来创建新视图。签名类似于+(UIView *)viewWithType:(ViewTypeStyle) viewTypeSyle)

TableController.h

#import <Foundation/Foundation.h>

@interface TableController : NSObject <UITableViewDataSource,UITableViewDelegate>

@end

TableController.m

#import "TableController.h"

@implementation TableController

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 100;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *cellIdentifier = @"MyCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
    }
    cell.textLabel.text = [NSString stringWithFormat:@"%i", indexPath.row];
    return cell;
}
@end

ViewController.m

#import "ViewController.h"
#import "TableController.h"

@interface ViewController ()
@property(nonatomic,retain) UITableView *tableView;
@property(nonatomic,retain) TableController *controller;
@end

@implementation ViewController
@synthesize tableView = tableView_;
@synthesize controller = controller_;


-(void)dealloc
{
    self.tableView = nil;
    self.controller= nil;
    [super dealloc];
}
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.controller = [[[TableController alloc] init] autorelease];
    self.tableView = [[[UITableView alloc] initWithFrame:self.view.frame] autorelease];
    self.tableView.delegate = self.controller;
    self.tableView.dataSource= self.controller;

    [self.view addSubview:self.tableView];

    // Do any additional setup after loading the view, typically from a nib.
}

//...

@end