可以使用UIView作为ViewController吗?

huangapple go评论72阅读模式
英文:

can I use uiview as viewcontroller?

问题

以下是翻译好的部分:

Plan 1: 传统的MVC(Model-View-Controller)

#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 {
    // 处理AView的委托告知视图控制器的用户触摸
}

- (void)delegateBuserAction {
    // 处理BView的委托告知视图控制器的用户触摸
}

- (void)delegateCuserAction {
    // 处理CView的委托告知视图控制器的用户触摸
}

- (void)delegateDuserAction {
    // 处理DView的委托告知视图控制器的用户触摸
}

@end

Plan 2: 将子视图作为子视图控制器

#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 {
    // 刷新UI
}

#pragma mark - 处理用户操作
- (void)handleUserAction {
    // 不要委托给视图控制器,自行处理
}

@end

希望这对你有所帮助。如果你有任何问题,请随时提出。

英文:

I have a uiviewcontroller, it's view has 4 subviews, they don't need communication but need many user interaction and have many many content , but they need many network request to fetch data and refresh them. as the trandional mvc, viewcontroller fetch data and then refresh subviews. I think the viewcontroller is too heavy, can I take the 4 subviews as child viewcontroller, they request the data by themself. Is it a good practise or not ?

plan 1:tranditional 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

plan 2:Take subview as child viewcontroller

#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

答案1

得分: 0

可以使用容器视图而不是在一个视图控制器中使用多个视图。这样你可以根据你的视图控制器或视图将代码分开。在故事板中,只需拖动你想要作为视图的控制器的数量。

现在在你的主视图控制器中添加容器视图以将这些控制器添加到主视图控制器中。

现在在你的主视图控制器中创建这些容器视图的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")
        
        // 添加第一个视图控制器
        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)
        
        // 添加第二个视图控制器
        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)
        
        // 添加第三个视图控制器
        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)
    }
}

在控制台中,你会看到首先加载的是主视图控制器,然后是其他的。

现在你可以开始了。

英文:

You can use container views instead of using multiple views in one view controller.
In this way you can separate your code based on your view controller or view.

you just need to drag number off controllers you want as a view in the storyboard.

可以使用UIView作为ViewController吗?

Now in your main view controller add containers views in your view to add these controllers in the main view controller


可以使用UIView作为ViewController吗?

Now in your main view controller create IBOutlets of these container views and in your viewDidLoad add these controllers as child view and set their constraints (you can do this using storyboard as well) 

Your Main view controller class will look like this.

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)
        
    }
}

In the console you can see First MainViewController Loaded and then the others

可以使用UIView作为ViewController吗?

And you are good to go.

答案2

得分: 0

"Object / class 'naming' can be taken too literally. Don't confuse yourself with UIViewController being the only class that can 'control views.'

As a very simple example - well, it seems simple to me - let's look at a commonly used view: a UITextField ...

Suppose in my view controller code I add a UITextField as a subview. After that point, maybe in response to a 'Submit' button tap, I may:

  • get the text of that text field
  • do something with the resulting string

But... what does my controller do when the user is editing the field? Do I have code in my controller that says:

  • user tapped 'A' on the keyboard
  • figure out where the insertion point is
  • insert 'A' into that string
  • redraw the text field

No - all of that code is self-contained inside the UITextField view class itself.

So, in your case, you could think in terms of:

  • the view controller manages the size/positions of the 4 subviews
  • the view controller perhaps sets some initial properties of those 4 subviews
  • perhaps at some point the view controller asks each subview for an update of what it has been doing -- or maybe it never needs to.

It is perfectly acceptable for each subview to have its own internal code to handle 'doing its own thing.'

The trap that people run into - and the reason MVC is stressed - is when they write code in a subview (which is a subview of a subview of a subview...) that relies on a distinct coupling with one or more of its parent views.

TL;DR - if a view has code to manage (control) its subviews, that doesn't mean it has to be a UIViewController class, nor does it mean it violates the MVC pattern.

Edit - in response to comment...

A little searching, and we can find hundreds of articles / discussions about MVC and views vs controllers - far too much to go into here.

But, a quick example...

Suppose I have a view that looks like this:

可以使用UIView作为ViewController吗?

Each time a color quadrant is tapped, it increases the 'number of taps' for that quadrant.

Should I put all of the tap handling and value tracking into my UIViewController holding this view? Or, can I put that inside the UIView itself?

Personally, I would put it inside the view.

Now, suppose I then want to save the values to persistent storage (data file, database, remote db, etc)?

In that case, it would make much more sense to have the view (via protocol/delegate or closure) inform the controller of the changes. The controller would then handle updating the model / storing the data.

It could be argued that I've violated MVC ...

Of course, suppose I have 8 of these views? Would it make more sense to build a big, heavy controller with all of the tap and value tracking logic, and the view itself only, ummm, does nothing?

I'd suggest searching the web for uiviewcontroller vs uiview mvc -- and spend a few days reading all of the different opinions."

英文:

Object / class "naming" can be taken too literally. Don't confuse yourself with UIViewController being the only class that can "control views."

As a very simple example - well, it seems simple to me - let's look at a commonly used view: a UITextField ...

Suppose in my view controller code I add a UITextField as a subview. After that point, maybe in response to a "Submit" button tap, I may:

  • get the text of that text field
  • do something with the resulting string

But... what does my controller do when the user is editing the field? Do I have code in my controller that says:

  • user tapped "A" on the keyboard
  • figure out where the insertion point is
  • insert "A" into that string
  • redraw the text field

No - all of that code is self-contained inside the UITextField view class itself.

So, in your case, you could think in terms of:

  • the view controller manages the size/positions of the 4 subviews
  • the view controller perhaps sets some initial properties of those 4 subviews
  • perhaps at some point the view controller asks each subview for an update of what it has been doing -- or maybe it never needs to.

It is perfectly acceptable for each subview to have its own internal code to handle "doing its own thing."

The trap that people run into - and the reason MVC is stressed - is when they write code in a subview (which is a subview of a subview of a subview...) that relies on a distinct coupling with one or more of its parent views.

TL;DR - if a view has code to manage (control) its subviews, that doesn't mean it has to be a UIViewController class, nor does it mean it violates the MVC pattern.


Edit - in response to comment...

A little searching, and we can find hundreds of articles / discussions about MVC and views vs controllers - far too much to go into here.

But, a quick example...

Suppose I have a view that looks like this:

可以使用UIView作为ViewController吗?

Each time a color quadrant is tapped, it increases the "number of taps" for that quadrant.

Should I put all of the tap handling and value tracking into my UIViewController holding this view? Or, can I put that inside the UIView itself?

Personally, I would put it inside the view.

Now, suppose I then want to save the values to persistent storage (data file, database, remote db, etc)?

In that case, it would make much more sense to have the view (via protocol/delegate or closure) inform the controller of the changes. The controller would then handle updating the model / storing the data.

It could be argued that I've violated MVC ...

Of course, suppose I have 8 of these views? Would it make more sense to build a big, heavy controller with all of the tap and value tracking logic, and the view itself only, ummm, does nothing?

I'd suggest searching the web for uiviewcontroller vs uiview mvc -- and spend a few days reading all of the different opinions.

huangapple
  • 本文由 发表于 2023年2月24日 15:03:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/75553480.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定