If i use a for loop;
for(UIView *subview in [myView subviews])
in which order, subviews are brought?
According to their added order or something else?
As the documentation says, it reflects their visible order in the screen.
#property(nonatomic, readonly, copy) NSArray *subviews
Discussion
You can use this property to retrieve the subviews associated with
your custom view hierarchies. The order of the subviews in the array
reflects their visible order on the screen, with the view at index 0
being the back-most view.
For complex views declared in UIKit and other system frameworks, any
subviews of the view are generally considered private and subject to
change at any time. Therefore, you should not attempt to retrieve or
modify subviews for these types of system-supplied views. If you do,
your code may break during a future system update.
I find it to be useful, and in my experience it places subviews in order that they were added. Just be careful using them when using UIScrollView. I occasionally ran into 'phantom' subviews that are created for scroll bars
Related
This is an UIView and I want to activate it (with its constraints etc.), when I want, how to do that? I don't want removefromsuperview etc. Just want to learn this Installed function exact equivalent in terms of code.
There are two options 1) hide 2) removeFromSuperview.
If You install or uninstall view from storyboard, It is equivalent to add/remove view.
refer this apple documentation it says,
A runtime object for an uninstalled view is still created. However, the view and any related constraints are not added to the view hierarchy and the view has a superview property of nil. This is different from being hidden. A hidden view is in the view hierarchy along as are any related constraints.
you can check this by two line of code,
NSArray *arr = [self.view subviews];
NSLog(#"arr is %#",arr);
swift:
let array: Array = self.view.subviews
print("Array is \(array)")
try it with installed and uninstalled.
hope this will help :)
I want to set the tag of a UITableViewCell that I, personally, create, with initWithStyle:reuseIdentifier: in tableView:cellForRowAtIndexPath:, to 0 or 1 to indicate whether I should position its subviews to the left or right. Is it safe to do this, or will Apple mess with the value of this cell's tag? I know I could use a separate cell identifier for each type of cell, but both cells are pretty much the same, besides positioning of subviews and some colors. (I'm recreating the native Messages app with the chat bubbles.)
While you can certainly use tags, I'd definitely suggest to be more explicit. You will do yourself a favor when you look at your code a few months from now. I'd create a custom UITableViewCell subclass that has a contentAlignment property that you can explicitly set to left or right. It will be much more readable that (ab)using the cell's tag.
Something like this:
typedef NS_ENUM(NSUInteger, MyTableViewCellContentAlignment) {
MyTableViewCellContentAlignmentLeft,
MyTableViewCellContentAlignmentRight
};
#interface MyTableViewCell : UITableViewCell
#property (assign, nonatomic) enum MyTableViewCellContentAlignment contentAlignment;
#end
Enjoy.
It's okay, but a better place to set the tag would be the tableView:willDisplayCell:forRowAtIndexPath: method of the UITableViewDelegate. According to the docs:
A table view sends this message to its delegate just before it uses cell to draw a row, thereby permitting the delegate to customize the cell object before it is displayed. This method gives the delegate a chance to override state-based properties set earlier by the table view, such as selection and background color. After the delegate returns, the table view sets only the alpha and frame properties, and then only when animating rows as they slide in or out.
It is absolutely safe to set a UITableViewCell's (or any UIView's) tag to whatever value you want. No one (including Apple) will mess with this tag's value outside the control of your application.
I think it's OK to give UITableViewCell a tag. Interface Builder lets you do it. Still, feeling shaky about doing so is understandable. Normally, you'd give a tag to a view that you're explicitly adding to another view via addSubview:. But, think about it. If Apple messed with the values of any of the tags of the views within your view controller's view, then that could break the functionality of something like [self.view viewWithTag:TEXT_FIELD_TAG]. So, I doubt they would. I have heard once that Apple reserves the tag integers <= 10, and therefore, you should use integers > 10 for tag values, but I don't see how that could be true.
How to change the diagrams displayed in the same view?
I have a view inside a view controller.
This view has another view inside it, to which I have allocated a custom class (sub-classing UIView).
This custom class has the code to draw interactive diagrams in this view.
The interactive code is operated by sliders in the main view.
I have all this in interface builder.
What if I want to draw a completely different diagram in this view?
I would like to be able to allocate a new class to this view, with a different set of drawing code? But how?
There are many ways to do this, but changing the class at runtime is not advisable
Here are a few suggestions:
1 / Replace customView1 with a different view instance of the right type in the same location as your first view...
self.customView2 = [[CustomView2 alloc] initWithFrame:self.customView1.frame];
[self.view addSubView:self.customView2];
[self.customView1 removeFromSuperView];
This example uses a distinct property for each of the swapped subviews, but you could use a single property just to refer to the current subview - this could help link up your sliders to do the right thing to the diagrams. If you are doing a lot of this you will need to think about memory issues - when customView1 has gone, will you be reusing it? You can keep it hanging around in a (strong) property (faster, needs more memory), or create a new one each time (slower, needs less memory).
2 / if you want to toggle between them, you could place both in Interface Builder and toggle their hidden properties or their order in the view hierarchy (self.view.subviews array). Saves having to constantly recreate the views.
3 (better...) / Keep to a single subclass of UIView and use properties to affect the diagram that gets drawn...
//CustomView.h
#property (nonatomic,assign) BOOL drawDiagram1;
#property (nonatomic, assign) BOOL drawDiagram2;
//CustomView.m
- (void)drawRect {
if (drawDiagram1) [self drawDiagram1];
if (drawDiagram2) [self drawDiagram2];
}
- (void) drawDiagram1 {
//drawDiagram1 code here
}
- (void) drawDiagram2 {
//drawDiagram2 code here
}
I am creating a Custom Grid kind of View for my App. I am placing many subviews on them. I have a necessity to reload the Gird with new set of Views based on users' interaction and when new data arrives.
I allocate memory for my subviews as this:
while(index < count)
CustomGridTile *view = [[CustomGridTile alloc] initWithFrame:frame];
[self addSubView:view];
[view release];
}
When I wanted to refresh my Grid, I remove all subviews from their superViews and create new set of Grid Tiles (subviews), add to the Custom Gird View and release them.
Am I doing things correctly? Can this bring me memory related issues?
As long as you are removing the subview it should release memory.
Explanation:
When you allocate the view CustomGridTile its retain count becomes 1. When you add it as the sub view, its retain count would become 2. When you release, retain count becomes 1. Finally when you remove the subview, its retain count will become zero and should be released.
releasing the views can bring some issues - i suggest attempting an autorelease on them or something along those lines
otherwise what i would do is when you remove it from the superview release it as well, but releasing after you add it as a subview has given me troubles in the past
If I'm creating a UIView programmatically and I wish to change the UIView properties (background, for example, or actually, messing with CALayers), must I place the code outside of UIView such as in the View controller? Can I put the code somewhere inside UIView?
I was checking out the CoreAnimationKioskStyleMenu example, its code is inside UIView but it's loaded from Nib and can be placed at awakeFromNib, so it doesn't seem to apply to my case.
That depends. Obviously, a good way to handle this is to use a xib file, as it is designed to hold data like this, but that isn't always the best answer for every situation.
If the view is meant to be reused frequently (like a button, or some widget) throughout the application, its best to store all that customization in a subclass of the UIView.
If its a single larger view that will always be managed by a UIViewController, you can keep some of the information in the UIViewController. However, if you end up subclassing a UIView anyway it's probably best practice to keep the data in the UIView.
As a general note, I believe its worth your time to push as much of this data into a xib using interface builder. Magic values (like colors or sizes) peppered through your code will always be a problem if you want to modify it. I have found modifying a xib to be much easier.
Actually there are some methods where you could place initialization/ customization code.
(void)willMoveToSuperview:(UIView *)newSuperview;
(void)didMoveToSuperview;
will get called as soon as u add the view as a subview to another view, at which point you already have the frame and all the properties, and you can do further customizing as you wish.
(void)layoutSubviews -- generally used for changing subviews' frames and layout organization.
Will get called each time the view needs to be redrawn by the system, or when you specifically call [self setNeedsLayout] on your UIView.
Hope this helps.