Adding Subviews programmatically vs. adding them in InterfaceBuilder - iphone

I have a beginner's question.
I was wondering about the level of subviews and how to determine them. Consider having put one button in IB (sampleButton) and then creating a subview programatically, like so:
[view insertSubview:aView atIndex:[view.subviews count]];
which is simply equivalent to:
[view addSubview:aView];
Now, in both cases, my index (which is referred to as z, right?) should be 1, if I am not mistaken.
I have one button added to my view in IB which should be at index 0 (z = 0, or do they start at one?). Then, if I do a view.subviews count, this will give me the number 1, as I have 1 object at index 0. So my new subview 'aView' will be placed at index = 1 which is just one layer above my sampleButton.
So far so good. But what if I did not want things to be this way? What if I wanted to be the sampleButton at a higher level (e.g. 1) and my 'aView' at the lowest (e.g. 0)? Can I simply do this:
[view insertSubview:aView atIndex:0];
Will this simply take care of my button created in IB, pushing it to another layer or will I have to tell IB that sampleButton shouldn't be at z=0?

It behaves as you already guessed: if you insert a subview at index 0 it is "below" all the other subviews.

Related

UIView Content Clipping Not Working/UIView Resize Not Working

I ran into an issue where clipping of subviews is not working consistently (or potentially, the UIView resize isn't working). Here's the scenario:
I have a UIView (section above the line). The actual size is larger to accommodate search bar. I basically resize it on viewDidLoad.
When clicking on the text field, UIView expands and show a search bar
After search, I collapse the UIView, but found that the UIView is not collapsed in certain case (see first image). If I were to not hide the search bar, it will remain also.
Is there any reason why this issue occurs? I'm still trying to debug and see if there is anything that could have caused this issue (as something may reset to original size). It definitely does seem like everything is resized correctly since even the result table is moved correctly also. Something else must have triggered it after the expected resize. Any pointer is appreciated. I've only done iOS development for 5 days so I'm still not aware of a lot of things.
- (void)showAddressField
{
CGRect headerFrame = self.searchHeaderView.frame;
headerFrame.size.height = headerHeight + adjustmentSize;
self.searchHeaderView.frame = headerFrame;
CGRect tableFrame = resultTableView.frame;
tableFrame.size.height = tableHeight - adjustmentSize;
tableFrame.origin.y = headerFrame.size.height + statusBarHeight;
resultTableView.frame = tableFrame;
[self renderHeaderBorder:headerFrame.size.height - 1];
}
- (void)hideAddressField
{
CGRect headerFrame = self.searchHeaderView.frame;
headerFrame.size.height = headerHeight;
self.searchHeaderView.frame = headerFrame;
CGRect tableFrame = resultTableView.frame;
tableFrame.size.height = tableHeight;
tableFrame.origin.y = headerHeight + statusBarHeight;
resultTableView.frame = tableFrame;
[self renderHeaderBorder:headerHeight - 1];
}
EDITED
SearchHeaderView is just a UIView that is a subview of the main view. It's not a table header. I found that if I put a search bar in the table header, it behaves very unpredictably so I have a UIView containing the search portion and have a UITableView right below it.
Sorry, since I only have just over a week to get a rather massive app out from scratch, I didn't have time to wait. I already changed my approach a little bit, but I will still award the points even after the bounty has expired. I'm trying to understand everything to do with layout since that's pretty much the only thing that I can't quite figure out with iOS app development.
If the search bar is in the table view header, try reassigning the header view to the table view:
[tableView setTableHeaderView:self.searchHeaderView];
If it is a section header, be sure to update the value for the delegate's
– tableView:heightForHeaderInSection:
– tableView:viewForHeaderInSection:
Otherwise, please post more code on how the searchHeaderView is initialized and added to the table.
Hope this helps!
Firstly, frames are already relative to the enclosing window. You should not be taking into account the height of the status bar (assuming that refers to the 20px area at the top of the screen).
I have found in the past that you may need to implement "layoutSubviews" in your view controller and compute the frames of the views there. It depends on your resizing mask / if you auto-layout enabled.
As the others have stated, more code would be helpful... or at least the relevant portions of the nib/xib.

iOS: Toggling between UIScrollView views without adding new views?

I am having a problem! When I use addSubview: and add a view to a UIScrollView, it adds a completely new view.
I want to either:
toggle between 3 predefined views, or
remove the last view from the UIScrollView before adding another one.
(All 3 views have some images so I'd imagine that the second option would be more efficient, memory-wise. However, perhaps the first option would be better on battery life? This is a 'subquestion'.)
How does one accomplish this?
You could accomplish your plan B by using removeFromSuperview function of your UIView.
Use it as below.
[mySecondImageView removeFromSuperview];
[myScrollView addSubview:myThirdImageView];
EDITED:
When you create UIImageView assign a tag value to each and also use and integer iVar to hold the tag value of your current view lets say it's currentViewTag ;
myFirstImageView.tag = 1;
mySecondImageView.tag = 2;
myThirdImageView.tag = 3;
currentViewTag = 1;
[myScrollView addSubview:myFirstImageView];
Now use as below
[[myScrollView viewWithTag:currentViewTag] removeFromSuperview];
[myScrollView addSubview:myThirdImageView];
currentViewTag = 3;
Sounds to me that you are trying to implement an infinite scrolling uiscrollview like the photos app.
If so, you don't need to remove any subviews and add them, you just need to create a UIScrollView that is as wide as three of your images and then when the scroll view is scrolled, change the image in either position 1 or 3 depending on which way the scroll is performed and then reset the position of the scroll view. If this is what you are trying to do, I can give more information if you need it.

Using tags in iphone programming--can someone explain?

I've seen people using tags in iphone programming, like inside labels or tableview cells:
name.tag = kNameTag
Can someone explain with an example how these tags might be used? I gather that it's so that you can refer to a ui element later? Like if you programmatically use a for loop to create an array of UIButtons onto the iphone screen, do you assign tags to each button within the for loop or something?
Thanks!
The example you've included in your question is one of the common ones.
You can instantiate buttons (or other UI elements) in a loop, assigning a incremental tag to each. When an IBAction is invoked by one of those buttons, you can ask the sender for it's tag, which tells you exactly which button triggered the request.
for( int i = 0; i < 10; i++ ) {
UIButton * button = [[UIButton alloc] init...];
button.tag = i;
}
IBAction:
- (IBAction)doSomethingFromButtonTap:(id)sender {
NSLog(#"Button pressed: %d", [sender tag]);
}
They're also widely used to find specific subviews within a parent view. UIView provides a viewWithTag:(NSInteger)tag method. This is useful when building custom views without subclassing (or situations where you don't want to hold references to subviews, but know the tag).
Tags are integers. You assign them to a view using UIView.tag. You then use -[UIView viewWithTag:] to search the view hierarchy for the view.
UIKit doesn't use tags (I think), so they're free for you to use as necessary. However, tags are global to your app, so they're not an ideal replacement for IBOutlet (but it's often more convenient when you have a lot of views).
Avoid using 0 as a tag, since it's the default tag — [v viewWithTag:0] is unlikely to return the view you're looking for.

UIView viewWithTag 0 problem

On view in IB I have numerous items (including view itself). ONLY one item has tag 0, yet following line works for ANY UITextBox other then the one with tag 0. Note that only ONE UITextBox has tag 0, why:
(UITextField *) [self.view viewWithTag:0]).text = #"foo";
Interesting that when triggered event received for the element with tag 0, I can get value of Tag 0 with no problem.
Is there a limitation to look for tag 0 elements?
All views have a 0 tag as a default so if you get a 0 view it could be any view. For it to work you need to use non-zero values that you set in your program or within Interface builder.
actually, if you ask a view called "X" for a viewwithtag 'zero', you will probably get the "X" view as the return value :/ idiotic behaviour. send regards to apple
que is right. I just got bit by this.
From the docs:
Discussion This method searches the current view and all of its
subviews for the specified view.
At least it's documented correctly. I guess we need a method called "subviewWithTag:"
set self tag as -1. won't affect other view's tag.

