Is it possible to use something like an IBOutlet array? - iphone

I have a top list view in my current iPhone app, that's populated by code. I've assembled the view using Interface Builder, so it contains lot of UILabels.
Obviously I wouldn't like to have name1, name2, etc. outlets in my class, but prefer a name[10] array.
Is it possible to do so, and connect each item to the appropriate label (or any other interface builder like view)?

You can of course do this with interface builder, the keyword is IBOutletCollection. What it does is basically an NSArray out of multiple interface builder outlets.
IBOutletCollection(UILabel) NSArray *myLabels;
So the next thing would be connecting your labels in interface builder and then you can use the array to access all labels at runtime.

Follow these steps to create an array of outlets an connect it with IB Elements (Here is example of UIView, you can use UILabel also):
Create an array of IBOutlets
Add multiple UIElements (Views) in your Storyboard ViewController interface
Select ViewController (In storyboard) and open connection inspector
There is option 'Outlet Collections' in connection inspector (You will see an array of outlets there)
Connect if with your interface elements
-
class ViewController2: UIViewController {
#IBOutlet var collection:[UIView]!
override func viewDidLoad() {
super.viewDidLoad()
}
}

you cannot do it in IB, but you can create an array in your init method and add all your labels to it.
BTW, you can set some tag to each label and define macro to access it. smth like
#define NAME[TAG] (UILabel*)[self.view viewWithTag:TAG]

This can be done using outlet collections, see this related question.

Related

Swift difference between IBOutlet/IBAction and programatically constructing a view?

