我可以将UIViewe用作ViewController吗?

can I use uiview as viewcontroller?

提问人:ming 提问时间:2/24/2023 最后编辑:ming 更新时间:3/1/2023 访问量:72

问:

我有一个 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
iOS Objective-C 体系结构 UIVieviceController

评论


答:

0赞 naveen 2/24/2023 #1

您可以使用容器视图,而不是在一个视图控制器中使用多个视图。这样,您可以根据视图控制器或视图来分离代码。你只需要将数字从你想要的控制器中拖出作为情节提要中的视图。

enter image description here 现在,在主视图控制器中,在视图中添加容器视图,以将这些控制器添加到主视图控制器中

enter image description here

现在,在主视图控制器中,创建这些容器视图的 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,然后是其他

enter image description here

你已经准备好了。

0赞 DonMag 2/24/2023 #2

对象/类的“命名”可能过于字面意思。不要将自己混淆为唯一可以“控制视图”的类。UIViewController

作为一个非常简单的例子 - 嗯,对我来说似乎很简单 - 让我们看一个常用的视图:一个......UITextField

假设在我的视图控制器代码中,我添加了一个作为子视图。在那之后,也许为了响应“提交”按钮点击,我可能会:UITextField

  • 获取该文本字段的文本
  • 对生成的字符串执行某些操作

但。。。当用户编辑字段时,我的控制器会做什么?我的控制器中是否有代码显示:

  • 用户点击键盘上的“A”
  • 找出插入点的位置
  • 在该字符串中插入“A”
  • 重新绘制文本字段

否 - 所有这些代码都是自包含在视图类本身中的。UITextField

因此,就您而言,您可以考虑:

  • 视图控制器管理 4 个子视图的大小/位置
  • 视图控制器可能会设置这 4 个子视图的一些初始属性
  • 也许在某个时候,视图控制器会要求每个子视图更新它一直在做的事情——或者它可能永远不需要。

每个子视图都有自己的内部代码来处理“做自己的事情”是完全可以接受的。

人们遇到的陷阱 - 以及 MVC 受到压力的原因 - 是当他们在子视图(子视图的子视图的子视图的子视图)中编写代码时,该子视图依赖于与其一个或多个父视图的不同耦合

TL;DR - 如果 a 有代码来管理(控制)其子视图,这并不意味着它必须是一个类,也不意味着它违反了 MVC 模式。viewUIViewController


编辑 - 回应评论...

稍加搜索,我们可以找到数百篇关于 MVC 和视图与控制器的文章/讨论 - 这里太多了。

但是,一个简单的例子......

假设我有一个视图,如下所示:

enter image description here

每次点击颜色象限时,都会增加该象限的“点击次数”。

我是否应该将所有点击处理和值跟踪都放在我持有此视图中?或者,我可以把它放在里面吗?UIViewControllerUIView

就我个人而言,我会把它放在视图中。

现在,假设我想将值保存到持久存储(数据文件、数据库、远程数据库等)中?

在这种情况下,让视图(通过协议/委托或闭包)通知控制器更改会更有意义。然后,控制器将处理更新模型/存储数据。

可以说我违反了 MVC ......

当然,假设我有 8 个这样的视图?构建一个具有所有点击和值跟踪逻辑的大型、重型控制器,并且视图本身,嗯,什么都不做,会更有意义吗?

我建议在网上搜索 - 并花几天时间阅读所有不同的意见。uiviewcontroller vs uiview mvc

评论

0赞 ming 2/28/2023
因此,customView 会发送网络请求,因为它需要数据来刷新其子视图。customView 的角色是 view,customView 获取的数据是 model。VC在哪里?DID 视图保留模型直接违反了 MVC 架构
0赞 ming 3/1/2023
一个非常好的例子!我明白了,我会继续搜索你建议@DonMag的内容