How to activate "Installed" programmatically? - ios

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 :)

Related

Hide Outlets from Connections Inspector for Custom View

I have created a custom view (Quantity View) with nib file in Swift. I have created some IBOutlets & IBActions (for buttons, labels etc.) in my custom view.
I tried to use this custom view (Quantity View) by assigning class name to a UIView in my storyboard.
It's showing me all the IBOutlets & IBActions in the Connections Inspector, as shown in this screenshot: .
I just want to show only delegate for the Custom view.
Possible Answer:
I thought I can use the -viewWithTag to get the views instead of Outlets.
But, I want to know if it's possible with having Outlets also or if there is much better way to do this?
What are the other possible ways (optimum) to handle this situation?
You can also consider the following solution:
You can take the subviews of your QuantityViews(custom view) and you can identify the specific views by its frame origin.
Note : you should know the customview subviews frame
Its not possible to hide IBOutlets from storyboard if you declare the class members as IBs (IBOutlets or IBActions).
The IBOutlets or the IBActions are just indicators to the interface builder so that it can show the names on it when you try to bind them it actually calls the setValue: forKey: method to set the view's reference to the IBOutlet property.
Now if you try to access an subview from the file's owner class without any IBoutlets you need to have a pointer to point it, so for that either you can get the reference using ObjectID which is assigned to the subview by the interface builder or you can get it using the viewWithTag: method.
The ObjectID you need to find all time when you add or replace a subview from the view, so better and convenient approach is to use tag property of UIView class.
So my conclusion to this problem is to access the views using the viewWithTag method you mentioned earlier.
I think your way is correct. But sometimes Xcode doesn't work correctly.
The following makes the IBOutlets and IBActions reappear and work properly:
Clean project your project in Xcode.
Quit Xcode completely.
Delete all contents of ~/Library/Developer/Xcode/DerivedData/.
Restart MacOS just in case.
I hope you will resolve that :)

How to access custom view properties after initialize

I'm targeting IOS 8+.
I have a form that is used in more than one place. So I decided to create a custom view where I define the various "form" text fields.
I have built my XIB, and the UIView subclass contains the outlets for each textField.
The view is composed of a background image and a scroll with the form fields over it.
Now, my first obstacle was: I need to have this custom view in a container that may or may not have a navigation bar. This made me create a constraint outlet so I could update its value to push down the scroller view. This way I'd have the whole image in the frame, the top being behind the navbar and the scroller bellow the nav bar).
Here's a manual drawing to help understanding the problem.
It's very possible that I'm making a lot of mess and confusion on my way to solve this. :)
The problem is:
After awakeFromNib runs I have no access to the constraint property. I then noticed the same thing happens for the TextFields outlets.
So, how can I access the custom view's properties when I instantiate them programatically?
Something like:
Controller:
let customView = SignupView(frame: f)
view.addSubview(customView)
customView.pushScrollerDownBy(50.0)
Custom view:
func pushScrollerDownBy(yOffset: CGFloat) {
//topScrollerConstraint is the outlet for the textField.
topScrollerConstraint.constant = yOffset //right now topScrollerConstraint is nil.
}
You should check if you have connected your topScrollerConstraint to the file's owner since it will not get instantiated and therefore, error. Here is a recent SO question regarding difference between these two:
What is File’s owner in XIB in this case?

XCode 6 - iOS 8: programmatically check if view is installed

I am using class sizes in interface builder, defining slightly different designs for different sizes.
One of my view is not installed for a specific size. That works as expected, but now I would like to programmatically be able to tell if that view is installed or not. Whether it is installed or not, it looks like the view is never nil, and I can't see any isInstalled flag to check.
What is the correct way to do this?
This isn't a great solution, but I've not found a better one yet:
The docs state that "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".
So a test for a valid superview works as a solution, but I've found that it has to come quite late - in viewDidAppear. The superviews are still nil in viewWillAppear, for example.
From Apple Docs:Installing and Uninstalling Views for a Size Class
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 could check by evaluating PossiblyUninstalledView.superView != nil. If it is true, then the class is properly installed.
You could make an extension to UIView and check to see if the view has a superview. If it's Installed it will return true, if it's no it will return false.
extension UIView {
func isInstalled() -> Bool{
return (self.superview != nil) ? true : false
}
}

