Implement Delegate at Run Time?

2019-04-15 19:36发布

问题:

I have a universal view controller class which all of the view controller classes in my app inherit from which has the following loadView method:

- (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];
}

I have it done this way for a lot of reasons that I don't feel like getting into. Anyhow, as you'll notice, one of the view types to implement is a tableview. As we all know, a tableview needs a delegate and a datasource. I was wondering if it's possible to implement the <UITableViewDelegate, UITableViewDataSource> at run time when I know a tableView is the choice that was made?

If not, does anyone else have any ideas how I can do this without having to manually implement my delegate and datasource in the inheriting view controller class? If I implement the data source and delegate at compile time (normally) in my UIStandardViewController class, then I get warning because I need to implement the mandatory data source and delegate methods in my standard view controller class. Would you implement these and then just override them in child class? Or anyone have any idea of how I can do this cleanly?

UPDATE: Was wondering, if I just implemented the delegate and data source in my UIStandardViewController class, and also implemented empty versions of the required methods, would this be a lot of extra overhead when I didn't use a tableview?

回答1:

You can write a controller (just controller, not view controller) that implements data source and the table view delegate. You will only create an instance if needed.

Also note, that you are using the Factory pattern. You should use a class method to create new views. The signature would be something like +(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