提问人:ming 提问时间:2/24/2023 最后编辑:ming 更新时间:3/1/2023 访问量:72
我可以将UIViewe用作ViewController吗?
can I use uiview as viewcontroller?
问:
我有一个 uiviewcontroller,它的视图有 4 个子视图,它们不需要通信,但需要许多用户交互并有很多内容,但它们需要许多网络请求来获取数据并刷新它们。作为 trandional MVC,ViewController 获取数据,然后刷新子视图。我认为视图控制器太重了,我可以将 4 个子视图作为子视图控制器吗,它们自己请求数据。这是一个好的做法吗?
计划一:传统MVC
#import "TTViewController.h"
@interface TTViewController ()
@property (nonatomic, strong) id modelA;
@property (nonatomic, strong) id modelB;
@property (nonatomic, strong) id modelC;
@property (nonatomic, strong) id modelD;
@property (nonatomic, strong) CustomView *aView;
@property (nonatomic, strong) CustomView *bView;
@property (nonatomic, strong) CustomView *cView;
@property (nonatomic, strong) CustomView *dView;
@end
@implementation TTViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.aView];
[self.view addSubview:self.bView];
[self.view addSubview:self.cView];
[self.view addSubview:self.dView];
[self reqeustAData];
[self requetBData];
[self requestCData];
[self reqeustDData];
}
- (void)reqeustAData {
[self.aView refresh:modelA];
}
- (void)requetBData {
[self.bView refresh:modelB];
}
- (void)requestCData {
[self.cView refresh:modelC];
}
- (void)reqeustDData {
[self.dView refresh:modelD];
}
#pragma mark - delegate
- (void)delegateAuserAction {
// handle user's touch when Aview's delegate tell vc
}
- (void)delegateBuserAction {
// handle user's touch when Bview's delegate tell vc
}
- (void)delegateCuserAction {
// handle user's touch when Cview's delegate tell vc
}
- (void)delegateDuserAction {
// handle user's touch when Dview's delegate tell vc
}
@end
方案二:将子视图作为子视图控制器
#import "TTViewController.h"
#import "CustomView.h"
@interface TTViewController ()
@property (nonatomic, strong) CustomView *aView;
@property (nonatomic, strong) CustomView *bView;
@property (nonatomic, strong) CustomView *cView;
@property (nonatomic, strong) CustomView *dView;
@end
@implementation TTViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.aView];
[self.view addSubview:self.bView];
[self.view addSubview:self.cView];
[self.view addSubview:self.dView];
[self.aView reqeust];
[self.bView reqeust];
[self.cView reqeust];
[self.dView reqeust];
}
@end
#import "CustomView.h"
@interface CustomView ()
@property (nonatomic, strong) id model;
@end
@implementation CustomView
- (void)reqeust {
[self refreshUI:model];
}
- (void)refreshUI:(id)model {
}
#pragma mark - handle user action
- (void)handleUserAction {
// don't delegate to vc, handle it by self
}
@end
答:
您可以使用容器视图,而不是在一个视图控制器中使用多个视图。这样,您可以根据视图控制器或视图来分离代码。你只需要将数字从你想要的控制器中拖出作为情节提要中的视图。