How are NSTableCellViews supposed to be laid out?

I have a fairly basic MainWindow.xib with a source list-style sidebar. I created it by dragging the Source List template into the window, which already contains two NSTableCellViews: HeaderCell and DataCell.
The latter consists of an icon (using NSImageView) and a label (NSTextField). Instead, I want the label and another, smaller label underneath. In IB, this looks as follows:
If I focus on just DataCell, it highlights accordingly:
Thing is, actually running the program, it looks nothing like the template:
Notice how the two NSTextFields just get smashed together into one. My understanding was that view-based NSOutlineViews (and view-based NSTableViews, for that matter) are supposed to be designed as a template from within IB. Instead, the dimensions from the template seem to get mostly ignored.
Here's the code that sets the view's values from the data source:
public class TourSourceListDelegate : NSOutlineViewDelegate
{
public override bool IsGroupItem(NSOutlineView outlineView, MonoMac.Foundation.NSObject item)
{
return (item as TourSourceListDataSource.Item).IsHeader;
}
public override NSView GetView(NSOutlineView outlineView, NSTableColumn tableColumn, MonoMac.Foundation.NSObject item)
{
if (IsGroupItem(outlineView, item))
{
return outlineView.MakeView("HeaderCell", this);
}
else
{
var data = item as TourSourceListDataSource.Item;
var dataView = outlineView.MakeView("DataCell", this);
(dataView.Subviews[0] as NSTextField).StringValue = data.Name;
(dataView.Subviews[1] as NSTextField).StringValue = data.Date_start.ToShortDateString();
return dataView;
}
}
}
I've tried overriding GetRowHeight, but that doesn't seem to resolve the problem (it makes more room, but still doesn't let the views distribute themselves properly), nor does it seem necessary.
I've also tried playing with the various Autosizing, Autoresizes Subviews, etc. toggles in IB, but that doesn't seem to produce intuitive results, and again, it doesn't seem necessary — the view as presented in IB is exactly what I want, just with slightly longer labels in practice.
I haven't tried converting this to AutoLayout yet.
What obvious step am I missing?
Some more info that probably doesn't make a difference: this is a Xamarin.Mac/MonoMac project with Xcode 5.0, MacOSX10.8.sdk, Xamarin Studio 4.0.12, Xamarin.Mac 4.0.12, and Mono 3.2.3 (targeting Mono / .NET 4.0). I've also enabled App Sandboxing.
What's important in interface builder is the view hierarchy. What kind of view is that cell? Are those labels really subviews of the cellview or not? The hierarchy should look something like:
One thing that's fishy that I see is accessing dataView.Subviews[0] and [1]. If you're adding subviews to your cells then should be creating your own NSTableViewCell subclasses, with each view connecting to the subclass' IBOutlet properties. The subclass doesn't need any code in its implementation, just the declaration of its properties in #interface, such as titleField and descriptionField, and an empty #implementation that auto-synthesizes them.
Then makeViewWithIdentifier (or apprently the glue MakeView in Xamarin) when passed the right identifier should create your NSTableViewCell subclass, and at runtime you can verify that using po dataView in the debugger. Then you access the subviews using the properties of your NSTableViewCell subclass' interface instead of assuming which view is in which position with the subview array, using dataView.titleField and dataView.descriptionField.
If your cell view has one text field then you can use NSTableViewCell without subclassing, but do connect up the textField outlet (its connected by default as long as you don't delete & recreate the cell view's label view) so you can access it through the property, again instead of having to dive into the subviews array.
All that said, it's not really clear why you're seeing what you are. It looks like those aren't the subviews you expect, and might even look like the wrong fonts as well as in the wrong positions. Using a custom subclass of NSTableViewCell and verifying its class at runtime is a good way of making sure it's creating the view you expect, but you can also dump the subview within the debugger using po [dataView _subtreeDescription].

UIView subviews' order?

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

Resources