how to add a subview to a view controller? - objective-c

I have a green rectangle, but it won't display when i run the app.
here is my code:
- (void) makeBlockg {
x = arc4random()%(320) + 1;
CGRect block = CGRectMake(x, 0, 100, 70);
greenblock.frame = block;
greenblock.self.backgroundColor = [UIColor greenColor];
[self.view addSubview:greenblock];
}

This code works fine for me. Are you sure you are correctly initialising greenblock with greenblock = [[UIView alloc] init]? Without doing this greenblock is nil, instead of being an empty UIView object.

Related

sendSubviewToBack on UITableView not working properly in iOS 11

I have an UITableViewController to which I successfully applied in the past a gradient background, by sending the newly added subview to back:
//performed on viewDidLoad
UIView *bgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1.5*280, 1.5*SCREEN_HEIGHT)];
bgView.backgroundColor = [UIColor yellowColor];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = bgView.bounds;
gradient.startPoint = CGPointMake(0, 0);
gradient.endPoint = CGPointMake(1, 1);
UIColor *topColor = UIColorFromRGB(0x229f80);
UIColor *bottomColor = UIColorFromRGB(0x621ad9);
gradient.colors = [NSArray arrayWithObjects:(id)[topColor CGColor], (id)[bottomColor CGColor], nil];
[bgView.layer insertSublayer:gradient atIndex:0];
[self.view addSubview:bgView];
[self.view sendSubviewToBack:bgView];
bgView = nil;
However, this no longer works in iOS 11 and the bgView is actually placed on top of all the cells.
Anyone knows how I can fix this?
Or maybe I was doing it wrong all the time?
If your cells are transparent then you can try self.tableView.backgroundView = bgView;
If you don't need the background view to be scrolling together with the table view, you can use
self.tableView.backgroundView = bgView;
If you need the background view to be scrolling, change layer's zPosition to a negative value to make it work in iOS 11:
[self.view insertSubview:bgView atIndex:0];
bgView.userInteractionEnabled = NO;
bgView.layer.zPosition = -1;
Another way to fix it is to call [self.view sendSubviewToBack:bgView]; in tableView:willDisplayCell:forRowAtIndexPath:
It works for not transparent cells also.
it appears that addSubview(UIView) sendSubview(toBack: UIView) no longer works for UITableViewControllers in iOS11. So I swap to this:
// in ViewDidLoad
// set the backgroundImage
let backgroundImage = UIImageView(frame: self.view.bounds)
backgroundImage.image = UIImage(named: "background.png")
// self.view.addSubview(backgroundImage) // NO LONGER WORKS
// self.view.sendSubview(toBack: backgroundImage) // NO LONGER WORKS
self.tableView.backgroundView = backgroundImage

UIViews Overlap after adding Gravity and Collision behaviour