现在,在主视图控制器中,在视图中添加容器视图,以将这些控制器添加到主视图控制器中
现在,在主视图控制器中,创建这些容器视图的 IBOutlets,并在 viewDidLoad 中将这些控制器添加为子视图并设置其约束(也可以使用情节提要执行此操作) 主视图控制器类将如下所示。
class MainViewController: UIViewController {
@IBOutlet weak var viewThree: UIView!
@IBOutlet weak var viewTwo: UIView!
@IBOutlet weak var viewOne: UIView!
override func viewDidLoad() {
super.viewDidLoad()
print("Main view Controller Loaded")
//add first view controller
let controllerOne = storyboard!.instantiateViewController(withIdentifier: "OneViewController") as! OneViewController
addChild(controllerOne)
controllerOne.view.translatesAutoresizingMaskIntoConstraints = false
self.viewOne.addSubview(controllerOne.view)
NSLayoutConstraint.activate([
controllerOne.view.leadingAnchor.constraint(equalTo: self.viewOne.leadingAnchor, constant: 0),
controllerOne.view.trailingAnchor.constraint(equalTo: self.viewOne.trailingAnchor, constant: 0),
controllerOne.view.topAnchor.constraint(equalTo: self.viewOne.topAnchor, constant: 0),
controllerOne.view.bottomAnchor.constraint(equalTo: self.viewOne.bottomAnchor, constant: 0)
])
controllerOne.didMove(toParent: self)
// add second view controller
let controllerTwo = storyboard!.instantiateViewController(withIdentifier: "TwoViewController") as! TwoViewController
addChild(controllerTwo)
controllerTwo.view.translatesAutoresizingMaskIntoConstraints = false
self.viewTwo.addSubview(controllerTwo.view)
NSLayoutConstraint.activate([
controllerTwo.view.leadingAnchor.constraint(equalTo: self.viewTwo.leadingAnchor, constant: 0),
controllerTwo.view.trailingAnchor.constraint(equalTo: self.viewTwo.trailingAnchor, constant: 0),
controllerTwo.view.topAnchor.constraint(equalTo: self.viewTwo.topAnchor, constant: 0),
controllerTwo.view.bottomAnchor.constraint(equalTo: self.viewTwo.bottomAnchor, constant: 0)
])
controllerTwo.didMove(toParent: self)
// add Third view controller
let controllerThree = storyboard!.instantiateViewController(withIdentifier: "ThreeViewController") as! ThreeViewController
addChild(controllerThree)
controllerThree.view.translatesAutoresizingMaskIntoConstraints = false
self.viewThree.addSubview(controllerThree.view)
NSLayoutConstraint.activate([
controllerThree.view.leadingAnchor.constraint(equalTo: self.viewThree.leadingAnchor, constant: 0),
controllerThree.view.trailingAnchor.constraint(equalTo: self.viewThree.trailingAnchor, constant: 0),
controllerThree.view.topAnchor.constraint(equalTo: self.viewThree.topAnchor, constant: 0),
controllerThree.view.bottomAnchor.constraint(equalTo: self.viewThree.bottomAnchor, constant: 0)
])
controllerThree.didMove(toParent: self)
}
}
在控制台中,您可以看到 First MainViewController Loaded,然后是其他
你已经准备好了。
对象/类的“命名”可能过于字面意思。不要将自己混淆为唯一可以“控制视图”的类。UIViewController
作为一个非常简单的例子 - 嗯,对我来说似乎很简单 - 让我们看一个常用的视图:一个......UITextField
假设在我的视图控制器代码中,我添加了一个作为子视图。在那之后,也许为了响应“提交”按钮点击,我可能会:UITextField
- 获取该文本字段的文本
- 对生成的字符串执行某些操作
但。。。当用户编辑字段时,我的控制器会做什么?我的控制器中是否有代码显示:
- 用户点击键盘上的“A”
- 找出插入点的位置
- 在该字符串中插入“A”
- 重新绘制文本字段
否 - 所有这些代码都是自包含在视图类本身中的。UITextField
因此,就您而言,您可以考虑:
- 视图控制器管理 4 个子视图的大小/位置
- 视图控制器可能会设置这 4 个子视图的一些初始属性
- 也许在某个时候,视图控制器会要求每个子视图更新它一直在做的事情——或者它可能永远不需要。
每个子视图都有自己的内部代码来处理“做自己的事情”是完全可以接受的。
人们遇到的陷阱 - 以及 MVC 受到压力的原因 - 是当他们在子视图(子视图的子视图的子视图的子视图)中编写代码时,该子视图依赖于与其一个或多个父视图的不同耦合。
TL;DR - 如果 a 有代码来管理(控制)其子视图,这并不意味着它必须是一个类,也不意味着它违反了 MVC 模式。view
UIViewController
编辑 - 回应评论...
稍加搜索,我们可以找到数百篇关于 MVC 和视图与控制器的文章/讨论 - 这里太多了。
但是,一个简单的例子......
假设我有一个视图,如下所示:
每次点击颜色象限时,都会增加该象限的“点击次数”。
我是否应该将所有点击处理和值跟踪都放在我持有此视图中?或者,我可以把它放在里面吗?UIViewController
UIView
就我个人而言,我会把它放在视图中。
现在,假设我想将值保存到持久存储(数据文件、数据库、远程数据库等)中?
在这种情况下,让视图(通过协议/委托或闭包)通知控制器更改会更有意义。然后,控制器将处理更新模型/存储数据。
可以说我违反了 MVC ......
当然,假设我有 8 个这样的视图?构建一个具有所有点击和值跟踪逻辑的大型、重型控制器,并且视图本身,嗯,什么都不做,会更有意义吗?
我建议在网上搜索 - 并花几天时间阅读所有不同的意见。uiviewcontroller vs uiview mvc
评论