I have a child view controller looking like this:
I am embedding it into another parent view controller,
#implementation ContainmentViewController
- (id)initWithCoder:(NSCoder *)decoder {
if(self = [super initWithCoder:decoder]) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.prototypeVC = [self.storyboard instantiateViewControllerWithIdentifier:#"PrototypeViewController"];
[self addChildViewController:self.prototypeVC];
[self.view addSubview:self.prototypeVC.view];
[self.prototypeVC didMoveToParentViewController:self];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
This is how it should look like in the original child VC:;
This is how it looks like in the ContainmentVC:
What am I doing wrong?
NOTE: I have to pick "Wants full screen" on the ChildVC otherwise I will see a 20px white space at the top.
I got fed up with playing with storyboard.
So I unchecked Wants Full Screen
and added the following:
self.prototypeVC.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
Everything works now
Related
I'm trying to position a button so that it is always an X amount of pixels from the bottom of the screen. The view is laid out programmatically using auto layout. If I use: #"V:|-44-[closeModalButton]" the object aligns 44 pixels from the top of the screen as expected. However, #"V:[closeModalButton]-44-|" causes the button to never show up. It seems like it ought to be pretty straightforward, so I feel like I'm missing something really obvious.
Implementation of view
#import "DetailView.h"
#implementation DetailView
#synthesize closeModalButton;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.backgroundColor = [UIColor whiteColor];
CGRect aFrame = [[UIScreen mainScreen] bounds];
self.frame = aFrame;
closeModalButton = [UIButton buttonWithType:UIButtonTypeCustom];
[closeModalButton setImage: [UIImage imageNamed:#"closeButton.png"] forState:UIControlStateNormal];
[closeModalButton setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addSubview:closeModalButton];
NSDictionary *viewArranging = NSDictionaryOfVariableBindings(closeModalButton);
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[closeModalButton(44)]-44-|"
options:0
metrics:0
views:viewArranging]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-149-[closeModalButton(44)]-149-|"
options:0
metrics:0
views:viewArranging]];
}
return self;
}
#end
View controller
#import "DetailViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
{
DetailView *_detailView;
}
- (void)loadView
{
_detailView = [[DetailView alloc] init];
[self setView:_detailView];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[_detailView.closeModalButton addTarget:self
action:#selector(closeModalButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
}
- (void)closeModalButtonPressed:(UIButton *)sender{
[self dismissViewControllerAnimated:YES
completion:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Ok, so it looks like DetailView.h subclassed UIScrollView rather than UIView. Setting the proper subclass caused the constraints to operate as expected.
I know this question has been asked a countless number of times, although I have not been able to get it to work at all, literally no answer has worked, maybe I'm not copying the code across correctly, but either way it wont work.
Anyway, my application's view controller layout is as follows, note that this is a Tabbed Application, NOT a single View Application:
Master Tab Bar Controller > Branches off into multiple Navigation Bar Controllers (all referencing to the same CustomNavigationController class) > Under each Nav Controller are a number of UIViewControllers, some of which are referencing custom view controller classes. (see pic for a visual representation of the hierarchy)
My question is: how can I lock the orientation of all pages in my application to portrait mode ONLY, however allow some pages (UIViewControllers) to be able to rotate to landscape if the user rotates the device? (The pages marked with a star, in the image above are the ones I would like to ALLOW rotation for)
Remember the view controllers that I want to allow rotation for are children to a Navigation controller which is also a child to a Tab Bar Controller. Also, note that one of the View controllers isn't under a Navigation controller, it is just under the Tab Bar controller, not sure how much this affects though.
Thank you so much
Code from the relevant classes of my app
Tab Bar Controller Code (note there is not meaningful code in here as I never used to have a class for this)
#interface TabBarController ()
#end
#implementation TabBarController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Navigation Controller Class (Also never had a class for this
#interface NavigationBar ()
#end
#implementation NavigationBar
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = #"NavigationController";
}
return self;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Home Page Class (Must be locked in portrait)
#interface HomePage ()
#end
#implementation HomePage
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = #"HomePage";
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// If the condition is not true/not YES, than create and show alert.
if (![[NSUserDefaults standardUserDefaults]
boolForKey:#"didShowOneTimeAlert"]) {
//Define and Edit the Alert details.
UIAlertView *zoomTip = [[UIAlertView alloc] initWithTitle:#"Tips" message:#"On all web site and map pages, pinch in and out to zoom. \n \n On the 'Program' page, tap on a session to view more details." delegate:self cancelButtonTitle:#"Okay" otherButtonTitles:nil];
//Show the alert
[zoomTip show];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"didShowOneTimeAlert"];
[[NSUserDefaults standardUserDefaults] synchronize];
} // End if
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Map Class (A page that displays a map and MUST be able to rotate)
#interface MezzanineLevelMap ()
#end
#implementation MezzanineLevelMap
#synthesize scrollView, imageView;
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return imageView;
}
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *tempImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Mezzanine Level"]];
self.imageView = tempImageView;
scrollView.maximumZoomScale = 1;
scrollView.minimumZoomScale = .25;
scrollView.clipsToBounds = YES;
scrollView.delegate = self;
[scrollView addSubview:imageView];
scrollView.zoomScale = .25;
// Change scroll view sizes according to the screen size
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
CGSize result = [[UIScreen mainScreen] bounds].size;
if (result.height == 480) {
[scrollView setFrame:CGRectMake(0, 5, 320, 475)];
} else {
[scrollView setFrame:CGRectMake(0, 5, 320, 563)];
} // End if
} // End if
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Just implement the following in your view controller (iOS 6+):
- (BOOL)shouldAutorotate {
return NO;
}
In each viewcontroller you can write following code and return yes or no as per requirement.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES/NO;
}
Very good description of fixing this is at
http://koreyhinton.com/blog/lock-screen-rotation-in-ios8.html
I have a view with a property that should take an NSString from my view controller and display an image. If I hard code locationImageFile with "320x213-1.png" in my view, the image displays properly, but if I try to set locationImageFile from my view controller, the image doesn't appear. I feel like I'm missing something pretty basic. Side note: I seem to be able to set the locationTitle property from my view controller without any problems.
LocationViewController.m
#import "LocationViewController.h"
#import "LocationView.h"
#implementation LocationViewController
{
LocationView *_locationView;
}
- (void)loadView
{
CGRect frame = [[UIScreen mainScreen] bounds];
_locationView = [[LocationView alloc] initWithFrame:frame];
[self setView:_locationView];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
_locationView.locationTitle.text = aLocation.name;
_locationView.locationImageFile = #"320x213-1.png";
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
LocationView.m
#import "LocationView.h"
#implementation LocationView
#synthesize locationTitle;
#synthesize locationImageFile;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self setBackgroundColor: [UIColor blueColor]];
// Image container
UIImage *locationImage = [UIImage imageNamed:locationImageFile];
UIImageView *locationImageContainer = [[UIImageView alloc] initWithImage:locationImage];
[locationImageContainer setTranslatesAutoresizingMaskIntoConstraints:NO];
locationImageContainer.backgroundColor = [UIColor yellowColor];
[self addSubview:locationImageContainer];
// Text line
locationTitle = [[UILabel alloc]init];
[locationTitle setTranslatesAutoresizingMaskIntoConstraints:NO];
locationTitle.backgroundColor = [UIColor whiteColor];
[self addSubview:locationTitle];
}
return self;
}
#end
I think this is because the loadView method are invoke earlier than viewDidLoad method.
so when you set _locationView.locationImageFile = #"320x213-1.png";,the containerView's image are not being set.
You can consider declare locationImageContainer as a property of locationView , and set it's image directly.like
_locationView.locationImageContainer.image = [UIImage imageNamed:#"320x213-1.png"];
instead of setting locationImageFile as a property.
When LocationView is initialized, the value of the instance variable locationImageFile equals nil. Override the setter of the locationImageFile property inside LocationView.m like this:
- (void)setLocationImageFile:(NSString *)aLocationImageFile
{
locationImageFile = aLocationImageFile;
locationImageContainer.image = [UIImage imageNamed:aLocationImageFile];
}
You can try, doing it like this:
_locationView.locationImageFile = [UIImage imageNamed:locationImageFile];
if you did it like this:
_locationView.locationImageFile = locationImageFile;
I am fairly new to xcode and having an issue with a scrollview. The scrollview works fine...however when using storyboards and push combined i have a problem. When first viewing the scrollview it works fine however when you push to a new page then go back to the storyboard with the scrollview it no longer scrolls. Im thinking this has something to do with the didload and maybe i should be using willappear? The code is below. I think i need to change this code somehow so that it reloads the storyboard everytime go back to this storyboard... Has anyone else come across this issue or advise on how to fix?
//
// PrintViewController.m
//
//
#import "PrintViewController.h"
#interface PrintViewController ()
#end
#implementation PrintViewController
#synthesize PrintScroller, rememberContentOffset;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[PrintScroller setScrollEnabled:YES];
// Do any additional setup after loading the view.
}
- (void) viewDidAppear:(BOOL)animated {
[PrintScroller setContentSize:CGSizeMake(300, 595)];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
self.PrintScroller.contentOffset = CGPointMake(0, 0);
}
- (void)viewWillDisappear:(BOOL)animated {
self.rememberContentOffset = self.PrintScroller.contentOffset;
[super viewWillDisappear:animated];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.PrintScroller.contentOffset = CGPointMake(0, self.rememberContentOffset.y);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I suspect your problem is here:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.PrintScroller.contentOffset = CGPointMake(0, self.rememberContentOffset.y);
}
This method could be called by the system repeatedly when the user is scrolling. Since you're setting the content offset each time, the view won't move. You should only do this once and then, say, set self.rememberContentOffset to CGPointZero, and then avoid changing the content offset if the remembered offset is zero. Something like:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if (self.rememberContentOffset.y > 0) {
self.PrintScroller.contentOffset = CGPointMake(0, self.rememberContentOffset.y);
self.rememberContentOffset = CGPointZero;
}
}
I have a custom view that I would like to use in Interface Builder. It's setup like the following:
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self initialize];
}
return self;
}
-(void)initialize {
....
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self initialize];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
...frame stuff
}
but when I use the class in interface builder it is not receiving the frame, just it's bounds. Meaning the origin stays at 0,0 but the width/height do get set correctly. If anyone can point out whats wrong I would be very greatful.
UPDATE:
Just spotted this in IB:
Override - (void)awakeFromNib; for your custom view. At that point, your frame should be setup.