Using Scanf with ObjC and iPhone - objective-c

trying to make an iPhone app and going through the tutorials and books recommended by those before me :) I'm trying to find information on the scanf/storing user input data from a text field into a variable which I can use later in my program. The text field is actually a number field, so I am trying to save the integers they input and not the text since there won't be any in my case. Am I on the wrong path here? Any help would be greatly appreciated.

what about if i am essentially trying
to save the input that is a number to
begin with
You want NSNumberFormatter. The data formatters ( Apple Guide) handle conversions to and from strings as well as formatting for output.

I think rather than scanf, you're just looking to get the value from the text field as an NSString pointer.
If you use a UITextField in your interface, you can connect the UITextField to a member variable in your class by declaring the variable as an IBOutlet and connecting it in Interface Builder.
You can then access the text value as an NSString pointer by using [UITextField variable name].text.
There are many useful functions to work with NSStrings or convert the string to other datatypes such as integers.
Hope this helps!

Here's an example of how to get an integer out of a text field.
In your .h file:
#include <UIKit/UIKit.h>
#interface MyViewController : UIViewController {
UITextField *myTextField;
}
#property (nonatomic, retain) IBOutlet UITextField *myTextField;
- (IBAction)buttonPressed1:(id)sender;
#end
In your .m file:
#include "MyViewController.h"
#implementation MyViewController
#synthesize myTextField;
- (IBAction)buttonPressed1:(id)sender {
NSString *textInMyTextField = myTextField.text;
// textInMyTextField now contains the text in myTextField.
NSInteger *numberInMyTextField = [textInMyTextField integerValue];
// numberInMyTextField now contains an NSInteger based on the contents of myTextField
// Do some stuff with numberInMyTextField...
}
- (void)dealloc {
// Because we are retaining myTextField we need to make sure we release it when we're done with it.
[myTextField release];
[super dealloc];
}
#end
In interface builder, connect the myTextField outlet of your view controller to the text field you want to get the value from. Connect the buttonPressed1 action to the button.
Hope this helps!

Related

Xcode OSX, bind NSString to UILabel

