Do I need to create a controller for a UITextField? - iphone

Just starting out with an iPhone application using xcode 4.2.
I understand that it is good practice to use a subclass of UIViewController for each view in my application, and I am able to write some basic code in these to test buttons etc on the associated view.
Now I want to perform some action on a text field in one of these views, let's say I will use the Value Changed event to log the textfield's contents on each keystroke.
Should I be creating some kind of UITextField controller subclass? Or do I deal with this kind of thing in the existing ViewController subclass that houses the textfield?
If the latter, how do I refer to the textfield in the view controller subclass, and make the connections?

You'll probably want your UIViewController to implement UITextFieldDelegate. Connections can be made via the Interface Builder and outlets or just setting the delegate on the text field and using the reference you get from the delegate callbacks.

You would use the existing ViewController subclass that houses the textfield. A good rule of thumb is one ViewController per screen of views (not including UINavigationController, Modal screens, uisplitviewcontroller, and popovers).
To refer to it, you would make a property in the .h of your custom UIViewController:
#property (nonatomic,weak) IBOutlet UITextField * myTextField;
Note the IBOutlet keyword. This will allow you to connect it in InterfaceBuilder (or your storyboard). To learn how to connect that I would recommend you watch a video about IBOutlets since its more of a visual thing.

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.

Interface Builder won't allow connections to custom UIView class?

Using Xcode 4.3.3, I can't figure out how to connect outlets in a custom UIView class with objects created in Interface Builder.
In one ViewController, I have a variety of buttons, sliders, etc that I'm trying to group into Views. So, within that ViewController in IB, I added 3 views. Only 1 view will be visible at any given time.
I derived custom UIView classes to handle each of these 3 views. My view controller instantiates each of the classes. I selected the view(s) in IB, opened the Identity Inspector and set the Class(es) to my custom class(es). But when I tried dragging connections from the view and/or it's constituent controls to the custom view's .h file IB won't add a connection.
IB allows me to add outlets/actions by dragging to the parent view controller's .h, but not to the custom view's .h file. I thought once I set the View's class to be my custom class, I could drag outlets for the view's components to my custom class rather than in the view controller.
This question seems identical to mine: how to connect UIview outlets to a custom subview The two solutions (manually adding outlets and setting the view's class in IB) did not change the behavior for me. Here are the manual outlets I added:
customView3.h
#import <UIKit/UIKit.h>
#interface customView3 : UIView
#property (retain) IBOutlet customView3 *view3;
#property (retain) IBOutlet UISlider *slider;
#end
customView3.m
#import "customView3.h"
#implementation customView3
#synthesize view3, slider;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
#end
What am I missing here? What else do I need to set/check in order to add outlets to my custom UIView rather than the view controller?
Note that I did get this to work today, but had to insert/type the outlets by hand in the derived class, then I could drag from the header file to the UI element in the Storyboard, but not the other way around.
I opened a bug with Apple. If anything interesting happens, I'll update this answer.
Updated 10/4/13: After much research, it seems the root of the problem is that IB believes that I'm trying to connect objects to properties within a class, that I'm going to then create a swarm of instances of this class and then IB won't be able to tell which instance should handle the messages. So, it disallows the connection on the belief that I'm (potentially) making simultaneous connections from one object to multiple copies of a property across several instances of the class.
My view is that I only want a single instance of the custom UIView, and that I should be able to tell IB, "don't panic, you're only dealing with this one instance."
I'm now focused on a new project and haven't had a chance to retry this in Xcode 5; however, given the info above, I'm not optimistic it will work in Xcode 5, either.
What you're trying to do is certainly both sensible (IMO) and possible. XCode is however quite quirky when it comes to establishing connections to outlets in subviews.
I've found that cleaning, rebuilding and sometimes restarting XCode tends to help, but sometimes it just doesn't work. In some cases I got it working by manually creating the outlet and dragging from the outlet to the control rather than the other way.
This is not very helpful, I know, but I just wanted to make it clear that this is supposed to work and when it doesn't it is most certainly due to a bug in XCode.
In my experience, you add IBAction and IBOutlet to subclasses of UIViewController and not subclasses of UIView. So within the MVC model, your "1" UIViewController has all of these IBOutlets in it and then you use the data from these IBOutlets to update your views.
So you are fine creating the UIViews objects in IB and then creating the corresponding classes in code and then changing the class of the UIViews objects in IB to your UIView subclass. Just put all IBOutlets in the UIViewController that has all the UIViews under it, get the values you need from the IBOutlets and then pass them down to (set them in) your UIView subclasses.
Hope this helps.
I had the same problem and found a workaround:
1) Open the Assistant Editor with customView3.xib on the left and customView3.h on the right
2) ctrl + drag from UISlider in customView3.xib to the customView3.h code on the right
3) An option to create a new Outlet connection will pop up.
4) Name the connection and click connect
It will then create a connected IBOutlet.

Will touchesBegan method called without UIView or UIViewController in iPhone?

I created an app in where i have appdelegate class only. I dont create a UIView or a view controller. I just added textFields, labels and buttons in my window.
I want to hide the keyboard when the user taps out of the text boxes. This is normally achieved by the method touchesBegan. For implementing this method, two things we need to do.
One is add in the header file(.h)
Another one is set the textField's delegate. Thats is, textField.delegate=self;
I did those two things. But still the touchesBegan method did not called.
Why? Should i have a UIView or UIViewController class for it?
Thanks in Advance
UIWindow is a subclass of UIView, so you could just hook into those. But this is a seriously bad design pattern. Consider modifying your application so it uses a single view controller, rather than doing everything in the app delegate. Otherwise you're jury-rigging the app delegate to be something it was never designed to do.
touchesBegan is a UIView method. if you want to do it in your setup you should create a UIView subclass, put all your controls in that one and implement touchesBegan in the UIView subclass.

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)

UITableView and a UITextField that is always visible

I want to create an application which combines a chat feature. My question is this: how can I have a UITextField that is always visible in the same view as a UITableView?
The obvious solution would be to create my own UIView having a UITableView and a UITextField below it, however the UITableViewController doesn't seem to like me doing that as it expects the connected "view" outlet to be a UITableView, essentially destroying my plans.
Anyone with an idea?
Don't use UITableViewController. After all, it's just a standard controller with a full-screen UITableView. You can roll your own easily.
Use a standard UIViewController and have it implement UITableViewDelegate and UITableViewDataSource protocols (you don't need to implement every method -- just the required ones). Then give it a UITableView as an iVar and set the delegate and dataSource to self. Size it so it only takes half the screen and your other views take the other part. You can lay out the whole thing in IB or create and position view+table manually.
I would suggest sticking a regular view in between your controller and your smaller "half-views". That has usually cleared things up for me, or at least exposed what the problem might be.
If you don't need functionality that UITableViewController provided, than you can just use
UIViewController with <UITableViewDataSource, UITableViewDelegate> protocols.
So, your main viewController will accept any type of views.