I'm doing a calculator app base on a online tutorial, itunes.apple. com/itunes-u/ipad-iphone-application- development/ id473757255 (tut 2)
I followed every step closely and all was fine, until the finishing step of a method call performOperation. When I build and run, the numbers and enter function work fine. Only the operation method is not working. So I presume that the main trouble is with the operation method.
BrainCalculator.h
#interface CalculatorBrain : NSObject
-(void) pushOperand: (double)operand;
-(double) performOperation: (NSString*) operation;
#end
BrainCalculator.m
#import "CalculatorBrain.h"
#interface CalculatorBrain()
#property (nonatomic, strong) NSMutableArray* _operandStack;
#end
#implementation CalculatorBrain
#synthesize _operandStack;
-(NSMutableArray *)operandStack
{
if (!_operandStack){
_operandStack= [[NSMutableArray alloc ]init];
}
return _operandStack;
}
-(void)pushOperand:(double)operand{
NSNumber *operandObject = [NSNumber numberWithDouble:operand];
[self.operandStack addObject:operandObject];
}
-(double)popOperand{
NSNumber *operandObject= [self.operandStack lastObject];
if (operandObject) [self.operandStack removeLastObject];
return [operandObject doubleValue];
}
-(double)performOperation:(NSString *)operation
{
double result = 0;
if ([operation isEqualToString:#"+"]){
result=[self popOperand] + [self popOperand];
}else if ([#"*" isEqualToString:operation]){
result = [self popOperand] * [self popOperand];
}else if ([operation isEqualToString:#"-"]){
double subtrahend = [self popOperand];
result = [self popOperand] - subtrahend;
}else if( [operation isEqualToString:#"/"]){
double divisor = [self popOperand];
if (divisor) result = [self popOperand] / divisor;
}
[self pushOperand:result];
return result;
}
#end
Initially, it seem to me that the performOperation method was pretty fishy, so I tried fiddling the
}else if ([#"*" isEqualToString:operation]){
to
}else if ([operation isEqualToString:#"*"]){
hoping it would work, but sadly it didn't.
Just for additional information
viewcontroller.m
#import "CalculatorViewController.h"
#import "CalculatorBrain.h"
#interface CalculatorViewController ()
#property (nonatomic) BOOL userIsInTheMiddleOfEnteringANumber;
#property (nonatomic, strong) CalculatorBrain *brain;
#end
#implementation CalculatorViewController
#synthesize display;
#synthesize userIsInTheMiddleOfEnteringANumber;
#synthesize brain= _brain;
-(CalculatorBrain*)brain
{
if(!_brain)_brain = [[CalculatorBrain alloc]init];
return _brain;
}
- (IBAction)digitPressed:(UIButton *)sender {
NSString * digit= [ sender currentTitle];
if (userIsInTheMiddleOfEnteringANumber){
self.display.text = [self.display.text stringByAppendingString:digit];
}
else{
self.display.text=digit;
self.userIsInTheMiddleOfEnteringANumber = YES;
}
}
- (IBAction)enterPressed {
[self.brain pushOperand:[self.display.text doubleValue]];
self.userIsInTheMiddleOfEnteringANumber = NO;
}
- (IBAction)operationPressed:(UIButton *)sender {
if (self.userIsInTheMiddleOfEnteringANumber){
[self enterPressed];
}
NSString *operation = [sender currentTitle];
double result = [self.brain performOperation:operation];
self.display.text = [NSString stringWithFormat:#"%g", result];
}
#end
help will be greatly appreciated as I'm practising xcode to prepare myself for my final year major project.
Related
I was wondering how to set the progress bar equal to max user input in xcode.
#property (weak, nonatomic) IBOutlet UIProgressView *progressBar;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_inputAmount.keyboardType = UIKeyboardTypeDecimalPad;
self.amount = [NSMutableArray new];
[self.amount addObject:#"Total Amount of Push-Ups:"];
[self.myList setDataSource:self];
_inputAmount = UIProgressViewStyleBar;
}
This is just a snipet of my code, the inputamount = progress bar is what I want to do, but I'm not really sure how to do it. I want the greatest input amount the be equal to the progressviewbar as well. So i would have to compare all the #s that were added to the array. Any ideas? Thanks!
//
// ViewController.m
// Push Up Tracker
//
// Created by Paul Lesny on 10/26/14.
// Copyright (c) 2014 Paul Lesny. All rights reserved.
//
#import "ViewController.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UITextField *inputAmount;
#property (weak, nonatomic) IBOutlet UIButton *addButton;
#property NSMutableArray *amount;
#property (weak, nonatomic) IBOutlet UITableView *myList;
#property (weak, nonatomic) IBOutlet UIProgressView *progressBar;
#end
#implementation ViewController
//#synthesize progressBar, progressValue;
///NSInteger stringToInt(NSString *string) {
//return [string integerValue];
//}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_inputAmount.keyboardType = UIKeyboardTypeDecimalPad;
self.amount = [NSMutableArray new];
[self.myList setDataSource:self];
[self readDataFromFile:#"lalala1"];
if (_amount.count!=0)
{
NSMutableDictionary *max=[_amount objectAtIndex:0];
NSString *m = max[#"max"];
NSLog (#"%#",m);
NSInteger num=[m intValue];
NSLog(#"amount is not empty");
_progressBar.progress = (float) [m intValue]/50;
}
else
{
_progressBar.progress=0;
}
//[self.amount addObject:#"0"];
//[self.myList reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return[self.amount count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString * cellId = #"pancake";//identifier for the cells
// get a cell from the cache
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellId];
// if the cell is not cached then
if(cell ==nil)
{
// create a new cell
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}
NSMutableDictionary *newEntry=_amount[indexPath.row];
[cell.textLabel setText:newEntry[#"pushUpNum"]];
// put the corresponding element of the array as text.
// return the cell.
return cell;
}
-(BOOL) textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
-(void) readDataFromFile:(NSString*)fileName
{
NSData *fileData=[NSData dataWithContentsOfURL:[self urlOfEntries:#"lalala1"]];
if(fileData!=nil)
{
_amount=[NSPropertyListSerialization
propertyListWithData:fileData options:
NSPropertyListMutableContainers format:nil error:nil];
}
else
{
_amount=[NSMutableArray new];
}
}
-(NSURL *) urlOfEntries:(NSString*)name
{
NSURL *docDirectory=[[[NSFileManager defaultManager]
URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]lastObject];
NSURL* fullPath=[docDirectory URLByAppendingPathComponent:name];
return fullPath;
}
-(void) savePushUpTotal:(NSMutableArray *)myEntries
{
[myEntries writeToURL:[self urlOfEntries:#"lalala1"]atomically:YES];
}
- (IBAction)sender:(id)addButton
{
NSMutableDictionary *newRecord = [[NSMutableDictionary alloc]init];
[newRecord setObject:self.inputAmount.text forKey:#"pushUpNum"];
if (_amount.count==0)
{
[newRecord setObject:#"0" forKey:#"max"];
}
[self.amount addObject:newRecord];
[self savePushUpTotal:_amount];
[self.myList reloadData];
[self.inputAmount resignFirstResponder];
[self savePushUpTotal:_amount];
NSMutableDictionary *max=_amount[0];
NSString *m = max[#"max"];
NSInteger num=[m intValue];
NSMutableDictionary *newDictionary=_amount[_amount.count-1];
NSString *blah = newDictionary[#"pushUpNum"];
NSInteger number=[blah intValue];
NSLog(#"dadala%#",blah);
if (_amount.count!=1)
{
if (number>num)
{
_progressBar.progress= (float)number/50;
NSString *pushUp = max[#"pushUpNum"];
NSMutableDictionary *maxPush = [[NSMutableDictionary alloc]init];
[maxPush setObject:pushUp forKey:#"pushUpNum"];
[maxPush setObject:blah forKey:#"max"];
[_amount removeObjectAtIndex:(NSUInteger)0];
[_amount insertObject:maxPush atIndex:0];
[self savePushUpTotal:_amount];
}
}
else
{
_progressBar.progress = (float)number/50;
}
}
- (IBAction)clear:(UIButton *)sender
{
_progressBar.progress=0;
[_amount removeAllObjects];
[[NSUserDefaults standardUserDefaults] setObject:_amount forKey:0];
[_myList reloadData];
}
#end
I am new to IOS programming and was going thru what should be an easy to utilize and understand tutorial at the following address `http://www.youtube.com/watch?v=twQ6UjhF1Ms'
I am getting warning (**) at this section of the viewcontroller.m file
NSString *meat = Meats[MeatRow]; **unused variable"meat"
NSString *cheese = Cheeses [CheeseRow]; **unused variable"cheese"
NSString *bread = Breads [BreadRow]; **unused variable"bread"
NSString *msg = [[NSString alloc]initWithFormat:#"You ordered a %# and %# on %# Bread"]; ** More "%" conversions than data arguments
Here is the viewcontroller.h code
//
// ViewController.h
// PickerViewPart2
//
// Created by on 12/23/13.
// Copyright (c) 2013 . All rights reserved.
//
#import <UIKit/UIKit.h>
#define kMeatComponent 0
#define kCheeseComponent 1
#define kBreadComponent 2
#interface ViewController : UIViewController <UIPickerViewDataSource,UIPickerViewDelegate>
#property (nonatomic, strong)NSArray *Meats;
#property (nonatomic, strong)NSArray *Cheeses;
#property (nonatomic, strong)NSArray *Breads;
- (IBAction)makeSandich:(UIButton *)sender;
#property (weak, nonatomic) IBOutlet UILabel *sandwichLabel;
#property (weak, nonatomic) IBOutlet UIPickerView *picker;
#end
and the Viewcontroller.m code if it helps any one. I am lost or else been looking at it way to long to find what the issue is:
//
// ViewController.m
// PickerViewPart2
//
// Created by on 12/23/13.
// Copyright (c) 2013 . All rights reserved.
//
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize Meats, Cheeses, Breads, picker;
- (void)viewDidLoad
{
[super viewDidLoad];
Meats = #[#"Bologna", #"Turkey", #"Ham", #"Chicken", #"Tuna", #"RoastBeef"];
Cheeses = #[#"Swiss", #"Cheddar", #"Feta", #"American", #"Pepper Jack"];
Breads = #[#"Wheat", #"White", #"Rye", #"Sour Dough", #"Pumpernickel"];
Meats = [Meats sortedArrayUsingSelector:#selector(compare:)];
Cheeses = [Cheeses sortedArrayUsingSelector:#selector(compare:)];
Breads = [Breads sortedArrayUsingSelector:#selector(compare:)];
}
-(void) didReceiveMemoryWarning{
[super didReceiveMemoryWarning];
}
- (IBAction)makeSandwich:(UIButton *)sender {
NSInteger MeatRow = [picker selectedRowInComponent:kMeatComponent];
NSInteger CheeseRow = [picker selectedRowInComponent:kCheeseComponent];
NSInteger BreadRow =[picker selectedRowInComponent:kBreadComponent];
NSString *meat = Meats[MeatRow];
NSString *cheese = Cheeses [CheeseRow];
NSString *bread = Breads [BreadRow];
NSString *msg = [[NSString alloc]initWithFormat:#"You ordered a %# and %# on %# Bread"];
_sandwichLabel.text=msg;
}
#pragma mark - UIPickerCView Datasource & Delegate Methods
// returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 3;
}
// returns the # of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
if (component == kMeatComponent)
return [Meats count];
else if (component == kCheeseComponent)
return [Cheeses count];
else
return [Breads count];
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
if (component == kMeatComponent)
return Meats[row];
else if (component == kCheeseComponent)
return Cheeses[row];
else return Breads[row];
}
- (IBAction)makeSandich:(UIButton *)sender {
}
#end
You are not using any of the varriable "meat,cheese,bread" try this updated code this will surely clear the warning from your code.
NSString *meat = Meats[MeatRow]; **unused variable"meat"
NSString *cheese = Cheeses [CheeseRow]; **unused variable"cheese"
NSString *bread = Breads [BreadRow]; **unused variable"bread"
NSString *msg = [[NSString alloc]initWithFormat:#"You ordered a %# and %# on %# Bread",meat,cheese,bread]; ** More "%" conversions than data arguments
I have a form-like view in my application which contains 8 textfields. Two of them are to be filled in by pickers, and the rest by normal heyboard typing. When picker-row is selected or when return button is pressed, the corresponding text should be entered into the textfield.
Could you please give some advice how to implement this properly? Also so that pickers/keyboards are dismissed after selection made/return pressed.
I found an answer to something similar here. ANd I managed to get the 2 picker-textfields working, but now I cannot make the keyboard appear for the rest. I guess it's because I'm overriding the textFieldShouldBegineEditing method. Any ideas to get round that? Can I somehow call the default method from inside textFieldShouldBeginEditing?? Note, if I uncomment my last lines of textFieldShouldBeginEditing I get a crash...
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
currentTextField = textField;
if (textField == self.pickerField1) {
currentArray = self.array1;
[pickerView reloadAllComponents];
pickerView.hidden = NO;
[self animatePickerViewIn];
return NO;
}
if (textField == self.pickerField2){
currentArray = self.array2;
[pickerView reloadAllComponents];
pickerView.hidden = NO;
[self animatePickerViewIn];
return NO;
}
// else {
// [currentTextField becomeFirstResponder];
// return NO;
// }
- (void)pickerView:(UIPickerView *)pickerView
didSelectRow:(NSInteger)row inComponent: (NSInteger)component
{
[currentTextField setText:[currentArray objectAtIndex:row]];
[currentTextField resignFirstResponder];
pickerView.hidden = YES;
}
Thanks!
Adding this for anyone that needs more information - here's how I got it work using user2135738's provided code:
MyViewController.h
#import <UIKit/UIKit.h>
#interface MyViewController : UIViewController <UITextFieldDelegate, UIPickerViewDataSource, UIPickerViewDelegate>
#property (weak, nonatomic) IBOutlet UITextField *aTextField;
#property (weak, nonatomic) IBOutlet UITextField *bTextField;
#end
MyViewController.m
#import "MyViewController.h"
#interface MyViewController ()
#end
#implementation MyViewController {
NSArray *aArray,
*bArray,
*currentArray;
UITextField *currentTextField;
UIPickerView *pickerView;
}
- (void)viewDidLoad {
aArray = [NSArray arrayWithObjects: #1, #2, #3, #4, #5, #6, #7, #8, #9, #10, #11, #12, #13, #14, #15, #16, #17, #18, #19, #20, nil];
bArray = [NSArray arrayWithObjects:#"aString", #"bString", nil];
[super viewDidLoad];
pickerView = [[UIPickerView alloc] init];
pickerView.dataSource = self;
pickerView.delegate = self;
self.aTextField.delegate = self;
self.bTextField.delegate = self;
self.aTextField.inputView = pickerView;
self.bTextField.inputView = pickerView;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
currentTextField = textField;
if (textField == self.aTextField) {
currentArray = aArray;
[pickerView reloadAllComponents];
pickerView.hidden = NO;
return YES;
} else if (textField == self.bTextField){
currentArray = bArray;
[pickerView reloadAllComponents];
pickerView.hidden = NO;
return YES;
} else {
[currentTextField becomeFirstResponder];
return NO;
}
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return [currentArray count];
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
return [NSString stringWithFormat:#"%#",[currentArray objectAtIndex:row]];
}
#end
App stops working after adding messageUI.framework
I have a fully working App created and I want to add some new features. I added the messageUI.framework and it stoped working. If I delete the Framework it works again, but this is not the idea.
The error I received is:
-[Account initWithCoder:]: unrecognized selector sent to instance 0x1cd953a0
I have a custom NSObject called Account and I get the error when loading it:
myAccounts = [[NSMutableArray alloc] init];
myAccounts = [NSKeyedUnarchiver unarchiveObjectWithFile:savePath]; //Crashes in this line
When it was previously saved with:
[NSKeyedArchiver archiveRootObject:myAccounts toFile:savePath];
Can it be caused by some overlapping variables or something like that?
Notes:
Account.h is like:
#define kAccName #"name"
#define kAccID #"identifier"
#define kAccInitAmount #"initAmount"
#define kAccActive #"active"
#import <Foundation/Foundation.h>
#import "Transfer.h"
#interface Account : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *identifier;
#property (nonatomic) double initAmount;
#property (nonatomic) BOOL active;
- (id)initWithID:(NSString *)ident;
#end
And Account.m is:
#import "Account.h"
#implementation Account
#synthesize name;
#synthesize identifier;
#synthesize initAmount;
#synthesize active;
- (id)init {
self = [super init];
if (self) {
self.active = TRUE;
}
return self;
}
- (id)initWithID:(NSString *)ident {
self = [super init];
if (self) {
self.active = TRUE;
self.identifier = ident;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
if (self = [super init]) {
self.name = [decoder decodeObjectForKey:kAccName];
self.identifier = [decoder decodeObjectForKey:kAccID];
self.initAmount = [decoder decodeDoubleForKey:kAccInitAmount];
self.active = [decoder decodeBoolForKey:kAccActive];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:self.name forKey:kAccName];
[encoder encodeObject:self.identifier forKey:kAccID];
[encoder encodeDouble:self.initAmount forKey:kAccInitAmount];
[encoder encodeBool:self.active forKey:kAccActive];
}
#end
I just hit this problem, I cannot tell you exactly why, but refactor your Account object to any other name, I used Accounts, and it works. Something at runtime in the MessageUI.framework is colliding with your Account object name.
What does this Expected expression error mean on this line of code:
[super setNilValueForKey:key];
Code:
#import "Person.h"
#implementation Person
- (id) init
{
self = [super init];
expectedRaise = 5.0;
personName = #"New Person";
return self;
}
- (void)dealloc
{
[personName release];
[super dealloc];
}
- (void)setNilValueForKey:(NSString *)key
{
if ([key isEqual:#"expectedRaise"])
{
[self setExpectedRaise:0.0];
}
else
{
[super setNilValueForKey:key];
}
}
#synthesize personName;
#synthesize expectedRaise;
#end
.h:
#import <Foundation/Foundation.h>
#interface Person : NSObject
{
NSString *personName;
float expectedRaise;
}
#property (readwrite, copy) NSString *personName;
#property (readwrite) float expectedRaise;
#end
If you really got
[super setNilValueForKey:<#key#>];
in your code, the solution should be as simple as
[super setNilValueForKey:key];
isEqual is the wrong method since I wanted to compare to a string value isEqualToString is correct.
- (void)setNilValueForKey:(NSString *)key
{
if ([key isEqualToString:#"expectedRaise"])
{
[self setExpectedRaise:0.0];
}
else
{
[super setNilValueForKey:key];
}
}