I have a Model Class like this:
Header:
#interface RTSecurityModel : NSObject
{
NSString *code;
}
#property NSString *code;
#end
Implementation:
#implementation RTSecurityModel
#synthesize code;
#end
Then I have my App Delegate:
Header:
#interface RTAppDelegate : NSObject <NSApplicationDelegate>
{
RTSecurityModel *security;
}
#property (assign) IBOutlet NSWindow *window;
#property RTSecurityModel *security;
#end
Implementation:
#implementation RTAppDelegate
#synthesize security;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
security = [[RTSecurityModel alloc] init];
security.code = #"test";
}
Then in my MainMenu.xib I've create a label and in the Bindings Inspector set "Bind To: App Delegate" with "Model Key Path: security.code".
But nothing is showing when I'm starting my application.
I tried soooo many ways to bind this variable, but no one gave success.
Please help me not to hate XCode and Cocoa!
UPD: http://www.experts-exchange.com/Programming/Languages/C/A_3381-Simple-Binding-Cocoa-GUI-Application-without-Outlets.html
Here is the sample how to set Property and Label value by editing the Text Field
But is there a way to edit Label without editing the Text Field? Or without Text Field at all?
UPD2:
You must not create another instance of Object
security = [[RTSecurityModel alloc] init]; // Kill this
Many many thanks to Viktor Lexington
Instead of using security.code as the model path use code. Use the class RTSecurityModel in the value section of the bindings tab instead of the AppDelegate.
Here is a demo project.
Do not bind the Text Field Cell, use the Text Field.
You can check if a value is null if you fill the Null Placeholder with text, will it show that text instead? Then in time of binding the value it null.
To see your RTSecurityModel in the Interface Builder you must let it know your class, it won't look for it.
Add an Object and then set the custom class of it to RTSecurityModel.
Then you can choose this object and set the referencing outlet to the property in the App Delegate.
Assignment will now be directly reflected in the label.
I can think of two ways to solve this programmatically without Interface Builder:
Key Value Coding
// add an observer for the value on the object that has the method below implemented
[self addObserver: self forKeyPath: #"security.code" options: NSKeyValueObservingOptionNew context: NULL];
// method will be called when the observer has 'seen' a value change
-(void) observeValueForKeyPath: (NSString *)keyPath ofObject: (id) object change: (NSDictionary *) change context: (void *) context {
label.text = ...
}
Use a custom setter for code (#synthesize will still create the getter for you)
- (void)setCode:(NSString *)aString {
label.text = aString;
}

Objective C calculator program

.h file
#import <UIKit/UIKit.h>
#interface calculatorViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *display;
#end
.m file
#import "calculatorViewController.h"
#interface calculatorViewController ()
#end
#implementation calculatorViewController
#synthesize display=_display;
- (IBAction)digitPressed:(UIButton*)sender
{
NSString *digit=[sender currentTitle];
NSLog(#"digit pressed %#", digit);
UILabel*myDisplay=self.display;
//[self display] why not just type
NSString *currentText= myDisplay.text;//[myDisplay text]; why are we not writing current title again?
nsstring*newText=[currentText stringByAppendingString:digit];
[myDisplay setText:newText];
Hi guys!
I have been trying to learn Objective-C so these questions might be stupid for you but tough for me, so please do not down vote my question as I am only trying to learn like you. :)
I have a couple of questions in .m file.
(IBAction)digitPressed:(UIButton*)sender Does (UIButton *) mean that it is a type and that sender is a pointer simultaneously? Cant we remove the bracket?
NSLog(#"digit pressed %#", digit);Why does this not work with *digit. Doesn't digit only store the address and not the actual value?
UILabel*myDisplay=self.display; I know self.display is a getter but what exactly is selfWhen do we use it?
NSString *currentText= myDisplay.text Why are we writing .text and not currentTitle like in NSString *digit=[sender currentTitle];
Lastly I read a lot but could not understand. In one sentence what is the difference between NSString and UILabel?
(UIButton*)sender means that the sender is passed in the parameter of the method, and that sender is casted to a UIBUtton object.
Because *digit is a pointer to an object, so that will print the memory address of the object
You use it if you want to access the variable trough the getter, and not directly the instance variable.
Is the same, is just a convention, use . to access properties and space to access methods.
NSString represents a string object like "ABC", UILabel is a view that will be displayed in your screen, and which text is a NSString.
I won't go into more details, as SO is not a tutorial page. You'll find all this answers in the first chapter of any CocoaTouch programming book.
(UIButton *) is a typecast to a UIButton object. If you are sure that the sender is a UIButton you can add the typecast. In that way you can directly access the properties/methos on the UIButton object
2.
As far as I understand digit refers to the string object. And *digit means the first (located at index 0).
3.
self means the class it self i.e. calculatorViewController
4.
text is a property of UILabel component
5.
You cannot display a NSString on the display itself you need a UILabel component. You can set the text property to a NSString object and display it on the screen
regards
Johan

NSTableView edits not changing NSMutableArray

I have a Class that stores some strings along with a BOOL flag that is set to YES if one of the strings has been updated.
I have a NSTableView that displays the strings in my class. The view is controlled via separate controller class and the view is fed by an NSMutableArray.
The GUI stuff seems to work fine in terms of displaying data and allowing me to edit the cells in the table view. The problem I am having is the edits don't change the objects stored in the NSMutableArray. I have some debug code to print out the strings when I close the app, and none of the changes made in the GUI show up in the objects at this point. Setting a break point where those values are changed shows me the objects are indeed changed, but those changes seem to get lost. How can I get any changes I make in the view to persist in the object stored in the NSMutableArray backing the NSTableView?
Here is how I am coding:
// my class .h file
#interface Snip : NSObject <NSMutableCopying>
#property (assign) int64_t id_num;
#property (assign) BOOL changed;
#property NSMutableString *name;
#property NSMutableString *text;
#property (copy) NSString *language;
// my class .m file
import "Snip.h"
#implementation Snip
#synthesize id_num;
#synthesize name;
#synthesize text;
#synthesize changed;
#synthesize language;
method from my controller class
// edit table values
-(void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn(NSTableColumn *)tableColumn row:(NSInteger)row
{
Snip *sn = [snippet_list objectAtIndex:row];
[sn setChanged:YES];
[sn setValue:object forKey:[tableColumn identifier]];
NSLog(#"Change: %#",sn.name);
}
That last NSLog statement displays the change I made in the GUI. Also, the setChanged:YES is lost as well when I print the NSMutableArray contents when closing the app.
This behaviour is often due to the data being initialised again at some point after being changed by the user.
You can catch this problem by setting a breakpoint (or NSLog statement) in your initialisation code.

Access class variable from another class

I have a UITabBarController that manages two ViewControllers. The first is a UIViewController that allows the user to change game settings. The second is a GLKViewController that runs the game simulation.
I'm trying to enable the Game ViewController to fetch the settings from the Settings ViewController. I have a Slider on the Settings View that represents "Speed".
I have a reference to the other controller, but I'm unable to expose the variable that backs my Slider properly.
SecondViewController.h
#interface SecondViewController : UIViewController{
IBOutlet UISlider * mySlider;
}
property (nonatomic,retain) IBOutlet UISlider * mySlider;
#end
SecondViewController.m
- (IBAction) mySliderWasMoved:(id)sender;
#implementation SecondViewController
#synthesize mySlider;
- (IBAction) mySliderWasMoved:(id)sender{
};
ThirdViewController.m
NSArray *tmpVCs = self.parentViewController.tabBarController.viewControllers;
UIViewController *tmpVC = [tmpVCs objectAtIndex:1]; //obtain handle to SecondViewController
//NSNumber *mySpeed = tmpVC.mySlider; //doesn't see mySlider
NSNumber *mySpeed = [tmpVC mySlider]; //doesn't see mySlider
I'm new to this, and there are many aspects of my project to learn - so I'm not trying to learn how to manage data at this time. I just need to know how to access an instance variable
As mention on the comments,
Use NSDefault to save the value on slider changed. On the very first time of loading your application, you will want to set a default value.
Use Singleton Object to store value.
We understand that, quoting from you " not trying to learn data persistence at this time. Nor do I need architecture direction.", but the rule of thumb here is that you probably will be able to access the instance variable in some way or the other but i think having the best approach will benefit you greatly.
Just my 2 cent.
Fort the benefit of others: I grabbed a handle to the other class, but I hadn't declared the return type as the correct type of class.
Replace:
UIViewController *tmpVC = [tmpVCs objectAtIndex:1];
With:
SecondViewController *tmpVC = [tmpVCs objectAtIndex:1];
Now I have access to the properties that are specific to the SecondViewController.

UITableView and delegates

I have an iPad app in progess but I'm having difficulty catching the selection of a row in my table view. I know this is because I haven't defined my delegate properly yet but, after 2 hours on the net, it still isn't making much sense.
What I'm trying to do is pass the selected table row item to a new view that displays info based on the selection - pretty standard.
I set up the tableViewController sub class using the option to create it as a UITableViewController subclass which, unless I am wrong, incorporates the delegates (UITableViewDelegate and UITableViewDataSource) automatically.
In the didSelectRowsAtIndex method I'm trying to create a DetailViewController. I've tried with a nib file and creating one purely in code but the class is never created. I'm missing a step I'm sure of it but I can't find what it is. At some point shouldn't I be defining what function I want to access with the selected row? But where? How?
In what I considered was my best attempt, I created the DetailViewController, set a string variable in the detailViewController to the selected row, and then tried to add the detailViewController view to display. I figured I could then use the viewDidload to call the next function but the view never got displayed on screen.
Some basic guidence would be nice. Or a decent tutorial would be nice. No calls to read the relevant docs please, I've been over it and right now I need a example to pull things together.
Thanks,
Steve
I think you are missing this line in your didSelectRowAtIndexPath: method
[self presentModalViewController:controller animated:YES];
where controller is an object of class DetailViewController
Yeah, maybe paste the code snippet will be easier to figure out what's going on here. And are those delegate(didSelectRowAtIndexPath:) methods being called correctly?
Try this,
this goes in didSelectRowAtIndexPath
MoreInfoTable *moreInfoView = [[MoreInfoTable alloc] initWithStyle:UITableViewStyleGrouped];
//in the MoreInfoTable, make properties like titles etc.
[self.navigationController pushViewController:moreInfoView animated:YES];
[moreInfoView release];
}
here's an example of an MoreInfoTable.h
#interface MoreInfoTable : UITableViewController {
NSMutableArray *moreInfo;
NSURL *getDirections;
NSURL *getWebsite;
NSMutableString *getPhoneNumber;
NSString *address;
NSString *footer;
float lat, lon;
}
-(void)goToWebsite;
-(void)goToMaps;
-(IBAction)addToFavorites:(id)sender;
-(void) callNumber;
#property (nonatomic,retain) NSURL *getDirections;
#property (nonatomic,retain) NSURL *getWebsite;
#property (nonatomic,retain) NSMutableString *getPhoneNumber;
#property (nonatomic,retain) NSString *footer;
#property (nonatomic,retain) NSString *address;
#property (readwrite) float lat;
#property (readwrite) float lon;
#end
now back in the other file in which you declare the table, you can say
MoreInfoTable *moreInfoView = [[MoreInfoTable alloc] initWithStyle:UITableViewStyleGrouped];
//in the MoreInfoTable, make properties like titles etc.
moreInfoView.title = #"TITLE!";
//etc.
[self.navigationController pushViewController:moreInfoView animated:YES];
[moreInfoView release]; //