Double Picker Question - iphone

I want to display the contents of a double picker to a label without hitting a button in the process. Can anyone show me how this is accomplished.
I displaying calculations to a label and I want them to change as the user moves the picker.

You need to set up a UIPickerViewDelegate, set it as the delegate of your picker, and implement – pickerView:didSelectRow:inComponent: to modify your label how you want. The UIPickerViewDelegate protocol reference is here. I would probably just set the viewController for the containing view as the delegate, but it depends on how your program is structured.
EDIT - example code added:
You declare a class as implementing a delegate protocol with <> notation as in the following:
#interface MyViewController : UIViewController<UIPickerViewDelegate>
Then you can set the delegate of your picker view instance like so:
myPicker.delegate = myViewControllerInstance;
Or, if your picker is an ivar of the viewcontroller class:
myPicker.delegate = self;
Then, inside the implementation of your MyViewController class you can optionally implement the methods of the UIPickerViewDelegate protocol, and the corresponding messages will be sent at the right time. eg, -pickerView:didSelectRow:inComponent: (if implemented in your delegate) will be called whenever the picker selects a value, and it will be passed the row selected and the component the row was selected in.

Related

Recognize tab button pressed to move to next responder

I have multiple instances of a custom class that takes inputs from keyboard. You can think of UITextField (but they are not UITextField, they are NSObject). However, they all have a property UIControl *control.
These objects are instantiated and put into an array (orders matter), and they are put on the screen in the same order.
Scenario 1: User tabs on the first object, it becomes the first responder. User taps on another object (from the same class) and that becomes the first responder. No problem.
Scenario 2: User tabs on the first object, it becomes the first responder. User taps on the TAB button of the keyboard (iPad or iPhone or wireless keyboard), I want the next object in the array becomes the next responder. iOS picks randomly [? or with some logic not clear to me] another object which is not in the same order as I want.
Problem: Because these objects are NSObjects, how can I intercept the transition to the next object. I tried using tags or tracking who is the first responder, but the problem is, if user taps on an object out of order, it is fine - I don't want to intercept that. I only want to intercept transition from one object to anther only if it is through tapping on TAB (or Next or Return) button of keyboard.
Any idea? Thanks.
You can set your custom class to have something like this
#interface testClassButtonSub : UIButton
#property (weak,nonatomic) IBOutlet UIButton *nextButton;
#end
Then you can even use the interface builder to set which will be the next responder for when a certain action is taken. (an user presses the return when inside a textfield in your custom class)
For the return you have to declare your viewcontroller as the delegate of the specific textview.
First you set the viewcontroller header like this:
#interface RegisterViewController : UIViewController <UITextFieldDelegate>
then you set the delegates in the implementation
// Set Delegates of the Text Fields
eMail.delegate = self;
userPassword.delegate = self;
userNickname.delegate = self;
and you use this delegate method to jump to the next object
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
// Jumping code here
return NO;
}
HOWEVER in your case your textfield must be inside your object, so you have to make THAT object the delegate, and in that object's implementation jumping code add the
[thisObjectsTextfield becomeFirstResponder];

How do you notify a view controller that a row has been selected in a UIPickerView?

How do I notify my view controller and pass it the string when a row was selected in my UIPickerView?
I have a custom UIPickerView in regular view and I have a custom datasource/delegate in a different class.
How do I notify my view during the pickerView:didSelectRow:inComponent: delegate method? and pass the selected string to the view controller?
The class that is conforming to the picker delegates would implement
pickerView:didSelectRow:inComponent:
to know which row (or string) was selected in the picker.
If some other class from the outside world wants to know which row was selected, then this class in turn needs to inform. This will create a chain of delegation.
For example, if pickerClass is the class that implements the delegate method. If some other class (say outsideClass) wants to know about which row was selected, then you would make this outsideClass delegate of pickerClass and pass on this message to it.
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
[_pickerClassDelegate pickerClass:self didSelectRow:row inComponent:component];
}
For that, you have to create one method in custom class like below:
.h file
id parent;
.m file
-(void)initWithPageNumber:(id)pidParent{
parent=pidParent
}
Then you have set the delegate method programatically like below:
uipickerview.delegate = parent;
uipickerview.datasource = parent;
Hope it will be helpful.
Let me know in case of difficulty.
You can do this by either using posting and observing notification using NSNOtification centet or by creating a delegate protocol. Study delegate protocols that is a good thing to learn in objective-c.

