I'm trying to add a subview to my main view. Here's the relevant code from my viewController:
- (void)viewDidLoad {
[super viewDidLoad];
MyUIViewSubclass* myView = [[MyUIViewSubclass alloc] init];
[self.view addSubview:myView]; // self.view is a simple UIView
[myView setNeedsDisplay];
}
drawRect in myView doesn't get called.
However, if I use a MyUIViewSubclass as the main view for the viewController (setting it in Interface Builder), drawRect does get called.
What do I need to do to get drawRect called in my subView?
In your subclass you should use the designated initialiser for UIView:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
//Implementation code...
}
}
Ok, figured it out. Wasn't setting the frame of my subView.
Related
I use the "jazzHands" keyframe animation library to help my App finish the introduction view.jazzHands link
In the official example, it use a init method to configure the subViews. But I found when I use the viewDidLoad or viewWillAppear or view...,etc methods to configure the subViews, the subView will never add to the superView(self.scrollView), in here, self.scrollView is a subView in the self.view, see the original code below:
#import "IFTTTAnimatedScrollViewController.h"
#implementation IFTTTAnimatedScrollViewController
- (id)init
{
if (self = [super init]) {
self.animator = [IFTTTAnimator new];
self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
self.scrollView.delegate = self;
[self.view addSubview:self.scrollView];
}
return self;
}
But I found that you can add a subView to the self.view and it works! Why??
help me......
I solved it.....
The reason that I can't add the subView through the viewDidLoad method is that the self.scrollView has already release(nil)
when set self.view.tag is 10 in loadView ,but in viewDidload it's tag is 0
why ? thanks
- (void)loadView
{
[super loadView];
NSLog(#"loadView %d",self.view.tag);
[self.view setTag:10];
self.view = [[UIView alloc] initWithFrame:self.view.frame];
self.view.backgroundColor = [UIColor yellowColor];
}
#pragma mark view loaded
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"ViewDidload %d",self.view.tag);
[self.view setTag:10];
}
The loadView method is not usually implemented. The system calls it in order to create your view hierarchy. At the time it's called, your views will not exist.
Why are you implementing loadView? You probably should not be.
To quote the docs:
If you use Interface Builder to create your views and initialize the
view controller, you must not override this method.
What code are you putting in your loadView method?
I have customized UIView to create a custom UI component.
The hierarchy of views are this way.
----Custom UIView
----------------UIScrollView
-----------------------------Sub Views in ScrollView
-(id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if(self){
//Allocation and Initialization of ScrollView
//...
[super addSubView:scrollView];
}
return self;
}
- (void)layoutSubviews {
DLog(#"%#",[NSThread callStackSymbols]);
[super layoutSubviews];
[self reloadData];
}
//This method can be used to reload the entire control
-(void)reloadData{
//Reload the subviews of control
}
When ever the scroll view is scrolled, the layoutSubviews method gets called in iOS version 4.3. But in case of versions above 4.3 (5.0 , 6.0) this event handler does not get called.
In my use case, I do not wanted the layoutsubviews to get called.
How can I ensure that I have a scroll view when scrolled that does not trigger the layoutsubviews method?
The solution I came up with is below:
Add a container UIView (for reference ScrollViewHolder)on top of the customized view
Then add the UIScrollView on the view ScrollViewHolder.
----Custom UIView
----------------Another UIView
-------------------------------UIScrollView
--------------------------------------------Sub Views in ScrollView
The init method is now changed to the following:
-(id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if(self){
//Allocation and Initialization of Container View
[super addSubView:ScrollViewHolder];
//Allocation and Initialization of ScrollView
//...
[ScrollViewHolder addSubView:scrollView];
}
return self;
}
I have a subview with various methods that update my data and then call [self setNeedsDisplay]; to invoke the drawRect to update the view.
If I call one of these methods from the viewController, the data gets updated but the drawRect is not called.
The subView is added as a property of the viewController:
#property (nonatomic,retain) MyView *myView;
and initiated in the viewController:
#synthesize myView;
- (void)viewDidLoad {
[super viewDidLoad];
myView = [[MyView alloc] init];
}
I call a method on myView later in the viewController with [myView exampleMethod];
How can I make sure methods called from the viewController redraw the subView?
Won't you have to call
[self.view setNeedsDisplay];
:)
The default view in a view controller is called just "view" if you want to make your own, you have to add it to that or exchange the view with that, like this:
self.view = myView;
//or
[self.view addSubview:myView];
Can anyone explain why viewDidLoad does not get called when loadView is used? It's my understanding that viewDidLoad should still get called.
- (void)loadView
{
CGRect currentFrame = [[UIScreen mainScreen] applicationFrame];
UIView* myView = [[UIView alloc] initWithFrame:CGRectMake(currentFrame.origin.x, currentFrame.origin.y, currentFrame.size.width, currentFrame.size.height)];
myView.backgroundColor = [UIColor redColor];
self.view = myView;
[myView release];
[super loadView];
}
- (void)viewDidLoad {
//this never happens
NSLog(#"VIEW DID LOAD!");
[super viewDidLoad];
}
I've just found out that viewDidLoad won't be called if you call loadView manually in your application.
If you call loadView manually you have to call viewDidLoad manually as well.
More over according to apple docs you shouldn't call [super loadView] as it will overwrite your view with a default UIView.
You must have a warning here:
NSLog("VIEW DID LOAD!");
Instead, you should write like this (the # sign is necessary):
NSLog(#"VIEW DID LOAD!");
viewDidLoad will not get called when you create instance of ViewController. When you are pushing it to navigation controller or present it as model viewcontroller, then only the viewDidLoad get called. Until and unless you are presenting viewController, these delegate will not get called. And one more thing, if your viewcontroller presentation over, and still it remains in the stack or memory, then viewDidLoad method will not get called again because its already load the view. Then viewWillAppear and viewDidAppear delegates only get called when you present the same viewController.