Swift - Store the stacking order of views - ios

I used view.addSubview(imageView) to add two UIimageview on a UIview. How do I store the stacking order of them and reproduce them with the exact order? Any suggestions? I wish to store the stacking order information on firebase.

Here is how you can do it with the approach mentioned in the other answers (using subviews of the parent),
if let indexOfImageView = view.subviews.firstIndex(where: {$0 === imageView})) {
// Save index of image view
}

From Apple Doc,
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.
Ref : https://developer.apple.com/documentation/uikit/uiview/1622614-subviews

When you add a subview, it is stored in an array. To retrieve the array you have to write down just
view.subviews

Related

Passing data to Custom Views and their children from a UITbleViewCell?

I have a custom view, let's call it ArticleView, that has three child views, which are also custom views, let's call them CustomLabel (they are a view with two labels each)
Each of my views can be either "light" or "dark" themed, depending on a boolean called "dark", that each custom view knows how to draw itself depending on it.
My questions is the following: I have a UITableViewController, and each UITableViewCell has an ArticleView inside of it. I do not want to expose the child subviews of the ArticleView to the cell, so in each cell (in cellForRowAtIndexPath) I pass the "dark" parameter to the ArticleView, which in turn passes the var to its children CustomLabels (via the didSet{} methods of swift), which in turn draw themselves accordingly.
Is this the correct pattern of passing data from my TableView's data all the way down to the custom child views of my custom view?
I do not want to let my cell have access to my ArticleView's children since that would make things less maintainable in the future. What is the best approach here? It just seems I'm passing the "dark" parameter too many times, so I'm asking if there is a better architectural approach for my case.
Thank you!

iOS reusable and changeable ViewController

I'm creating an app to increase my knowledge.
I have a ViewController which receives information, and with that information he shows some Views. I've already done something like this but in the end that was a mess and had way too much work to change what I've done.
In my attempt I had some views in the same place as others and just changed the hidden property to NO if I didn't want them to be visible, at the time that was the best option for my knowledge(4 months of iOS) and I thought to myself that must be other ways and better ones to do this type of ViewControllers.
So now comes my question.. What is the best way to do a ViewController which can change accordingly to the information he receives??
A base ViewController and the others are subViews from that ViewController??
Example Updated: I can receive N type of news. Some have an image in the top of the view, others have a scrollview like a photogallery to show more than one image, others can have a title with an image and so on.
Others can have text, others one webview to show a video, others can have a collectionView to show some additional information.
What I would do is have several UIView subclasses. So the setup would look something along the lines of:
YourViewController has a view, that is only there to display subviews
Then depending on the data you receive you instantiate one of your UIView subclasses that are made to display the data you need ( you could also design them in interface builder and access them as a property on your UIViewController ) and add it as the subview to use
Whenever the data needs to change again, remove all the subviews and add the newly needed subview.
ViewController.mainView -> removeAllSubViews -> addNewSubView
Alternatively you could have multiple view controllers I guess, but it kind of depends all on how and what you need your views to do.
For instance if you need more than just a display of data, and some interaction / manipulation of your data you might want to consider using multiple ViewControllers

I was confused by immutable copy and mutable copy in Objective-C

Oddly, there is no command for removing all of a view’s subviews at once. However, a
view’s subviews array is an immutable copy of the internal list of subviews, so it is legal
to cycle through it and remove each subview one at a time:
for v in myView.subviews as [UIView] {
v.removeFromSuperview()
}
This content is in the Programming IOS 8,if the copy is immutable copy ,why it can change?
I don't think you are a really asking about immutable arrays here as you aren't invoking any methods on the array itself, so it's mutability cannot be an issue. The immutable attribute of the subviews array is how the view has decided to present the list to you. It's got nothing to do with how sub-views interact with parent views.
You appear to be confused about why a subview can remove itself from the parent view and you cannot; this is simply because the subview is a UIView-subclass and the parent view is a UIView-subclass and therefore the subview has access to all of the internal variables of the parent and can do whatever it likes to the parent. You cannot. This is deliberate as you don't know the intricacies of the view hierarchy (and don't want to), where as the UIView obviously does.
Another interesting aspect of the code you posted is that often getting an element in an array to remove itself from the array while you are enumerating it, will cause an exception. In this particular case, however the subviews array you receive from the view is a copy of the original (an immutable copy) and therefore getting the subview to remove itself from the parent view will not affect this array and the enumeration will not falter. Thanks to Christopher Kevin Howell for pointing this out, as I missed it completely, first time round.
The subviews array is immutable, so you can't change it. For example, you can't remove an element of the array yourself, or overwrite it with a completely new array.
However, there's nothing stopping the internal implementation of the class from changing it by overwriting it internally.
In this case though, the subviews array that is returned is a copy of the actual subviews array.

TreeView in IOS rearrange following Subviews after adding or removing subviews from Scrollview

I try to create an n-dimensional Treeview Control for an IOs application.
I use a UiViewController with a UIScrollView and have a custom UIView Class for the TreeNodes.
Now I want to collapse and Expand the Treenodes, but if i add or remove Subviews From the Scroll View i have to rearrange the other subviews.
This is the Tree:
If i collapse the second Node and remove the childnodes it looks like that:
Is there a way to realise something like that, without programatically rearrange the following Subviews?
You already realized a lot of code?
Because I probably would use a tableview.
As datasource of the table you can use an array of dictionary; and in each dictionary you can store the rows informations like:
row element;// current element to display
parent element;//* to the parent element
generation; //NSInteger number of parents (you can use it to do the indentation)
so when you delete a row, you can search in all the datasource the items with that parent element, and substitute it with the parent of the deleted row (if exists); than decrement the generation for them, and recursively for all the children (until you will find no more children).
Of course, when populating the tableview you can easily use the generation number to make the indentation.

Using view space of a hidden UIView

I have three UIViews one below another in my application.The UIView's data is filled by API responses. I want to hide the UIView when it's corresponding API response is nil. I am checking the API response and if it is nil, I am setting [myview setHidden:YES] which hides the view but here is my problem.
Say, if the second view doesn't have any data, it is hidden but the view's coordinate is still occupied and I get big blank space between my first and third view.
To solve this problem, what I did was I used UIView animation method to move the third view in to the second view's coordinate space if second view data is nil.
This works fine for me but this kind of approach adds complexity to my code if I add fourth or fifth view. I am sure there are better solutions than my approach and would be helpful if you can guide me to a better approach than mine.
Thank you
Among the solutions provided I went with the solution provided by Jonah.at.GoDaddy which suited my app. Thank other too for providing great inputs.
Why not use a UITableView with 0-3 cells depending on on how many api responses you have?
What you could do is check the APIs and only do
UIView *APIView1=[[UIView alloc] init];
[self.view addSubview:APIView1];
when you know the API is available.
This could be a good approach for you:
1. Define coordinates for each place you would like to use for placing view and store those coordinates in array A.
2. Each time you add/remove a view to/from superview, add/remove reference to that view to/from array B.
3. After adding/removing references run a loop and assign coordinates from array A to view's frames from array B. Assign them through array ids.
4. Put that loop in UIView animation block.
Now you can use any number of views and remove/add them in which place you want.

Resources