I am trying to stack up uiviews on click of a button. I've also added Gravity & Collision behaviour using UIKit dynamics. The problem as you can see from the image (http://pho.to/7nVJI) is, the lower most green block and the block on top of that seems to be overlapping. Here is the ViewDidLoad method :
`- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIButton *moveIt = [UIButton buttonWithType:UIButtonTypeRoundedRect];
moveIt.frame = CGRectMake(200, 50, 70, 30);
[moveIt addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:moveIt];
moveIt.titleLabel.text = #"Hit it";
moveIt.titleLabel.textColor = [UIColor whiteColor];
moveIt.backgroundColor = [UIColor blueColor];
UIButton *addBlockButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
addBlockButton.frame = CGRectMake(20, 50, 70, 30);
[addBlockButton addTarget:self action:#selector(addBlock:) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:addBlockButton];
addBlockButton.backgroundColor = [UIColor orangeColor];
animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
newBlockYCoordiante = self.view.bounds.size.height-BLOCKHEIGHT;
UIView *basicBlock = [[UIView alloc] initWithFrame:CGRectMake(64, newBlockYCoordiante, BLOCKWIDTH, BLOCKHEIGHT)];
basicBlock.layer.borderWidth = 1;
basicBlock.tag = 100;
basicBlock.layer.borderColor = [UIColor greenColor].CGColor;
basicBlock.backgroundColor = [UIColor clearColor];
[self.view addSubview:basicBlock];
newBlockYCoordiante = newBlockYCoordiante - BLOCKHEIGHT;
if (collisonBehaviour == nil) {
collisonBehaviour = [[UICollisionBehavior alloc] initWithItems:#[basicBlock]];
collisonBehaviour.translatesReferenceBoundsIntoBoundary = YES;
collisonBehaviour.collisionDelegate = self;
[animator addBehavior:collisonBehaviour];
}
if (gBehaviour == nil) {
gBehaviour = [[UIGravityBehavior alloc] initWithItems:#[basicBlock]];
[animator addBehavior:gBehaviour];
}
}`
And here is how I add new blocks on top of the previous blocks :
- (void) addBlock :(id)sender
{
UIView *basicBlock = [[UIView alloc] initWithFrame:CGRectMake(64, newBlockYCoordiante, BLOCKWIDTH, BLOCKHEIGHT)];
basicBlock.layer.borderWidth = 1;
basicBlock.layer.borderColor = [UIColor orangeColor].CGColor;
basicBlock.backgroundColor = [UIColor clearColor];
[self.view addSubview:basicBlock];
newBlockYCoordiante = newBlockYCoordiante - BLOCKHEIGHT;
[gBehaviour addItem:basicBlock];
[collisonBehaviour addItem:basicBlock];
}
How do i ensure that these blocks doesn't overlap while stacking up. This overlapping causes another issue, when I add another tower similar to this next to it on right and add push behaviour to the green block to move it towards right, instead of moving only the adjacent block from the second tower it also moves the second last block from the 2nd tower.
Any pointers/help is appreciated. Thanks in advance :).
I believe UIDynamics adds a little "give" to objects and friction so that when they collide and move they act more realistically. You may be able to reduce this, by using UIDynamicItemBehavior and reducing elasticity and bounce, but I'm not sure.
Long story short UIDynamics tends to be an imprecise system and if you're looking to animate interface items in, I'd recommend using dynamics only until items reach their desired location and then removing their behaviors and setting their exact locations :)

Why is each line of code giving me "invalid context"?

This is my code in which every line is giving me an "invalid context" error when running the app in the iPad Simulator. Every statement after "self.Frame = frame; gives the error. How do I fix it?
- (void)makeFrame:(CGRect)frame number:(NSInteger) number color:(UIColor *) color {
float rd1 = 225.00/255.00;
float gr1 = 102.00/255.00;
float bl1 = 0.00/255.00;
float rd2 = 225.00/255.00;
float gr2 = 153.00/255.00;
float bl2 = 0.00/255.00;
self.frame = frame;
self.backgroundColor = [UIColor colorWithRed:rd1 green:gr1 blue:bl1 alpha:1.0];
[[self layer] setBorderColor:[[UIColor blackColor] CGColor]];
[[self layer] setBorderWidth:0.5];
[[self layer] setCornerRadius:10];
self.tag = number; // set each button's tag
[self setClipsToBounds: YES];
// do date label
date = [[UILabel alloc]initWithFrame:CGRectMake(10, 2, 65, 40 )];
date.backgroundColor = [UIColor clearColor]; // x y w h
date.textColor = [UIColor colorWithRed:rd2 green:gr2 blue:bl2 alpha:1.0];
date.text = [NSString stringWithFormat:#"%d", number];
date.font = [UIFont boldSystemFontOfSize:40];
// date.alpha = 0.2;
[self addSubview:date];
}
And this is the code which calls makeFrame:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
allButtons = [NSMutableArray array];
for(int k = 40, m = 0; m < 6; m++, k+= 42) // this controls the vertical distance between rows
for(int i = 0, j=32; i < 7; i++, j+=102) { // this controls the size and horizontal distance
calendarButton *cb= [calendarButton buttonWithType:UIButtonTypeCustom];
[cb makeFrame:CGRectMake(j, k, 100, 40) number: allButtons.count+1 color:[UIColor orangeColor]];
// x y w h
[self.view addSubview:cb];
[allButtons addObject:cb]; // put it in the array
}
calendarButton *cb= [calendarButton buttonWithType:UIButtonTypeCustom];
[cb drawRect:CGRectMake(0,0, 100, 40)]; // 150
You're manually calling drawRect, which I suspect is causing this problem. From the docs:
You should never call this method directly yourself. To invalidate part of your view, and thus cause that portion to be redrawn, call the setNeedsDisplay or setNeedsDisplayInRect: method instead.
This doesn't look necessary in this case, though. The view has been added as a subview of your view; it will automatically draw itself when your view renders.
You are trying to access view properties in view controller. In your case self is UIViewController (or sublcass), change it to self.view in order to access to view
E.g.
self.view.frame = frame;

Using subviews in scrollerview iPhone

I am trying to add uipickerview in uiscrollview, but it is not being shown properly, just a black square.
Further, I have to add 1 more uipickerview, some labels and some buttons.
The code I am using is as under:
-(void)loadView {
[super loadView];
UIPickerView *pView = [[UIPickerView alloc] initWithFrame:CGRectMake(20, 20, 280, 165)];
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"Background.png"]];
scroller = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
scroller.pagingEnabled = YES;
NSInteger numberOfViews = 2;
for (int i = 0; i < numberOfViews; i++) {
CGFloat yOrigin = i * self.view.frame.size.height;
UIView *awesomeView = [[UIView alloc] initWithFrame:CGRectMake(yOrigin, 0, self.view.frame.size.width, self.view.frame.size.height)];
// awesomeView.backgroundColor = [UIColor colorWithRed:0.5/i green:0.5 blue:0.5 alpha:1];
[scroller addSubview:awesomeView];
[scroller addSubview:pView];
}
scroller.contentSize = CGSizeMake(self.view.frame.size.width , self.view.frame.size.height * numberOfViews);
[self.view addSubview:scroller];
}
what can be the issue?
Are you putting data in the picker view? I mean, if you just put the picker view without data on it you are not going to see anything on it.
You need to add the delegate and the datasource and put some data in your picker!
pView.delegate = self;
pView.datasource = self;
and then you have to implemente at least:
numberOfComponentsInPickerView:
numberOfRowsInComponent:
titleForRow:
make sure you are implementing uipickerviewdelegate methods. its normal that it will show just the black square because your pickerview cant find the data and thus does not display anything.
UIPickerView *pView = [[UIPickerView alloc] initWithFrame:CGRectMake(20, 20, 280, 165)];
Change height to 216 .. UIPickerView has fixed height of 216 ..only.. you can't change it..

