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
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:
But... what does my controller do when the user is editing the field? Do I have code in my controller that says:
No - all of that code is self-contained inside the UITextField
view class itself.
So, in your case, you could think in terms of:
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.