什么是最有效的:定制或改编的ViewControllers?

时间:2015-03-05 17:32:10

标签: ios

作为一个不是训练有素的程序员的人,我现在已经在脑后留下了一个挥之不去的问题。假设我想向用户呈现5个单独的“集合”或信息视图,但每个ViewController需要一些自定义,例如更改标签,甚至位置和某些UIElements的类型..

一个例子是提供不同类型数据的统计数据(例如身高,体重,心率等)。所有视图都有标题,但它们不同,它们有图表,但有不同的基础类型(Int vs Double)和一些观点会比其他观点提供更多的统计数据。

你是“有效”意味着什么的判断,例如速度或便利性或未来的进一步定制,或其他。

更好的是,是为每个视图创建一个UIViewController子类,复制一些代码,还是用IFTTT,数组等逻辑创建一个VC,这样你就可以重用部分代码了?

2 个答案:

答案 0 :(得分:1)

我喜欢创建所有其他视图控制器继承的父视图控制器(让它称之为RootViewController)。这样,如果我需要做一些会影响他们的事情,我可以把它放在一个地方。

例如:

(RootViewController.h)

@interface RootViewController : UIViewController {
    UIActivityIndicatorView *spinner;
    UIView *spinnerBkgd;
}

- (void) setSpinnerMessage:(NSString *)message;
- (void) showSpinner;
- (void) hideSpinner;

@end

(RootViewController.m)

#import "RootViewController.h"

@interface RootViewController () {
    BOOL spinnerAnimating;
    UILabel *spinnerLabel;
}

@end

@implementation RootViewController

- (void) viewDidLoad {
    [super viewDidLoad];

    float longestDimension = self.view.frame.size.width;
    if (self.view.frame.size.width < self.view.frame.size.height)
        longestDimension = self.view.frame.size.height;

    UIView *spinnerParentView = self.navigationController.view;
    if (!spinnerParentView)
        spinnerParentView = self.view;

    spinnerBkgd = [[UIView alloc] initWithFrame:(CGRect){ 0, 0, longestDimension, longestDimension }];
    spinnerBkgd.backgroundColor = [UIColor blackColor];
    spinnerBkgd.alpha = 0.0f;
    [spinnerParentView addSubview:spinnerBkgd];

    spinnerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 400, 60)];
    spinnerLabel.textColor = [UIColor whiteColor];
    spinnerLabel.font = [UIFont systemFontOfSize:18.0f];
    spinnerLabel.textAlignment = NSTextAlignmentCenter;
    [spinnerBkgd addSubview:spinnerLabel];

    spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    spinner.frame = CGRectMake(0, 0, 100, 100);
    spinner.center = self.view.center;
    [spinnerBkgd addSubview:spinner];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(showSpinner)
                                                 name:JBB_SHOW_SPINNER
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(updateStatusMessage:)
                                                 name:JBB_UPDATE_STATUS_MESSAGE
                                               object:nil];
}

- (void) viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    spinnerAnimating = NO;

    [self resetInternalFrames];
}

- (void) setSpinnerMessage:(NSString *)message {
    spinnerLabel.text = message;
}

- (void) showSpinner {
    dispatch_async(dispatch_get_main_queue(), ^{
        if (!spinnerAnimating) {
            spinnerLabel.text = @"";
            [UIView animateWithDuration:0.8f
                                  delay:0.2f
                                options: UIViewAnimationOptionAllowAnimatedContent
                             animations:^{
                                 spinnerBkgd.alpha = 0.6f;
                             }
                             completion:^(BOOL finished){
                                 //NSLog(@"show spinner");
                             }];


            [spinner startAnimating];

            spinnerAnimating = YES;
        }
    });
}

- (void) hideSpinner {
    dispatch_async(dispatch_get_main_queue(), ^{
        //NSLog(@"hide spinner");
        spinnerBkgd.alpha = 0.0f;
        [spinner stopAnimating];
        spinnerLabel.text = @"";

        spinnerAnimating = NO;
    });
}

- (void) updateStatusMessage:(NSNotification*)notification {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self setSpinnerMessage:[notification.userInfo objectForKey:@"statusMessage"]];
    });
}

- (void) resetInternalFrames {
    spinner.center = self.view.center;
    spinnerLabel.center = (CGPoint) { self.view.center.x, self.view.center.y - 90 };
}

- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    [self resetInternalFrames];
}

@end

通过上面的示例,任何子类RootViewController的视图控制器都可以利用我的全屏微调器(加载内容时)。

我也开始制作&#34; Base Cells&#34;对于集合视图,其他&#34; Cells&#34;子类。通常,有一些共同的功能可以放入一个由所有东西共享的基类中。任何需要条件的东西(if(x支持)然后显示y)都需要进入特定的子类。但是,如果它是2个或更多子类中的东西,我将子类化为root,并生成其他2个子类。

粗略的例子,有名称:

RootCollectionViewCell:UICollectionViewCell
+-- RootScrollviewCollectionViewCell:RootCollectionViewCell
   +-- FriendCell:RootScrollviewCollectionViewCell
   +-- MediaCell:RootScrollviewCollectionViewCell
       +-- PhotosCell:MediaCell
       +-- VideosCell:MediaCell
+-- DetailCell:RootCollectionViewCell
+-- FeelingsCell:RootCollectionViewCell

这样,照片和视频单元就是mediacell的子类,mediacell是我的scrollview单元的子类。其余的只显示内容而没有滚动视图,因此从根目录继承。

答案 1 :(得分:0)

如果你的viewConrollers有一些常见的'逻辑代码',即创建一些统计信息或设置一些信息,那应该驻留在一个parentViewController中,并且所有信息都应该继承该父代。

UI自定义当然应该在单独继承的UIViewControllers中完成。

你几乎不应该编写一个ViewController类,它有一大部分if / else语句设置自己的UI。

执行前者将使代码更清晰,并提供更多可维护性。

到目前为止,我见过的几乎所有代码都是人们使用这种特殊的方法。一些例外,其中2个视图非常紧密地链接,而简单的if / else将解决它们之间的差异。