Extending UIScrollView when it fills up with more content

Ok, so i got a scrollview to load when an user logs in to my application. When the user is authenticated, i need to create a scrollview programmatically. To do so, i have the following code:
[scrollView removeFromSuperview];
UIScrollView *view = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, applicationFrame.size.width, self.view.frame.size.height)];
view.backgroundColor = [UIColor greenColor];
//-- get the y-coordinate of the view
CGFloat viewCenterY = self.view.center.y;
//--calculate how much visible space is left
CGFloat freeSpaceHeight = applicationFrame.size.height - keyboardBounds.size.height;
//-- calculate how much the scrollview must scroll
CGFloat scrollAmount = viewCenterY - freeSpaceHeight / 2.0;
if(scrollAmount < 0) scrollAmount = 0;
//set the new scrollsize contentview
view.contentSize = CGSizeMake(applicationFrame.size.width, applicationFrame.size.height + keyboardBounds.size.height);
//scroll the scrollview
[view setContentOffset:CGPointMake(0, scrollAmount) animated:YES];
for(int v = 0; v < 15; v++){
CGFloat yCoord = v * 100;
UILabel *mijnLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, yCoord, 200, 50)];
mijnLabel.text = #"1337";
mijnLabel.font = [UIFont fontWithName:#"Verdana" size:20];
mijnLabel.textColor = [UIColor redColor];
[view addSubview:mijnLabel];
[mijnLabel release];
}
[self.view addSubview:view];
[view release];
}
How do i extend my view according to the amount of labels i added? I also want to know how i can make my scrollview fill up the entire screen.. My scrollview is now only filling up the screen when in portrait mode.
This is the login screen that gets removed:
[scrollView removeFromSuperview];
you need to keep track of numbers of label that you are adding into the scroll view. suppose if your label's height is 50 then take a variable and make a total of all label's height and give a new frame to your scroll view. like :
view.frame = CGRectmake(0,0,applicationFrame.size.width,totalHeightOfLabel);
[self.view addSubview:view];
[view release];
hope this will give a idea...