3

假设您实现了一个自定义表格视图和一个自定义视图控制器(它主要模仿UITableViewControllers 的行为,但是当以编程方式初始化时,...

@interface Foo : MyCustomTableViewController ...

Foo *foo = [[Foo alloc] init];

...foo.view是一种类,MyCustomTableView而不是UITableView

// MyCustomTableView.h

@protocol MyTableViewDelegate <NSObject, UITableViewDelegate>

// ...

@end

@protocol MyTableViewDataSource <NSObject, UITableViewDataSource>

// ...

@end

@interface MyCustomTableView : UITableView

// ...

@end

// MyCustomTableViewController.h

@interface MyCustomTableViewController : UIViewController

// ...

@end

您应该如何init以正确的顺序/方式实现/覆盖方法,以便您可以通过以编程方式进行子类化或通过在 Interface Builder 中将自定义类类型设置为任何自定义 nib 文件来创建和使用MyCustomTableView这两种方法的实例?MyCustomTableViewControllerMyCustomTableView

需要注意的是,这正是目前UITableView(主要是 UIKit)的工作方式:开发人员可以通过编程方式或从 nib 创建和使用,无论是File ownerview视图还是更复杂层次结构中的某个子视图,只需分配数据源或委托,你很高兴......

到目前为止,如果您子类化,我设法让它工作,我将在MyCustomTableViewController其中创建一个实例MyCustomTableView并将其分配给方法;但无法弄清楚, , , , 或其他任何操作方式。我迷失在生命周期链中,每次都以黑色视图/屏幕结束。self.viewloadViewinitWithNibName:bundle:initWithCoder:awakeFromNibawakeAfterUsingCoder:

谢谢。

4

3 回答 3

0

UITableViewController 如何加载它的表,无论是否连接到界面构建器,这都是一个真正的谜,但是我想出了一个很好的方法来模拟这种行为。

我想用一个包含 MKMapView 的可重用视图控制器来实现这一点,我想出了一个技巧,通过检查视图的背景颜色来实现它。

这很难的原因是因为任何对 self.view 的调用都会导致情节提要加载或加载默认的 UIView(如果不存在)。如果用户真的没有设置视图,则无法确定这两个步骤之间是否存在。所以诀窍是来自故事板的那个有颜色,默认的颜色是零。

所以现在我有一个 mapViewController 可以在代码或情节提要中使用,甚至不关心是否设置了地图。很酷。

- (void)viewDidLoad
{
    [super viewDidLoad];

    //magic to work without a view set in the storboard or in code.
    //check if a view has been set in the storyboard, like what UITableViewController does.
    //check if don't have a map view
    if(![self.view isKindOfClass:[MKMapView class]]){
        //check if the default view was loaded. Default view always has no background color.
        if([self.view isKindOfClass:[UIView class]] && !self.view.backgroundColor){
            //switch it for a map view
            self.view = [[MKMapView alloc] initWithFrame:CGRectZero];
            self.mapView.delegate = self;
        }else{
            [NSException raise:@"MapViewController didn't find a map view" format:@"Found a %@", self.view.class];
        }
    }
于 2013-12-09T07:55:10.227 回答
-1

这就是我解决自己问题的方法:

- (void)loadView
{
    if (self.nibName) {
        // although docs states "Your custom implementation of this method should not call super.", I am doing it instead of loading from nib manually, because I am too lazy ;-)
        [super loadView];
    }
    else {
        self.view = // ... whatever UIView you'd like to create
    }
}
于 2012-09-21T15:18:18.347 回答
-1

我在编写此类类时使用的策略是尽可能晚地推迟我的自定义初始化代码。如果我可以等待viewDidLoadviewWillAppear进行任何设置,并且不编写任何自定义代码或类似方法initinitWithNibName:bundle:我将知道我的对象已像父类一样被初始化,无论它以何种方式实例化。我经常设法编写我的类而不重写这些init方法。

如果我发现我需要将初始化代码放入init方法中,我的策略是只编写一个版本的初始化代码,将其放入单独的方法中,然后覆盖所有的 init 方法。被覆盖的方法调用自己的超类版本,检查是否成功,然后调用我的内部初始化方法。

如果这些策略失败了,那么这个类的对象的实例化方式真的会有所不同,我将为各种方法中的每一个编写自定义init方法。

于 2012-09-21T14:47:54.527 回答