How to access variables of a ViewController in a subclass?

I guess this is basic, but I can't get my head around this.
I used to have only one ViewController in which all my variables were defined, e.g. an UITextView named myTextView. I also had methods in this ViewController for handling events that relate to myTextView, such as - ()hideKeyboard { // do something with myTextView or - (void)keyboardWillShow:(NSNotification *)notification { // do something with myTextView.
As my program became bigger and bigger, I thought about using subclasses, especially for other views. So I started a subclass, eg. mySubClass.h and mySubClass.m, in which I had another UITextView (for argument's sake myOtherTextView). In order to incorporate mySubClass, I #imported it into my ViewController and added a #class mySubClass; and could then produce instances of this class so as to use it in my App.
So far so good. As you can imagine, all the nice methods I defined in my ViewController for what should happen when an UITextView is edited (such as hiding keyboard etc.) didn't work for the UITextView in mySubClass.
It was then suggested to me that I should make another class in which I had all the keyboard events and subclass my ViewController and mySubView to it:
#interface ViewController : MyKeyboardEventsViewController
Now, the problem I am seeing is that I won't be able to access all the views, textviews, textfields etc. that I have created in my ViewController (e.g. myTextView which I mentioned earlier).
How can I achieve that all the variables that I have defined in my ViewController will also be available for MyKeyboardEventsViewController? Or is there another way to handle this?
Basically, I don't get how MyKeyboardEventsViewController will be able to access variables in my ViewController which it will need (e.g. the UITextView in question, or the accessoryView which will pop up etc. etc.).
Any suggestions would be very much welcome.
Example:
Class A contains a ivar UITextField textField
Class B subclasses Class A and thus it already contains ivar textField
Note: it's not the other way around. Class A does not "see" what ever is created in Class B.
When ever you subclass a class you give your new class the same ivars end methods of that subclassed class.
I hope this is what you were asking for.
EDIT
So for your example I would do the follwing:
Create a class "MyUIKeybordEventResponder"
Implement all the responder methods like - (BOOL)textFieldShouldReturn:(UITextField *)textField
Subclass your ViewController from "MyUIKeybordEventResponder"
Note method textFieldSHouldReturn has a parameter UITextField so it knows which textfield was pressed. So in a way it receives your textField from the subclass.
If I'm understanding this correctly, you have a UIViewController with MyKeyboardEventsViewController as an instance variable and you want to communicate between the two? If that is the case, one option would be to create a protocol.
#protocol MyKeyboardDelegate
- (void)closeAccessoryView;
#end
(Note - make whatever methods in the protocol that you need, this is simply an example)
In your MyKeyboardEventsViewController you then include the protocol file, and create an ivar
id <MyKeyboardDelegate> delegate;
Also make it a property and synthesize it.
Whatever class that is going to create the keyboardviewcontroller should delcare themselves as conforming to the protocol.
#interface MyViewController : UIViewController <MyKeyboardDelegate>
...
#end
When you create the MyKeyboardEventsViewController, set the delegate.
MyKeyboardEventsViewController *eventsVC = [[MyKeyboardEventsViewController alloc] init];
[eventsVC setDelegate:self];
Now just implement the delegate method and perform whatever action that is necessary.

Objective-C iPhone - Delegating an IBAction from one class to another? Can this be Done?

I have created a class, that makes it easy to enter in the amount for a particular price in the same way an ATM machine allows you to enter in an amount, user does not enter the decimal.
This is a generic class called (AmountPicker), so that it can be used among many other classes. I am using it by invoking the presentModalViewController method, this class uses a nib file. Inside the xib there is a hidden text field and a label along with a done button in the navigation bar. The done button is an IBAction connected to a method named doneButtonPressed.
I am wanting to know if it is possible to delegate this method to another class, so that the logic inside the method can differ from the one already defined inside the amountPicker class.
The reason is, I use the amountPicker Class in two places one for entering a purchase, which takes the label text and assigns the value to a variable inside the appDelegate, this was ok when i just used it in one class, but now there is a detailTableViewController of the purchase and this view will also need to provide a way to change the data in case it was entered wrong.
So in the detail view i am using a custom header, the custom header has a textField for the name of the purchase, a button to activate the AmountPicker, and a label for the amount, when the amount button is pressed then the AmountPicker class pops up and the user enters the amount and presses the done button, NOW, this is where i need to change the logic for the doneButton, instead of using a variable in the appDelegate.
I was thinking that the DetailTableViewController could act as a delegate for the amountPicker Class and override the doneButtonPressed method, so that the amountLabel can be updated with the new amount.
Is this possible, if not what is the right way?
Your thinking is right along with how delegation is normally used. What I would do is create an Objective-C protocol, maybe AmountPickerDelegate. Then, in your interface for the AmountPicker, you would have this:
#interface AmountPicker : NSObject {
NSString *someValue;
...
id <AmountPickerDelegate> delegate;
}
#property (assign) id <AmountPickerDelegate> delegate;
#end
Then, in your delegate class, you would do this:
#interface DetailTableViewController : UITableViewController <AmountPickerDelegate>
Finally, in the original AmountPicker class, you could call something like this:
[delegate amountPickerDidPressDoneButton];
which would execute in the delegate.

What is the easiest way to add a row in a UITableView with a user-provided string?

I have a simple UITableViewController in a UINavigationController that displays a list of strings from an array with the default Edit/Done button on the right-hand side of the navigation bar.
When pressing the Edit button, the UITableView animates correctly and shows the red minus icons to delete. Pressing the delete button removes the row from the table view and the array (implemented in the tableView:commitEditingStyle:forRowAtIndexPath: method of the UITableViewController).
I would now like to allow the user to add a row to the view (and add the string to the underlying array), but I'm not sure how to go about doing so. The commitEditingStyle method has else if (editingStyle == UITableViewCellEditingStyleInsert), but I don't know how I can get the user to input the string.
I've read the Table View Programming Guide (more specifically the example of adding a table-view row), but this seems to require a whole new UIViewController subclass just to get a string from the user.
Is there no easier way?
Creating another view controller is probably going to be the easiest way in the long run. You can present it modally by calling
SomeViewController* theViewController = [[SomeViewController alloc] init];
[self presentModalViewController: theViewController animated: YES];
[theViewController release];
When the theViewController is ready to go away it can call
[[self parentViewController] dismissModalViewControllerAnimated: YES];
OR
you can setup a protocol for your new view controller so it can notify your original view controller of completion and send a value back, if you wanted an NSString back you might use
#protocol MyViewControllerDelegate
- (void)myViewControllerDelegate: (MyViewController*)myViewController didFinishWithValue: (NSString*)theString;
#end
MyViewController would then have a delegate property
#interface MyViewController
{
id<MyViewControllerDelegate> delegate;
}
#property(nonatomic,assign) id<MyViewControllerDelegate> delegate;
#end
If you use the protocol method your original view controller will adopt that protocol and will dismiss the modal view itself when it receives this message.
I hope that helps out, it may seem a little complicated at first, but it makes gathering data very easy.
You could use a UIAlertView or similar class yourself. Just pop up the modal view to request the string, establish the right callbacks, then pop it in your dataSource.
You can also insert a cell with a UITextView and a "Tap to Edit" placeholder, then on the textView Callbacks, remove the textView and display the string. Further editing would need to drill down or do something else