get the frame of a view made in IB in viewDidLoad? - iphone

When I create a label in Interface Builder and hook the outlet to a viewController, and log the label in viewDidLoad as follows:
NSLog(#"label: %#",self.label);
It gives me a frame of (0,0,0,0). self.view gives me a size over 0. An older program's label also gives me a size over 0. It will log the text in the label, so it is hooked up right. Is this a change in Xcode 4.5? How do I access the frames that I set in Interface Builder?
this is the log:
UILabel: 0x754e1b0; frame = (0 0; 0 0); text = 'this is a label'; clipsToBounds = YES; opaque = NO; autoresize = TM+BM; userInteractionEnabled = NO; layer =...

Usually the frame layouts are unreliable in viewDidLoad. In the case of a nib this shouldn't be a problem. Are you using AutoLayout by any chance ?
Please also log the same values in viewWillAppear, this will certainly have the correct values. I usually use viewWillLoad to initiate my UI elements, and viewWillLoad to place them correctly.

Try this:
NSLog(#"Label Frame: %#",NSStringFromCGRect(self.label.frame));

Related

UIDynamicAnimator - won't work with UIView but will with Self.View?

I used this code from Apple's sample app and adjusted it to mine. I want the UIImageView gameOverFalling to run this method (fall and kind of bounce). It should collide with the UIView finalScoreView, as you can see in line 2.
-(void)gameOverFallingMethod{
UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:finalScoreView];
UIGravityBehavior *gravityBeahvior = [[UIGravityBehavior alloc] initWithItems:#[self.gameOverFalling]];
[animator addBehavior:gravityBeahvior];
UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:#[self.gameOverFalling]];
// Apple said: "Creates collision boundaries from the bounds of the dynamic animator's
// reference view (self.view)."
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
collisionBehavior.collisionDelegate = self;
[animator addBehavior:collisionBehavior];
self.animator = animator;
}
However when I run my app, it returns a Thread 1: SIGABRT error. In the console:
View item (<UIImageView: 0x10aaa0c70; frame = (15 175; 288 42);
autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x10aa7e0a0>>)
should be a descendant of reference view in <UIDynamicAnimator: 0x10ae17610>
Stopped (0.000000s) in <UIView: 0x10aa9e1e0> {{0, 0}, {288, 195}}
It works when I replace 'finalScoreView' on line 2 with 'self.view', but then it falls to the bottom of the whole screen.
Any ideas what I did wrong? I would love to know, thanks!
It appears from the exception that self.gameOverFalling does not descend from finalScoreView in your view hierarchy. See the quote from UIDynamicAnimator class reference:
To animate views, create an animator with the initWithReferenceView:
method. The coordinate system of the reference view serves as the
coordinate system for the animator’s behaviors and items. Each dynamic
item you associate with this sort of animator must be a UIView object
and must descend from the reference view.
I solved this by adding to subview before adding any behaviour.
addSubview(square)
var gravity = UIGravityBehavior(items: [square])
gravity.magnitude = gravitySpeed
animator.addBehavior(gravity)
You probably forgot to add your items to the reference view using:
finalScoreView.addSubview(self.gameOverFalling)

Can't get scrollsToTop working on iOS7

I'm targeting iOS7 in my latest app, and tapping on the status bar doesn't seem to scroll a tableView or collectionView to the top.
I've set self.tableView.scrollsToTop = true and still nothing happens.
I know Apple significantly changed the status bar in iOS7, but did those changes break the scrollsToTop functionality?
Update
In response to a comment in one of the answers, I tested to ensure that my collection view was indeed the only scrollView on the screen, and it was:
(lldb) po [self.view recursiveDescription]
<UIView: 0x1092ddf0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x109357e0>>
| <UICollectionView: 0x11351800; frame = (0 0; 320 568); clipsToBounds = YES; opaque = NO; autoresize = W+H; gestureRecognizers = <NSArray: 0x10966080>; layer = <CALayer: 0x109623a0>; contentOffset: {0, -64}> collection view layout: <UICollectionViewFlowLayout: 0x10940a70>
| | <UIImageView: 0x10965fa0; frame = (0 564.5; 320 3.5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x10965ee0>> - (null)
| | <UIImageView: 0x10948f60; frame = (316.5 561; 3.5 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x10966030>> - (null)
Update #2
Not sure if it matters, but I'm using a standard iOS7 NavigationController where the navigationBar is transparent and applies a blur to my collection/tableViews as they scroll underneath.
Update #3
Figured it out. Turns out I did have more than one scrollView on the screen. My app has a left drawer menu underneath the main part of the app, and that menu has a tableView for the options. I simply set self.menuTable.scrollsToTop = false and everything worked as expected throughout the rest of the app. Didn't have to implement the scrollView Delegate methods or anything.
Do you have more than one scroll view/table view/collection view on screen? If so, only one of them can have scrollsToTop set to YES, otherwise iOS7 will not scroll any of them to the top.
You can also implement the UIScrollViewDelegate method scrollViewShouldScrollToTop: and return YES if the passed in scroll view is equal to the one that you want to scroll to the top:
- (BOOL) scrollViewShouldScrollToTop:(UIScrollView*) scrollView {
if (scrollView == self.myTableView) {
return YES;
} else {
return NO;
}
}
The short answer is there's nothing different in iOS7. As long as there isn't more than one UIScrollView loaded, your tableView or collectionView will scroll to the top when the user taps the status bar. The key here is loaded; another scrollView doesn't necessarily have to be on screen to conflict with another scrollView that is.
Sliding drawers in the left/right are very popular these days, and this was the reason for my problem. I have a menu containing my navigation options, and these are all held by a UITableView. I had to make sure that I set menuTable.scrollsToTop = false before I could get things working in the other parts of my app.
My problem was that I had a UITextView with scrollsToTop set to YES, so my UITableView wasn't responding to the gesture. In short, make check all other scrollable views.
for others :
Remember that the scroll view you are searching can also be a UIWebView..not just UITableView.
Another important thing is that it's not only about VISIBLE scrollViews, but LOADED scrollviews.
If you don't find the scrollView, you can always
insert UITableView test table, immediately when app is starting, check if it's scroll to top,
and then load more and more views, until the test table stop scrolling to top.
If your table cells are dynamic, remove the following:
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
{
return YES;
}
Create a new function as follows:
- (void) disableScrollsToTopPropertyOnAllSubviewsOf:(UIView *)view {
for (UIView *subview in view.subviews) {
if ([subview isKindOfClass:[UIScrollView class]]) {
((UIScrollView *)subview).scrollsToTop = NO;
}
[self disableScrollsToTopPropertyOnAllSubviewsOf:subview];
}
}
Call the function above in - (void)viewDidLoad
[self disableScrollsToTopPropertyOnAllSubviewsOf:self.view];
Now enable ScrollsToTop for your table view as follows:
[myTableView setScrollsToTop:YES];
This always works for me:
[self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];

UIScrollView initializing with two uiimageviews from system?

I have a Nib with a scrollview which i use on my controller. I have to make some constant calculations based on the scrollview.subviews count. However, surprisingly the scrollview is always starting with two uiimage views.
The scrollview at my Nib file is empty, and i have even checked the nib source code to assure there is no garbage there. I also deleted the scrollview and created another with the same result.
I am always receiving the same views there (always at, so my scrollview.subviews.count always start at 2. What could be causing this??
If I print scrollview subviews just after initializing view..
[[NSBundle mainBundle] loadNibNamed:#"TileScreen" owner:self options:nil];
NSLog(#"Started scrollview with subviews %#", _scrollView.subviews);
I receive:
Started scrollview with subviews (
"<UIImageView: 0x1dcb50; frame = (294 400; 7 7); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x1e51b0>>",
"<UIImageView: 0x1bb6a0; frame = (294 400; 7 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x1a9b50>>"
)
Well before I posted this question I understood the problem. I wanted to share in case someone falls into this.
The problem is that the "Show horizontal scrollbar, Show vertical scrollbar" add the mentioned UIImageViews. You can avoid this by simply unchecking the property on the IB.
If you want to show the scrollbars though, you will need to take into account these two views in your count.

Set UIView.frame.size.height to zero to hide content?

UIView *stateView = [getSomeUIView thisOne];
CGRect currentFrame = stateView.frame;
if(currentFrame.size.height == 0.0) {
currentFrame.size = CGSizeMake(260, 60);
}
else {
currentFrame.size = CGSizeMake(260, 0);
}
stateView.frame = currentFrame;
I would expect all the subviews would be hidden when the height of the frame is set to zero however this does not happen (in the iPhone 4.0.1 Simulator).
Any suggestions why or alternatives?
I was planing to later animate the frame so it's a sliding effect. I can not use the y position and move it off screen nor can I create a element to hide it behind since I'm working with a background image and everything on top is transparent/alpha layer.
I've got the same problem. Solved it with clipsToBounds property:
stateView.clipsToBounds = YES
Subviews will only change size if you set their springs and struts to do so.
By default, they are set to "stay the SAME width and height, and stay the same distance from top left corner of the parent view".
You can set the springs/struts in Interface Builder, or in code. e.g.:
aSubView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Use UIScrollView instead of UIView. UIScrollView is made to hide "overflow" and works perfectly.

Making sure that UIView autoresizes as specified in NIB settings

I have create a view based application and its loaded correctly what i designed in the xib files.My doubt is when i designed uiview it has the property of resize its frame size(autoresize).
But when i loaded the application into iphone the uiview has not the property of resize its frame automatically.Is it possible to change a uiview automatically in iphone (when application loaded)? (or) We can change the frame size of the uiview for every touches moved event.
Can anyone help me ?
Thanks in advance.......
have you tried something like this:
CGRect f = self.view.bounds;
f.size.width = 200; // change value here;
f.size.height = 200; // and here
self.view.bounds = f;