英文:
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.

Now in your main view controller add containers views in your view to add these controllers in the main view controller
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
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:
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:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论