重构大方法以在 UIViewController 中创建自定义 UIView
Posted
技术标签:
【中文标题】重构大方法以在 UIViewController 中创建自定义 UIView【英文标题】:Refactoring large method to create custom UIView in UIViewController 【发布时间】:2014-02-14 17:35:18 【问题描述】:我正在尝试在我的UIViewController
中正确重构一个方法。我对 Objective-C 相当陌生,因此试图了解这里最好的方法是什么。方法是在屏幕上创建一个自定义底栏。它是一个UIView
,有多个子视图和自动布局。
目前,条形图的整个创建是在一种方法中,大约 300 行。理想情况下,我想将其移入子类,但需要了解如何正确完成。
这里是方法的开始,以了解它的作用:
-(void)setupBottomBarViewForOrientation:(UIInterfaceOrientation)forOrientation
UIView *bottomBarInnerView = [UIView autolayoutView];
[self.bottomBarView addSubview:bottomBarInnerView];
NSDictionary *views = NSDictionaryOfVariableBindings(bottomBarInnerView);
NSDictionary *bottomBarMetrics = @@"minVPadding":@2.0;
[self.bottomBarView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(minVPadding)-[bottomBarInnerView]-(minVPadding)-|" options:0 metrics:bottomBarMetrics views:views]];
[self.bottomBarView addConstraint:[NSLayoutConstraint constraintWithItem:bottomBarInnerView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.bottomBarView attribute:NSLayoutAttributeCenterX multiplier:1 constant:1]];
NSString *word = @"Word";
NSUInteger letterCount = [word length];
NSMutableArray *viewList = [[NSMutableArray alloc] init]; // Create an array to store the tiles within
NSDictionary *metrics = @@"letterTileMinHeight":@40.0,@"padding":@3.0,@"letterViewPadding":@5.0; // Constraint metrics
... [OTHER LOGIC] which create multiple subviews further UIViews and UILabels ...
将其移入UIView
子类的最佳途径是什么?那么自定义代码进入哪里(哪个方法)?还有如何从 VC 中调用并创建自动布局?
我了解子类化等,主要问题是如何创建自动布局约束。后来的一些自动布局约束从UIViewController
链接到self.view,那么这个视图是否应该被传递到创建横幅栏子视图的新方法中??
【问题讨论】:
【参考方案1】:你绝对应该让它成为 UIView 的子类。传递配置它所需的任何内容。现在看起来像一本字典,所以你可以调用你的 init 方法类似
-(MyNewView*)initWithDictionary:(NSDictionary*)dict
视图子类将为其中的事物设置自己的约束。如果使用它的视图控制器需要对整个子视图进行约束,那么它应该添加它们,但它不应该与其中的那些混淆。
这是一个子视图初始化方法的示例,它接受字符串和计数,创建两个标签来显示它们,并将它们添加到自身。您可以 layoutSubviews 或 autolayout 将它们定位在新视图中。
-(BottomBarInnerView *)initWithString:(NSString *)string count:(NSNumber*)count
self = [super initWithFrame:CGRectZero];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
label.text = string;
[self addSubview:label];
UILabel *countLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 0, 20, 10)];
countLabel.text = [count stringValue];
[self addSubview:countLabel];
return self;
由于视图使用 CGRectZero,因此您需要在创建它时调整它的大小,所以它是这样的:
BottomBarInnerView* bottomBarInnerView = [[BottomBarInnerView alloc] initWithString:@"Hi Mom" count:@(42)];
bottomBarInnerView.frame = CGRectMake(0, 200, 100, 50);
[self.view addSubview:bottomBarInnerView];
或者,您可以为其添加约束,并让自动布局为您设置框架。
【讨论】:
好的,我是否创建UIView
的子视图,然后在 init 方法中调用 initWithDictionary 或我最终使用的任何内容?我已经看到它使用 layoutSubViews 等完成,我应该在实际的子视图类中使用什么方法/方法?
在您的 initWithDictionary 中您将执行 self = [super init],这会将您的对象变成 UIView。在那之后,做任何你需要做的事情来让它成为你的。添加子视图,当然,然后在 layoutSubviews 中布局它们,或者使用自动布局,这似乎是你最初想要做的。
嘿@jsd。这里的实际要求是从问题中生成bottomBarInnerView
。不需要字典,因为它用于该视图的约束。我需要将UIView
子类化为bottomBarInnerView
。因此,字符串、计数等将被传递到相关的新 init 方法和代码 [AFTER] 上面的大块中。无论如何,问题是我如何子类化UIView
并正确配置它。 IE。我要继承UIView
,然后调用 alloc/init - 然后将所有代码放在后面。还是我创建一个自定义的initWithString
方法然后调用...
...alloc/initWithString ?然后在子类的那个方法中它调用super self
?抱歉,整个调用子类和子类中的自定义 init 方法导致了混乱。谢谢
我已经编辑了我的答案以包含一个代码示例,因为这个评论太长了。以上是关于重构大方法以在 UIViewController 中创建自定义 UIView的主要内容,如果未能解决你的问题,请参考以下文章
将 UITableViewController 子类重构为 UIViewController 子类