UIView Hell. Hiding one subview hides them all

I am apparently in some swirling UIView hell zone at the moment where up is down sibling is parent and my brain is completely fried.
Here's the deal. Really, really simple. I have a container view with N leaf node sibling subviews. No tricks here, dead simple. I do the following:
// occludedPageSet is the set of view tags corresponding to views that are off screen and // thus fully occluded. This was determined geometrically.
for (NSNumber *n in occludedPageSet) {
// Point to a view corresponding to this tage
UIView *v = [self.containerView viewWithTag:[n integerValue]];
// Hide this view
if (v.hidden == NO) {
NSLog(#"View %d is occluded. Hide it.", [n integerValue]);
v.hidden = YES;
} // if (v.hidden == NO)
} // for (occludedPageSet)
Pretty tame stuff. Unfortunately ALL sibling views vanish! What the?!? How is this possible?
Do I need a [retain]/[release] for v here. I'm stumped.
Baffled,
Doug
Am I missing something about the problem here? It's only natural that if you hide a view, any view it holds as a subview would be hidden as well. After all, you can't see the container view...
If you put ten things in a box and make the box invisible, wouldn't you expect that to mean you couldn't see the things in the box? Similarly an invisibility cloak would be of little use if only the cloak were invisible and not the person beneath...
If you need some things visible and some not, work on the specific items and not the container.
Apparently, all of your views are included in occludedPageSet, or all of your tags are the same n.
NSNumber *n in occludedPageSet
Or, one of the v views is the parent of the rest, so when you hide it, you hide them all.
Make sure self.containerView's tag is something completely different from any of the children's tags. Calling viewWithTag will return the receiver if it is the given tag, which will in turn hide all of your views. Either step through the iteration or print out the address that v points to so that you know you're occluding what you should be occluding.