Drag and move something in Interface builder, without changing parent/superview - ios

I have some views in interace builder. I have a background view that takes up my entire view area
and above it I have some buttons which are NOT in the background view.
I want to drag those around to reposition them; but when I do, IB will reparent them when I let go of them.
That is to say, IB seems to only understand drag/drop in this case as a reparenting action; not a moving action.
Is there a hotkey, or something I can do to make IB just move things, without changing the parent when I let go?
This has to be the most painful part of working with IB for me.

If you hold the command key down while dragging, the dragged element will not change superviews. At least in Xcode 7.3.

This has been bothering me as well. I've found a workaround which I find slightly less annoying. Sounds like a lot but it's really quite easy.
Select the item you want to move
Goto Editor -> Embed In -> View (this creates a parent view for your item)
Resize (but don't move) the parent view to encompass the area you want to move to
Move the item within the parent view
Select the parent view and Goto Editor -> unembed
Also, since resizing doesn't cause the parent to change you could actually move a view with two resizes. However it's tedious to get the size right again which is why I like the embed method.

You can press function key and drag the object: Fn + drag

Related

How to bring subview to front in interface builder without changing its position

I want to ask a simple question how can I temporary bring a subview to front to view its element without changing its position by dragging and dropping. The problem i face all the time is i forgot to put the views back to there position and that causes lot of trouble specially if you are working on the view that have large number of subviews.
Question : Is there any shortcut or any functionality that can show the view temporary without dragging, changing its frame or making any changes in its hierarchy.
For a view controller like this :-
FYI, for those who are wondering, the view closest to the bottom of the list (on the left) will show in the front. So in the case below, view 'a' will be in front of 'b' and 'b' will be in front of 'c'
XIB:
If you need your views to be readily accessible for viewing/editing without having to rearrange them, I would actually recommend breaking them out into their own view and then stitching them together in the correct order in your code. This will ensure that all elements will be put in the proper order and will always be easily editable. Something like this:
And then in your code, in somewhere like viewDidLoad:
[self.view addSubview:view2];
[self.view addSubview:view3];

Swapping UIViews in and out of a ViewController's view

I'm not entirely new to iOS/Swift development but I've mostly been working on "backend" code so my UI design/development skill level is unfortunately not what I'd like it to be. With that in mind, I have a UI layout (for a view controller) that looks something like this:
In this layout, the view labeled "View To Swap" could be in one of three states:
It may be hidden (or removed?) in which case StackView B should appear directly below StackView A
It may need to show (or be replaced by?) "Subview A"
It may need to show (or be replaced by?) "Subview B"
Both Subview A and B will have a button in the upper right hand corner that, when clicked, should remove/hide the "View To Swap" view.
I've been reading about container views a little bit and I'm wondering if this is the approach that I should take here or is there a more simple, direct way to implement this? I'm currently using the storyboard and autolayout to define my primary view (the view on the left) and constraints but I understand the basics of building a UI programatically if that makes it easier to implement something like this? Thanks for any suggestions!
You need to insert the 3 main views ( top stack , viewToSwap , bottom stack ) inside a vertical UIStackView with distribution = fillEqually , and hook viewToSwap as IBOutlet, whenever you want to hide it do
self.viewToSwap.isHidden = true
this will automatically collapse it's content , and you can add any subview to it (A/B) and don't forget self.viewToSwap.clipsToBounds = true

How do I make the elements in my UIView responsive?

My goal is to create an alert that has three text fields, one taller than the others, and an image that, when tapped, allows the user to choose a picture to replace a set default one.
After unsuccessfully searching for a library for this, I decided to create my own alert by placing a UIView off the screen and, when prompted by a button, would zoom onto the screen; it consists of all the elements I require.
When I run the application, the view pops up correctly, but none of the elements on the view are responding to touch. I've checked that isUserInteractionEnabled for everything is turned on.
What's also odd is that when I keep the view on the screen (instead of placing it some distance away on Storyboard), all the elements work fine.
I'm assuming it had something to do with the animation. I tested it with a fade in instead of a displacement, and the result was the same - the elements were unresponsive.
In order for your elements to be responsive you have to link the action of you clicking them to your view's code. You can do this in a non-programmatic manner by ctrl-clicking your element on story-views and then dragging to the view controller. Then choose action instead of outlet, and choose when the action you want will be triggered (bottom part). Then insert your code in the viewController.
So I figured it out. I used the debug view hierarchy and saw that the alert was behind the elements behind it, even though it was still being shown (for some reason). I changed the zIndex of the UIView and it worked!

Wiring up Outlet Collection Trouble

From what I can tell there are some challenges people are having in XCode6 in terms of wiring up outlet collections. I just wanted to see if i'm doing this right or what I need to do correctly! I reviewed here Can't hook up an outlet collection in Xcode 6 using storyboard as well as other areas, but I wanted to be more basic about this first.
I have 7 images on a screen. I'd like to iterate through all of them in a loop or something. I read an outlet collection would be a sensible way to do this. To create an outlet collection, I am doing this:
While splitting the screen (storyboard on left, assistant editor on right) I control+click on one of my 7 images, and drag it into the view controller code on the right. This will prompt me to create an outlet, or outlet collection (I select outlet collection).
Now that this is done, a circle appears in the left margin next to this variable indicating that the image is associated with that variable. If I hover over the circle, the first image lights up.
What you're supposed to do (can someone confirm this please??) is you just hover your mouse over the circle, and a + symbol appears, and all you do is hold down the left mouse button, and drag over to another image (for example image#2), and it should automatically add that to the collection. The idea is to simply drag to each image so they are all added.
Is that right in step #3 above? Is this the normal way you would add items to a collection? Drag from the + to the image within your controller? For me, when I do this, the line appears, but it doesn't seem to respond to connecting the line to anything. I just hover it over the images, and it doesn't highlight the image or select it or anything, and when I let go, nothing happens.
I'm still somewhat new to this - what am I doing wrong?
Thanks so much for your patience/help!
OK I had the same issue and I think I have just found a workaround
1) Do steps one and 2 with the first image
2) Now repeat exactly what you did using the second image - drag and drop just below the first outlet collection (this would simply create a second outlet collection use exactly the same name )
3) Now Xcode won't like it as you have two outletCollections with the same name. Now comment out the first one
4) Now you only have one outlet collection. And it would be wired up to both your images. confirm it by hovering your mouse pointer over the little 'circle' next to the IBOutlet to see your images being highlighted.
This seems to work for me. So hope this helps :-)
There is an error with Xcode and Interface Builder that causes problems with outlet collections. You are doing it right, Xcode is problematic.
A workaround is to:
Go to your DerivedData folder (Xcode preferences -> locations)
Clean build folder from the Product menu while holding option (alt) button
Quit Xcode
Delete the folder starting with your app's name in the derived data folder
Go to your xcodeproj file, right click it, show package contents.
Delete the xcuserdata folder (warning: don't touch the others!)
Open Xcode again.
When you delete user data, window positions etc. will be reset to defaults and breakpoints will be deleted. Your project should work smoother (after a few seconds of re-indexing) and outlet collections should work properly.
I have had some success by just changing my workflow as follows (no need to restart Xcode).
First, create the outlets in code in the controller class file.
Second, drag from the objects (in the outline view of IB) to the controller, or back (for actions).
This has always worked without fail. It is slightly more effort, but actually negligible. Definitely an Xcode bug.

How do you stop Interface Builder embedding a control in a UIView when I drag it around?

When I move controls in Interface Builder and pass over a UIView. Is there anyway to stop IB from embedding the control in the UIView and making it a child of the UIView in the tree hierarchy.
BEFORE
+UIView
+UIButton
+UIView
If I move the UIButton with the mouse and place it above the UIView IB will make it a child of the UIView
AFTER
+UIView
+UIButton
+UIView
Is there anyway to lock the bottom view. I often use them as backgrounds and tint them.
You can reposition without embedding by pressing and holding Cmd while dragging the element.
Edit: This is only confirmed to work with Xcode 7.
I gave up and decided all groups of controls should have a parent UIView. Can be invisible (backgroundColor of clearColor)
Select all the controls then choose Editor menu > Embed in View.
After that we can safely move them around within their own grouping view without them jumping levels in the hierarchy.
One issue with Embed in View is when you use tagging and viewWithTag:
If you build your view using more than one VC controller and tag subviews make sure the tag ids are unique across the whole view hierarchy.
This is because viewWithTag: will only return the first control that matches the id and seems to search ACROSS the view hierachy before moving down a level to continue the search.
So if you choose Editor menu > Embed in View you're moving the control down a step in the hierarchy. So a call to viewWithTag:999 might have picked up your control before but now may return a completely different control.
It also may crash!
Its common to cast the result from UIView to control e.g UIImageView
Then call method on the control.
If viewWithTag find a different control than the one expected it may not even be a UIImageView so calling a missing method would throw exception.
BASICALLY never use tags as you have to debug in XIB and code and no checking for duplicate ids.
Drag from XIB to .h and create outlets instead.

Resources