【问题标题】:Implement Delegate at Run Time?在运行时实现委托?
【发布时间】:2012-02-03 09:50:50
【问题描述】:

我有一个通用视图控制器类,我的应用程序中的所有视图控制器类都继承自它,它具有以下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。我想知道当我知道 tableView 是所做的选择时,是否可以在运行时实现 <UITableViewDelegate, UITableViewDataSource>

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

更新:想知道,如果我只是在我的 UIStandardViewController 类中实现了委托和数据源,并且还实现了所需方法的空版本,那么当我不使用 tableview 时,这会不会有很多额外的开销?

【问题讨论】:

  • 不,这是不可能的。但是您可能想重新考虑您的结构,为什么要这样做?
  • a) 为了使用 loadView,您必须能够在其中初始化视图,b) 在子类中,我将诸如手势识别器之类的东西附加到视图并想要这样做在加载视图中正确。我的意思是为什么这很重要,最终,当您执行 loadview 时,无论如何您将按照以下方式实现这三个中的一个。
  • 是的,我明白你在这里问什么,但我认为你的 OO 设计中存在一个更根本的问题,应该以不同于你所问的方式来解决。跨度>
  • @dougw 我唯一能想到的就是分离出一个单独的 uitableviewcontroller 子类,这是我试图避免的,所以我不必复制代码
  • @CoDEFRo - 一种选择是使用多级继承,就像 Apple 为 UITableView 所做的那样。另一种选择是使用内部类作为委托和数据源。

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


【解决方案1】:

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

另请注意,您使用的是工厂模式。您应该使用类方法来创建新视图。签名类似于+(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

【讨论】:

  • 不知道我在做什么是一个实际的模式。为什么推荐使用类方法来创建视图?
  • 如果你在你的视图类中添加一个类方法,你不需要创建一个对象来创建另一个对象。请注意,你会发现这种图案遍布可可。即NSMutableArray *array = [NSMutableArray arrayWithCapacity:number]
  • 还有一点需要注意:这些方法应该自动释放。
  • 无论如何你可以举一个你正在谈论的控制器的例子吗?我想接受这个答案是正确的,只是无法验证控制器的东西。感谢您的帮助。
  • 但是你知道MVC?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-07
  • 1970-01-01
相关资源
最近更新 更多