Objective C calculator program - objective-c

.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

Related

Assign to UIImageView a string tag

Is it possible to assign a text tag to any UIObject? If not is there another way I can do it? Can I do for example:
image.tag = [NSString stringWithFormat: #"Hello"];
Thanks for any help!
The tag property is an NSInteger - therefore this is not possible.
You can create a subclass and add an NSString property.
No, the tag is an integer.
Consider subclassing UIImageView class and just adding a NSString property. It is really simple these days.
Example:
#interface TaggedImageView : UIImageView
#property (nonatomic, strong) NSString *tagString;
#end
#implementation TaggedImageView
#end
Then just use TaggedImageView in place of UIImageView.
If you only access the MyImageView from one .m file you can just put these lines just after the #import statements.

Objective C Adding custom objects into NSMutableArray

I want to store a list of data records in a NSMutableArray for use in a UITableView. In other languages I would have used a simple 'type' structure to define the record structure but I understand the way to do this in Obj-C is to define a new class. I've done this as follows :
#interface CustSuppListItem : NSObject
#property (nonatomic, copy, readwrite) NSString *acCode;
#property (nonatomic, copy, readwrite) NSString *acCompany;
#property (nonatomic, copy, readwrite) NSString *acContact;
#property (nonatomic, assign, readwrite) double osBalBase;
#property (nonatomic, assign, readwrite) unsigned int acAccStatus;
#end
#implementation CustSuppListItem
#synthesize acCode, acCompany, acContact, osBalBase, acAccStatus;
#end
In the viewDidLoad of my UITableViewController I instantiate the array :
tableListDataArray = [[NSMutableArray alloc] init];
Once I have retrieved my data, I add it to the array as follows :
CustSuppListItem *custSuppItem = [[CustSuppListItem alloc] init];
[custSuppItem setAcCode:[jsonCustSuppRecord getStringForKey:#"acCode"]];
[custSuppItem setAcCompany:[jsonCustSuppRecord getStringForKey:#"acCompany"]];
[custSuppItem setAcContact:[jsonCustSuppRecord getStringForKey:#"acContact"]];
[custSuppItem setOsBalBase:[jsonCustSuppRecord getDoubleForKey:#"osBalBase"]];
[custSuppItem setAcAccStatus:[jsonCustSuppRecord getIntForKey:#"acAccStatus"]];
[tableListDataArray addObject:custSuppItem];
[custSuppItem release];
In my table cellForRowAtIndexPath method, I retrieve the data for the current cell as follows:
CustSuppListItem *listDataRecord = [tableListDataArray objectAtIndex:indexPath.row];
[cell.lblCompanyName setText:listDataRecord.acCompany]; // EXC_BAD_ACCESS here
[cell.lblAcCodeContact setText:[NSString stringWithFormat:#"%#, %#",
listDataRecord.acCode, listDataRecord.acContact]];
[cell.lblBalance setText:[Utils fmtNumber:listDataRecord.osBalBase withDecPlaces:2]];
[cell.lblStatus setText:[Utils exchAccStatusDesc:listDataRecord.acAccStatus]];
return cell;
In the dealloc method for the view controller I release the NSMutableArray :
[tableListDataArray release];
I'm very new to Obj-C so it would be great if somebody could confirm everything I've done so far makes sense and is in order. I am getting an intermittent EXC_BAD_ACCESS error when trying to read the acCompany property (see comment next to line) so something must not be right.
Any help appreciated,
Jonathan
All your code looks reasonable and correct to me at first glance.
A few things that I would look at are:
Confirm that cell definitely has a property lblCompanyName. If you're trying to assign to a property that doesn't exist then you will get this type of error. Have you defined a custom cell object type?
Confirm that it is always the acCompany property that is causing the EXC_BAD_ACCESS, and not just any property on the object. One way to do this would be to change the ordering of the lines in the cellForRowAtIndexPath method.
Confirm that the listDataRecord that's causing the crash is getting populated correctly in the first place. In other words, confirm that your jsonCustSuppRecord is always valid. What does jsonCustSuppRecord getStringForKey: return if the key doesn't exist in the jsonCustSuppRecord?
Set a breakpoint at this line: [tableListDataArray addObject:custSuppItem]; and examine the contents of the custSuppItem each time (this is an extension of point 3. above)

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]; //

Objective-C NSArray

I'm new to Obj-C and iPhone SDK. The test application I'm stock with is a color switcher containing two buttons ("Back", "Forward") and one text label. The idea is to switch between rainbow colors (background) and setting an appropriate text label in a cyclic manner.
I declared NSArray (which is to contain colors names) in RainbowViewController.h, synthesized it in RainbowViewController.h and I can't add any string into that array.
This is "h" file:
#import <UIKit/UIKit.h>
#interface RainbowViewController : UIViewController {
IBOutlet UILabel *currentColorTextLabel;
NSArray *colorsArray;
NSString *msg;
}
#property (nonatomic, retain) IBOutlet UILabel *currentColorTextLabel;
#property (nonatomic, retain) NSArray *colorsArray;
#property (nonatomic, retain) NSString *msg;
- (IBAction) pressForwardButton;
- (IBAction) pressBackButton;
#end
This is "m" file:
#import "RainbowViewController.h"
#import <Foundation/Foundation.h>
#implementation RainbowViewController
#synthesize currentColorTextLabel;
#synthesize colorsArray;
#synthesize msg;
int currentArrayIndex = 0;
colorsArray = [[NSArray alloc] init]; //here i get "Initializer element is not constant" error message
[coloursArray addObject:#"Red"]; //here I get "Expected identifier or '(' before '[' token"
[coloursArray addObject:#"Orange"];
//etc
- (IBAction) pressForwardButton {
//here I'm going to increment currentArrayIndex, set an appropriate color, and update a currentColorTextLabel based on currentArrayIndex.
}
- (IBAction) pressBackButton {
}
//auto-genereted code here
#end
I'm new to obj-c as well, but I think you need to initialize the array with objects, or use an NSMutableArray if you want to add objects after it is created.
You have the code that should go in your init method just sitting out in the middle of the file. You can't set instance variables like that.
jasongetsdown is correct. You need to instantiate the NSArray object with the objects it will contain and nil terminated.
#"Red", #"Blue", nil
If you wish to have an array that you can change you need to make it a Mutable Array.
However, you have another problem here. Your property that you are synthesizing and allocating for is an object named colorsArray and you are trying to pass a method to a coloursArray object, two different spellings.

Using Scanf with ObjC and iPhone

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!