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 :)
Related
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?
I would like to be able to interact with the UIControl I have made, and therefore want it in my ViewController.
What I tried
I subclassed UIControl (1).
Then I added a UIView to my View Controller and assigned it the new class (2).
But in Interface Builder I am not able to set my outlets to the buttons contained in the new class (1)?!
1:
2:
UIControl's documentation confirms that it is a subclass of UIView, and I should therefore be able to connect the outlets, right?
What am I missing here? :/
Off-course you can't add IBOutlet because buttons what you added to WeekdayControl are in UIViewController, you can't add Outlet to WeekdayControl, buttons only subviews of WeekdayControl, UIViewController is boss here, and you can add outlet only to UIViewController. (Sorry for my English)
Better create you buttons programatically in WeekdayControl.
Must read first:-
You cannot use the UIControl class directly to instantiate controls.
It instead defines the common interface and behavioral structure for
all its subclasses.
The main role of UIControl is to define an interface and base
implementation for preparing action messages and initially dispatching
them to their targets when certain events occur
So, you are doing wrong, if you really need to make a custom view or custom control then you can directly do it by creating a custom UIView and connecting the outlets directly with the view.
I think you missing the objective of subclassing a UIControl, it doesn't give rights to create outlets as it's a subclass of UIView,just read this lines what it is stated in the docs:-
Subclassing Notes
You may want to extend a UIControl subclass for either of two reasons:
To observe or modify the dispatch of action messages to targets for
particular events
To do this, override sendAction:to:forEvent:, evaluate the passed-in
selector, target object, or UIControlEvents bit mask, and proceed as
required.
To provide custom tracking behavior (for example, to change the
highlight appearance)
To do this, override one or all of the following methods:
beginTrackingWithTouch:withEvent:,
continueTrackingWithTouch:withEvent:, endTrackingWithTouch:withEvent:.
Where should I customise my IBOutlets?
Say I have created a button with interface builder, created an IBOutlet for it and I would want to change a property during runtime (ex: background color or localized title).
I would think of adding it to the viewDidLoad method, but outlets aren't yet created.
I remember having nil outlets in viewDidLoad, but I might be wrong.
If I move it viewWillAppear, the code will be executed every time the view controller's view appears.
Is there any better place for my IBOutlet related code, so it's only executed once?
Obviously I can do just about any customization using only the interface builder and making use of the User defined runtime attributes or localized stroryboards, but I don't like that since it's much more tedious to change later.
From the Doc
Its clearly says about the Views loaded into the memory in the -viewDidLoad() delegate itself.
I would think of adding it to the viewDidLoad method, but outlets
aren't yet created.
It is a false statement, Because you only get the viewDidLoad: message after IBOutlets are created. So you can safely do any customization in viewDidLoad:
Let’s say you have a Button you want to customise. You put the button at the place where you want it to be and then open the “Identity Inspector” on the right.
There is a textfield for “Custom Class”:
I usually create a subclass of UIButton / NSButton (depending on iOS or OSX) and edit the behaviour, drawing methods and functionality in this class file. Then just add the name of this class in this textfield. Voila!
OK, so this one is probably a bit challenging, as it is monotouch...
I have a reusable custom toolbar that that I plan to reuse on multiple screens.
I want to create the toolbar in Interface Builder
I want to be able to update labels on the toolbar from ANY view controller. So I might have five different view controllers that all have this toolbar, and can update labels on it.
So my question is:
How do I even begin to subclass UIView in MonoTouch? If I create a new "iPhone View", all it gives me is a nib. I have no place to hook up outlets or actions.
Given that you are able to tell me how to set up MonoTouch to have C# code files for subclassing UIView so I can handle events and access properties, how do I hook it up to the nib? I see a lot of people saying to use initWithFrame to call loadNibNamed in Objective-C, but this doesn't correctly translate to MonoTouch. How would I do that in MonoTouch?
Given that #1 and #2 are fulfilled, how do I load this custom toolbar into any viewcontroller, and add it at specific coordinates on the screen? Doing the initWithFrame CGRect stuff doesn't seem to have a simple path in MonoTouch
If anyone is able to figure this out, you are amazing!!!!
Thanks you in advance!
So after a lot of digging, I finally found the answer.
The most informative tutorial was here:
http://sgmunn.com/blog/2012/03/using-loadnib-to-load-a-view/
Essentially, you need to create custom subviews, set them up in the interface builder, then do some simple mapping on the MonoTouch side. But the key point that was throwing me off from the example was this:
You must, when subclassing UIView, implement the base constructor for IntPtr
When you do that, everything falls into place. You have your Outlets and Actions hooked up, and can manipulate them at will.
EDIT: To be more descriptive than just linking...
How do I even begin to subclass UIView in MonoTouch? If I create a new
"iPhone View", all it gives me is a nib. I have no place to hook up
outlets or actions.
Create a new iPhone view, it'll create a nib. Open the nib, set the "custom class" to your custom class. MonoTouch should generate it automatically. If it doesn't, create a new C# class and subclass UIView, but make sure you create the constructor for IntPtr. If you use Storyboards, when you call Storyboard.InstantiateViewController() it'll fill in the IntPtr value for you. Note that if you DO use Storyboard.InstantiateViewController, you need to set the identifier as well to your custom class' name.
Once you create that iPhone view, you should be able to open up "code view" in IB and hook up your outlets and actions.
Given that you are able to tell me how to set up MonoTouch to have C#
code files for subclassing UIView so I can handle events and access
properties, how do I hook it up to the nib? I see a lot of people
saying to use initWithFrame to call loadNibNamed in Objective-C, but
this doesn't correctly translate to MonoTouch. How would I do that in
MonoTouch?
There is no initWithFrame: or CGRect in MonoTouch, you use RectangleF. If you load the nib programmatically, you can use the constructor that takes in a RectangleF and use that to set x, y, width, height.
Given that #1 and #2 are fulfilled, how do I load this custom toolbar
into any viewcontroller, and add it at specific coordinates on the
screen? Doing the initWithFrame CGRect stuff doesn't seem to have a
simple path in MonoTouch
For Storyboards use Storyboard.InstantiateViewController (make sure you set the identifier in IB). For everything else, use:
var nibObjects = NSBundle.MainBundle.LoadNib("YourViewName", theController, null);
var instantiatedView = (YourClassName)Runtime.GetNSObject(nibObjects.ValueAt(0));
as depicted in the above link.
Enjoy! - Allison.
Instead of loading Nib files from iOS 9 onwards you can use container views and storyboard reference to achieve the same.
You can check here
I have a nib file where I have a view that contains a background image, a button and another image that covers the full screen (a shadow) that needs to be moved to the front.
On the view, I'm creating child views, and after creating those and adding them using [self addView] I need to move to the front the shadow image.
I'm currently using the tag attribute to find that view, but I'm thinking there's probably a better way, by means of identifying the subviews I add in Interface Builder by some name.
I tries adding a IBOutlet to connect the subview with its parent, but it didn't work (and made no sense, since the subview is already connected to its parent in some way).
The IBOutlets way should work, and is probably the best way to do it. Make sure you made the proper connection in Interface Builder after you declared them in the .h file.
The iPhone does a lazy loading of view controllers. The nib might not have been loaded in initWithCoder or any init method for that matter as Kendall specified.
viewDidLoad is the preferred place to access anything from the nib if you want to access them before the view is displayed.
Hope that helps.
At what point are you trying to access the subviews? If you try within init of a ViewController, the IBOutlets will be nil. The first method you can get at them is probably viewDidLoad.
The reason it does make sense to do things this way is that IBOutlets are just direct pointers to some component, even if they are already subviews of something else. Just saves a lot of hunting.
Using the Tag is a perfectly valid way to locate specific views, so long as you're using the viewWithTag: method. If you're already using tags, there's no need to change to IBOutlets unless you just don't like calling viewWithTag:.