im kinda new to swift, and I don't understand what is the difference between the Interface Builder Outlet/Actions and programatically constructing a view. If I have IBOutlet why I don't need to still add them as subviews of the self.view and why do I don't need to instantiate them? As well, to not create two questions, why in the case of a creating a custom UiView I have to load the xib file with Bundle.loadNib?
Thanks,
You cannot initialize a property that is not nil by nature at instantiation time.
Interface Builder outlet, which always initializes after its owner. In this specific case — assuming it's properly configured in Interface Builder — you've guaranteed that the outlet is non-nil before you use it. That is why we can use as below:
#IBOutlet private var searchBar: UISearchBar!
Also, you already added subviews as well.
SearchViewController - ContentView - searchBar
That means ContentView or self.view is already superview of searchBar so you don`t need to add as a subview.
IBAction, IBOutlet, is responsible for connecting with objects on the Storyboard.
IBOutlet is a variable for accessing values, and IBAction can define an action on the event.
With Storyboard, prototypes can be created quickly and are easy to implement. However, if you work with multiple people, it can cause conflicts, so be careful.

Connecting NSTableView's delegate and dataSource to a custom subclass?

My app reads text files into [Card]. Each Card has a two-letter code at the front, and I break up the cards into different NSTableViews depending on that code. That lets me set the layout in IB so each group of cards has an appropriate display.
I used to have all of the controller code in a single VC, but as the number of tables grew, so did the complexity of this code. Since the views differ primarily in layout and some default settings, they can all descend from a single class. So I did:
class CardView: NSTableView, NSTableViewDataSource, NSTableViewDelegate { ...
and, for one example...
class GeometryView: CardView { ...
Then I went to IB, selected the tableview, and changed it's class to GeometryView. Now I have to set up the delegate and dataSource, and this is where I have my problem : IB will not allow me to drag either setting to either the GeometryView or CardView.
So... do the targets of these IB settings have to be a particular subclass, say NSViewController? Or is there something I'm missing that lets IB see these as targets? I didn't do anything in the original VC, it just worked. Or am I simply doing the wrong thing in IB?
In this image you can see the tableview on the far left, the custom view subclass in the helper, and the connections for the tableview on the right. Any attempt to drag from the connections to anywhere in the helper fails. Note that the two existing connections are to the former delegate VC, which is what I am trying to replace.
I'm not sure why Interface Builder won't let you connect the delegate or data source to itself, but you could do it programatically. The awakeFromNib method is probably the best place for this, as it's called after both initWithFrame and initWithCoder:
override func awakeFromNib() {
delegate = self
dataSource = self
super.awakeFromNib()
}

Create an outlet in storyboard to an inherited property

I'd like to create a basic view controller class BasicController with two subclasses SubclassController and AnotherSUbClassController. BasicController controls view that have a button inside them, so there should be a
weak var buttonThing: UIButton?
property in it. In the actual implementation I want to use the subclasses in various parts of the interface: I want to draw them in storyboard, put buttons in that drawings, and connect the buttons to the inherited buttonThing property via an outlet. But wait, the buttonThing property was announced in the superclass and doesn't even appear in the code of the subclasses. So how do I connect the buttons to that outlet?
You can ctrl-drag the UIButton from your storyboard to your BasicController for each subclass you have laid out in your storyboard. You can then use the buttonThing in each subclass as usual.
Remember to link your subviewcontrollers to their respective viewcontrollers in the storyboard.

How can I populate UITableView with XML?

I have a tab bar application. In one of my tabs, there is a search bar and a table view below that. When you enter something into the search bar, it returns parsed xml. I need to put this parsed information into the tableview below. The class inherits from UIViewController. I declared a UITableView object in the header file and linked it in interface builder, and adopted the UITableViewDelegate protocol.
I'm not sure If i'm going about this the correct way. Any help?
That sounds about right. You will need to also have your UIViewController implement UITableViewDataSource, and add the methods from that protocol to populate the table.
There are various tutorials available which guide you step-by-step to create a simple tablview. Google them. You can follow these steps for connecting your tableView outlets:
Select your viewController where you are displaying the tableview to be your "File's Owner" in Identity Inspector.
Drag your view's outlet to your File's owner.
For tableView inside view, drag its outlets to File's owner again so that your datasource and delegates are up. And in the same view, drag your referencing outlet to the IBOutlet you have created in your viewController class.

How to get a reference to a control in the view?

If I have a UIScrollView set up in the view via the Interface Builder, how do I get a reference to it in the ViewController implementation? I want to programmatically add labels to the scroll view.
For example, in C# if you have a textbox declared in the UI/form, you can access it by simply using the ID declared for that textbox. It doesn't seem this simple in objective c.
Thanks
Kevin
Assuming I understand you rightly and you are instantiating a view controller from a .xib containing subviews including the UIScrollView you want, there are two ways - first, you can find it in the subviews array that is owned by the view controller. Second, you can add an IBOutlet reference to it in your header file, then in interface builder make the connection using the connections inspector. Then you can refer to the object in your code, change frame, add labels etc.
You need to wire your ViewController up to your Nib files. This is pretty straightforward. This is your basic workflow for using Interface Builder on the iPhone/iPad:
Set the Class of the 'File's Owner' to the class of your view controller. You can do this by selecting the 'File's Owner' object in your nib window, pressing Command-4, and setting the class via the drop-down.
Create properties in your View Controller with the following format:
#property (nonatomic, retain) IBOutlet UIScrollView *scrollView;
The IBOutlet keyword is a macro that evaluates to nothing. So it doesn't actually do anything to your code, it just exists to let Interface Builder know that the 'scrollView' property can be bound to.
Control-drag from the object you'd like to bind to your ViewController. In the popup you can select the property you'd like to bind to the scroll view object.
This sort of stuff is pretty basic Xcode stuff. If you read any tutorial out there it'll cover this. Good luck, and enjoy!
edit:
I should add that if you used the default "New UIViewController Subclass" from the New File dialog, it will have done step one for you. You'll have a nib file and a View Controller that already know about each other.
Yes, the code you wrote is all you need in your header. Just make sure you connect the Scroll View object to the property in Interface Builder.
Yup! 'viewDidLoad' is added after all the connections specified in the Nib file have been made, so you can be confident that scrollView point to the correct object (assuming everything in the Nib is wired correctly, which is an easy mistake to make)