This question has been re-written, since I think it has more to do with views and layers than the original 'Finding the center of a tableview'. Also in hope of finding another answer.
In question, is a set of 4 views to show activity, in a tableview, in a tab bar.
The code of:
NSLog(#"view.center: %#", self.view.center);
NSLog(#"view.frame: %#", self.view.frame);
Produces, on first display of 'loading':
view.center: {160, 250}
view.frame: {{0, 20}, {320, 460}}
For 2nd (and subsequent) displays: (after a pop up date picker)
view.center: {160, 205.5}
view.frame: {{0, 0}, {320, 411}}
Self (ListViewController) is subclass of UITableViewController. So, the height of the view (or tableview) frame is changing. Why?
I've been exploring and found this info in the debugger, that seems relevant.
--- Before ---
[self parentViewController]:
<UITabBarController: 0x6e115a0>
[[self parentViewController] view]:
<UILayoutContainerView: 0x6e1b750; frame = (0 0; 320 480); autoresize = W+H; layer = <CALayer: 0x6e0c8f0>>
self: <ListsViewController: 0x6e13730>
[self tableView]:
<UITableView: 0x71e4000; frame = (0 20; 320 460); clipsToBounds = YES; opaque = NO; autoresize = W+H; layer = <CALayer: 0x6834db0>; contentOffset: {0, 0}>
[[self view] subviews]: (array)
<UIImageView: 0x6825e30; frame = (0 453; 320 7); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x6835a90>>,
<UIImageView: 0x68314e0; frame = (313 411; 7 20); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x683d120>>,
<UIView: 0x6a054f0; frame = (0 0; 320 460); alpha = 0.4; tag = 12; layer = <CALayer: 0x6a07840>>,
<UIView: 0x6a04c60; frame = (110 155.5; 100 100); alpha = 0.6; tag = 13; layer = <CALayer: 0x6a073c0>>,
<UILabel: 0x6a07480; frame = (110 200.5; 100 50); text = 'Loading ...'; clipsToBounds = YES; userInteractionEnabled = NO; tag = 14; layer = <CALayer: 0x6a065b0>>,
<UIActivityIndicatorView: 0x6a07a80; frame = (140 167.5; 40 40); tag = 15; layer = <CALayer: 0x6a07b40>>
--- After datepicker ---
[self parentViewController]:
<UITabBarController: 0x6e115a0>
[self parentViewController] view]:
<UILayoutContainerView: 0x6e1b750; frame = (0 0; 320 480); autoresize = W+H; layer = <CALayer: 0x6e0c8f0>>
self: <ListsViewController: 0x6e13730>
[self tableView]:
<UITableView: 0x71e4000; frame = (0 0; 320 411); clipsToBounds = YES; opaque = NO; autoresize = W+H; layer = <CALayer: 0x6834db0>; contentOffset: {0, 0}>
[[self view] subviews]:
<DetailTableViewCell: 0xb642120; baseClass = UITableViewCell; frame = (0 369; 320 44); autoresize = W; layer = <CALayer: 0xb642230>>,
<DetailTableViewCell: 0xb643850; baseClass = UITableViewCell; frame = (0 325; 320 44); autoresize = W; layer = <CALayer: 0xb643960>>,
<DetailTableViewCell: 0xb6435c0; baseClass = UITableViewCell; frame = (0 281; 320 44); autoresize = W; layer = <CALayer: 0xb6436d0>>,
<DetailTableViewCell: 0xb63cf30; baseClass = UITableViewCell; frame = (0 237; 320 44); autoresize = W; layer = <CALayer: 0xb63d130>>,
<DetailTableViewCell: 0x6a14050; baseClass = UITableViewCell; frame = (0 193; 320 44); autoresize = W; layer = <CALayer: 0x6a16fb0>>,
<DetailTableViewCell: 0x6a13760; baseClass = UITableViewCell; frame = (0 149; 320 44); autoresize = W; layer = <CALayer: 0x6a13870>>,
<DetailTableViewCell: 0x6a10920; baseClass = UITableViewCell; frame = (0 105; 320 44); autoresize = W; layer = <CALayer: 0x6a10010>>,
<DetailTableViewCell: 0xb63ce20; baseClass = UITableViewCell; frame = (0 60; 320 45); autoresize = W; layer = <CALayer: 0xb63c3e0>>,
<UIImageView: 0x6825e30; frame = (0 404; 320 7); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x6835a90>>,
<UIView: 0xb6477f0; frame = (0 0; 320 60); autoresize = W; layer = <CALayer: 0xb647820>>,
<UIImageView: 0x68314e0; frame = (313 411; 7 20); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x683d120>>,
<UIView: 0x6a098a0; frame = (0 0; 320 411); alpha = 0; tag = 9; animations = { opacity <CABasicAnimation: 0xb6279f0>; }; layer = <CALayer: 0x6a154b0>>,
<UIDatePicker: 0x6a23350; frame = (0 455; 320 216); tag = 10; animations = { position <CABasicAnimation: 0xb63bd40>; }; layer = <CALayer: 0x6a20590>>,
<UIToolbar: 0x6843f60; frame = (0 411; 320 44); opaque = NO; tag = 11; animations = { position=<CABasicAnimation: 0xb645f80>; }; layer = <CALayer: 0x6844a20>>,
<UIView: 0xb60baa0; frame = (0 0; 320 411); alpha = 0.4; tag = 12; layer = <CALayer: 0xb626af0>>,
<UIView: 0xb626b20; frame = (110 155.5; 100 100); alpha = 0.6; tag = 13; layer = <CALayer: 0xb626930>>,
<UILabel: 0xb60cfb0; frame = (110 200.5; 100 50); text = 'Loading ...'; clipsToBounds = YES; userInteractionEnabled = NO; tag = 14; layer = <CALayer: 0xb60d020>>,
<UIActivityIndicatorView: 0xb649e20; frame = (140 167.5; 40 40); tag = 15; layer = <CALayer: 0xb626960>>
You can use tableview.frame to access the origin points and it's dimensions. You can use tablview.center which is a CGPoint which gives you the center point of the object.
Related
I am trying to loop all my subviews and print them in NSLog.
I have developed this recursive method:
- (void)allSubViews:(UIView*)mainV
{
for (UIView *view in mainV.subviews) {
NSLog(#"%#", view);
if ([[view subviews]count]>0) {
[self allSubViews:view];
}
}
}
which I call from MainViewController.m:
[self allSubViews:self.myView];
The result is:
2015-09-12 11:18:48.919 Profile-Statistics[3153:506562] <_UILayoutGuide: 0x7fc70bf1c330; frame = (0 0; 0 0); hidden = YES;
layer = >
2015-09-12 11:18:48.919 Profile-Statistics[3153:506562] <_UILayoutGuide: 0x7fc70bf1ced0; frame = (0 0; 0 0); hidden = YES;
layer = >
My View has Top and Bottom Layout Guide and a View which has 3 UIButtons, 1 ImageView and 1 UIView.
Did I miss something here?
Update:
Screenshot of StoryBoard
For what it's worth, I tried this in a sample project with a bunch of subviews and it worked as expected.
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (IBAction)printButtonTapped:(id)sender {
[self allSubviews:self.view];
}
- (void) allSubviews:(UIView*) parent {
NSLog(#"%#", parent);
for (UIView *child in parent.subviews) {
[self allSubviews:child];
}
}
#end
Console output is:
2015-09-13 22:06:00.904 RecursivePrint[66243:3455899] <UIView: 0x7fa902e0e6e0; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7fa902e15030>>
2015-09-13 22:06:00.905 RecursivePrint[66243:3455899] <UIView: 0x7fa902e0e840; frame = (70 56; 452 337); autoresize = RM+BM; layer = <CALayer: 0x7fa902e15050>>
2015-09-13 22:06:00.905 RecursivePrint[66243:3455899] <UIView: 0x7fa902e24c90; frame = (31 33; 153 160); autoresize = RM+BM; layer = <CALayer: 0x7fa902e21f00>>
2015-09-13 22:06:00.906 RecursivePrint[66243:3455899] <UIView: 0x7fa902e24fc0; frame = (219 41; 153 160); autoresize = RM+BM; layer = <CALayer: 0x7fa902e1ec10>>
2015-09-13 22:06:00.906 RecursivePrint[66243:3455899] <UIButton: 0x7fa902d177e0; frame = (164.5 603; 46 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x7fa902d16c80>>
2015-09-13 22:06:00.907 RecursivePrint[66243:3455899] <UIButtonLabel: 0x7fa902d1f010; frame = (0 6; 46 18); text = 'Button'; alpha = 0.2; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fa902d1f670>>
2015-09-13 22:06:00.907 RecursivePrint[66243:3455899] <_UILayoutGuide: 0x7fa902e25ed0; frame = (0 0; 0 20); hidden = YES; layer = <CALayer: 0x7fa902e21b20>>
2015-09-13 22:06:00.907 RecursivePrint[66243:3455899] <_UILayoutGuide: 0x7fa902f77ec0; frame = (0 667; 0 0); hidden = YES; layer = <CALayer: 0x7fa902f09f70>>
As a side note, this is the first time in over a year that I've tried to do something in Objective-C. The Swift version seems so much easier to understand:
import UIKit
class ViewController: UIViewController {
#IBAction func printButtonTapped(sender: UIButton) {
printSubviews(self.view)
}
}
func printSubviews(parent:UIView) {
print(parent)
for child in parent.subviews {
printSubviews(child)
}
}
In addition, the Swift version of printSubviews is defined as a function, not a method so you don't call it from self, you just call it with the top level view you want to start with.
I use transitionFromView switch two UIView ,But there is somethine wrong with it , When I transition the view to second UIView ,it work ok, then I transition the view back The error is happen(the location of first UIView is wrong)
What happen?
self.primaryView.hidden = !self.primaryView.hidden
self.secondaryView.hidden = !self.secondaryView.hidden
println("\(self.primaryView)")
UIView.transitionFromView(displayingPrimary ? self.primaryView : self.secondaryView,
toView: displayingPrimary ? self.secondaryView : self.primaryView,
duration: 1.0,
options: nil ) { (finish) -> Void in
if finish {
println("after:\(self.primaryView)")
self.displayingPrimary = !self.displayingPrimary;
}
}
this is print info in console
<UIView: 0x79fe3c80; frame = (0 0; 399 349); hidden = YES; autoresize = RM+BM; layer = <CALayer: 0x79fe3d10>>
after:<UIView: 0x79fe3c80; frame = (0 0; 399 349); hidden = YES; autoresize = RM+BM; layer = <CALayer: 0x79fe3d10>>
<UIView: 0x79fe3c80; frame = (0 0; 399 349); autoresize = RM+BM; layer = <CALayer: 0x79fe3d10>>
after:<UIView: 0x79fe3c80; frame = (-436 -328; 399 349); autoresize = RM+BM; layer = <CALayer: 0x79fe3d10>>
I put a regular UITableView owned by a UITableViewController under UINavigationController.
Now, look at this code:
[BGHPTools vDoForeGroundAndWait:^{
PO(vi);
PO([vi superview]);
PO ([[vi superview]superview]);
PO ([[[vi superview]superview]superview]);
}];
NSArray * arObjects =blarGetArrayTobeParsedWith(weakBODo);//No view object is manipulated here!!!!
[BGHPTools vDoForeGroundAndWait:^{
PO(vi);
PO([vi superview]);
PO ([[vi superview]superview]);
PO ([[[vi superview]superview]superview]);
}];
The code blarGetArrayTobeParsedWith simply download stuff from internet and for all display purpose, just do nothing and wait for a while
The first set of PO is like this:
2013-12-10 21:14:43.257 [8620:9407] vi: <BGTableViewWithBackgroundAndTopAndBottom: 0xd36d600; baseClass = UITableView; frame = (0 0; 320 480); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x15d64320>; layer = <CALayer: 0x15d64890>; contentOffset: {0, -64}>
2013-12-10 21:14:43.259 [8620:9407] [vi superview]: <_UIParallaxDimmingView: 0x15f48a40; frame = (0 0; 320 480); opaque = NO; layer = <CALayer: 0x15f79d00>>
2013-12-10 21:14:43.259 [8620:9407] [[vi superview]superview]: <UIView: 0x15850530; frame = (0 0; 320 480); layer = <: 0x15860480>>
2013-12-10 21:14:43.261 [8620:9407] [[[vi superview]superview]superview]: <UIViewControllerWrapperView: 0xcb35660; frame = (0 0; 320 480); autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0xcb392f0>>
The second set of PO shows
2013-12-10 21:22:26.145 [8620:9407] vi: <BGTableViewWithBackgroundAndTopAndBottom: 0xd36d600; baseClass = UITableView; frame = (0 0; 320 480); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x15d64320>; layer = <CALayer: 0x15d64890>; contentOffset: {0, -64}>
2013-12-10 21:22:26.145 [8620:9407] [vi superview]: <UIViewControllerWrapperView: 0xcb35660; frame = (0 0; 320 480); autoresize = W+H; layer = <CALayer: 0xcb392f0>>
2013-12-10 21:22:26.146 [8620:9407] [[vi superview]superview]: <UINavigationTransitionView: 0x11cac940; frame = (0 0; 320 480); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x11cad190>>
2013-12-10 21:22:26.146 [8620:9407] [[[vi superview]superview]superview]: <UILayoutContainerView: 0x11ca8ef0; frame = (0 0; 320 480); autoresize = W+H; gestureRecognizers = <NSArray: 0x11cb1070>; layer = <CALayer: 0x11ca69e0>>
It seems that vi, which is a UITableView, then changes its parent view.
Why?
_UIParalaxDimmingView, judging from the name, has two purposes:
Dim content behind the wrapped controller
Add a paralax effect to the wrapped controller
I am not sure about your view hierachy but I would expect this kind of controller in the following situations:
Presented view controller
UIPopoverController
During specific controller transitions (animations)
If blarGetArrayTobeParsedWith downloads data from the internet, the difference could be between view hierarchy when animation is running and when animation has ended.
I'm getting some issues with a constraint relative from the bottom layout.
There are some views inside a UITabBarViewController. When I change to another view from the tab and return to first one, the viewcontroller not recognize the bottom layout as the tab bar, but from the bottom of the view.
I uploaded the problem here: https://sites.google.com/site/rveducationapps/layoutError.png?attredirects=0&d=1
I already tried put in ViewDidAppear and also ViewWillAppear:
[self.view layoutSubviews];
[self.view setNeedsUpdateConstraints];
I logged the subviews in the two cases, the right one and after I exit and return to the view:
subviews:(
"<UIView: 0x146b2260; frame = (210 0; 814 712); autoresize = RM+BM; layer = <CALayer: 0x146b22c0>>",
"<UIButton: 0x146a9eb0; frame = (727 672; 287 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x146aa070>>",
"<UITableView: 0x151d3400; frame = (0 0; 210 761); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x146b14b0>; layer = <CALayer: 0x146ade20>; contentOffset: {0, 0}>",
"<_UILayoutGuide: 0x146b23b0; frame = (0 0; 0 20); hidden = YES; layer = <CALayer: 0x146b24a0>>",
"<_UILayoutGuide: 0x146b28a0; frame = (0 712; 0 56); hidden = YES; layer = <CALayer: 0x146b2910>>"
)
subviews:(
"<UIView: 0x146b2260; frame = (210 0; 814 768); autoresize = RM+BM; layer = <CALayer: 0x146b22c0>>",
"<UIButton: 0x146a9eb0; frame = (727 728; 287 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x146aa070>>",
"<UITableView: 0x151d3400; frame = (0 0; 210 817); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x146b14b0>; layer = <CALayer: 0x146ade20>; contentOffset: {0, 0}>",
"<_UILayoutGuide: 0x146b23b0; frame = (0 0; 0 20); hidden = YES; layer = <CALayer: 0x146b24a0>>",
"<_UILayoutGuide: 0x146b28a0; frame = (0 768; 0 0); hidden = YES; layer = <CALayer: 0x146b2910>>"
)
I see there are some differences, specially in:"<_UILayoutGuide: 0x146b28a0; frame = (0 712; 0 56); hidden = YES; layer = <CALayer: 0x146b2910>>"
But I don't know how to fix it.
EDITED:
I think I fixed. I selected the UIViewController in the Storyboard and disabled the EXTEND EDGES->Under Bottom Bars option.
If you are transitioning from your UITabBarViewController to a new UIViewController, and then attempting to go back to your tabBarController from that UIViewController, then you could simply segue back to the UITabBarViewController(The segue will take you back to your rootViewController for your UITabBarViewController).
If you need to transition back to a specific tab, instantiate a custom segue and send it back to a different tab using a different specified VC, this can be set in your UITabBarViewController class or in your applications AppDelegate.m file.
I add objects in UIScrollView inside cycle FOR, but after the second interaction the index of subviews change.
When i create the ScrollView:
scroll.subviews :(
"<UIImageView: 0x147aeee0; frame = (1017 186; 7 5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x147aef50>>",
"<UIImageView: 0x147aefa0; frame = (1019 184; 5 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x147af010>>"
)
After i have the cycle FOR with [scroll addSubview:btn];
First
scroll.subviews :(
"<UIImageView: 0x147aeee0; frame = (1017 186; 7 5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x147aef50>>",
"<UIImageView: 0x147aefa0; frame = (1019 184; 5 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x147af010>>",
"<ContentButton: 0x13fdc610; baseClass = UIButton; frame = (15 10; 221 173); opaque = NO; tag = 1; layer = <CALayer: 0x1034cc00>>"
)
Second (change last object to index 0)
scroll.subviews :(
"<ContentButton: 0x13fdc610; baseClass = UIButton; frame = (15 10; 221 173); opaque = NO; tag = 1; layer = <CALayer: 0x1034cc00>>",
"<UIImageView: 0x147aefa0; frame = (1019 184; 5 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x147af010>>",
"<UIImageView: 0x147aeee0; frame = (1017 186; 7 5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x147aef50>>",
"<ContentButton: 0x105ddf70; baseClass = UIButton; frame = (246 10; 221 173); opaque = NO; tag = 149; layer = <CALayer: 0x105523e0>>"
)
Third and so on, the object will add normally (in last index)
scroll.subviews :(
"<ContentButton: 0x13fdc610; baseClass = UIButton; frame = (15 10; 221 173); opaque = NO; tag = 1; layer = <CALayer: 0x1034cc00>>",
"<UIImageView: 0x147aefa0; frame = (1019 184; 5 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x147af010>>",
"<UIImageView: 0x147aeee0; frame = (1017 186; 7 5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x147aef50>>",
"<ContentButton: 0x105ddf70; baseClass = UIButton; frame = (246 10; 221 173); opaque = NO; tag = 149; layer = <CALayer: 0x105523e0>>",
"<ContentButton: 0x13f1dc80; baseClass = UIButton; frame = (477 10; 221 173); opaque = NO; tag = 3; layer = <CALayer: 0x13f1dd20>>"
)
The problem is in the second interaction, so why the last object (ContentButton) was in the index 2 and change into index 0?
for (obj * objScroll in arrayChaObj)
{
// UIButton
ContentButton * btn = [[ContentButton alloc] initWithFrame:CGRectMake(btContentPosXChaObj,
10,
imgButtonScroll.size.width,
imgButtonScroll.size.height)];
btContentPosXChaObj += 10 + imgButtonScroll.size.width;
[scroll addSubview:btn];
NSLog(#"scroll.subviews :%#",scroll.subviews);
[scroll setContentSize:CGSizeMake(btContentPosXChaObj, imgButtonScroll.size.height+10)];
}
This is just a wild guess.
What happens when you call setContentSize: for the first time? Well, the two image views end up outside the content region. They won't be ever displayed.
I guess the scrollview then optimizes the order of subviews and puts the invisible ones to the end which can probably improve its clipping (redrawing) functionality.
Currently I don't have the time to check this and experiment but it's a reasonable explanation for me.