iPhone: -[NSConcreteMutableData fastestEncoding]: unrecognized selector - iphone

I am trying to do this:
self.somestring = [#"hardcodedstring" stringByAppendingString:someotherstring];
But I keep getting:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSConcreteMutableData fastestEncoding]: unrecognized selector sent to instance 0x1fb930'
I don't call this method anywhere but I see that stringByAppendingString: calls it in my stack:
Stack: (
808221155,
806100816,
808224837,
807957033,
807851552,
812064725,
812064413,
18085, <== -[NSString stringByAppendingString:] + 109 in section LC_SEGMENT.__TEXT.__text of /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.1.sdk/System/Library/Frameworks/Foundation.framework/Foundation
817945012,
821160740,
821157652,
821149552,
807852041,
812070519,
807836299,
807834407,
827752032,
816118388,
816157144,
8381,
8244
)
How would I fix this so that it appends the string, just like it is supposed to. Thanks,
Isaac
Edit: To access somestring, I do this:
#property (nonatomic,retain) NSString *somestring;
In my ViewController.h and:
#synthesize somestring;
In my ViewController.m.
Edit: someotherstring comes from here:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
self.somestring = [#"hardcodedstring" stringByAppendingString:[UIImagePNGRepresentation(img) encodeBase64]]; //encodeBase64 encodes it to base64
}
More Edit: I broke it up:
2009-03-20 15:14:21.389 myproject[3467:20b] *** -[NSConcreteMutableData getCharacters:range:]: unrecognized selector sent to instance 0x1fa630
2009-03-20 15:14:21.403 myproject[3467:20b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSConcreteMutableData getCharacters:range:]: unrecognized selector sent to instance 0x1fa630'
2009-03-20 15:14:21.412 myproject[3467:20b] Stack: (
808221155,
806100816,
808224837,
807957033,
807851552,
807660389,
807733601,
807733297,
807891629,
812155873,
812293801,
18081,
817945012,
821160740,
821157652,
821149552,
807852041,
812070519,
807836299,
807834407,
827752032,
816118388,
816157144,
8381,
8244
)
terminate called after throwing an instance of 'NSException'
(gdb) info symbol 18081
-[InternalChoicesController imagePickerController:didFinishPickingImage:editingInfo:] + 73 in section LC_SEGMENT.__TEXT.__text of /Users/isaacwaller/Documents/myproject/build/Debug-iphoneos/myproject.app/myproject
(gdb) info symbol 812293801
NSLog + 25 in section LC_SEGMENT.__TEXT.__text of /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.1.sdk/System/Library/Frameworks/Foundation.framework/Foundation
So I think it is a problem with encoding the Base64 data? The code I am using is:
static const char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#implementation NSData (Base64)
- (NSString *)encodeBase64;
{
if ([self length] == 0)
return #"";
char *characters = malloc((([self length] + 2) / 3) * 4);
if (characters == NULL)
return nil;
NSUInteger length = 0;
NSUInteger i = 0;
while (i < [self length])
{
char buffer[3] = {0,0,0};
short bufferLength = 0;
while (bufferLength < 3 && i < [self length])
buffer[bufferLength++] = ((char *)[self bytes])[i++];
// Encode the bytes in the buffer to four characters, including padding "=" characters if necessary.
characters[length++] = encodingTable[(buffer[0] & 0xFC) >> 2];
characters[length++] = encodingTable[((buffer[0] & 0x03) << 4) | ((buffer[1] & 0xF0) >> 4)];
if (bufferLength > 1)
characters[length++] = encodingTable[((buffer[1] & 0x0F) << 2) | ((buffer[2] & 0xC0) >> 6)];
else characters[length++] = '=';
if (bufferLength > 2)
characters[length++] = encodingTable[buffer[2] & 0x3F];
else characters[length++] = '=';
}
return [[[NSString alloc] initWithBytesNoCopy:characters length:length encoding:NSASCIIStringEncoding freeWhenDone:YES] autorelease];
}
#end
Thanks, Isaac Waller

I would check the code for typos. The error pretty clearly indicates that an instance of NSMutableData is being used where an NSString is expected. It would seem that either encodeBase64 is somehow returning self or else the raw UIImagePNGRepresentation(img) is getting passed to stringByAppendingString:.
If it's not apparent, just break it down and check at each step. (I'm using NSLog for this example, but stepping with a debugger would work fine too, of course.)
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
NSData *rep = UIImagePNGRepresentation(img);
NSLog(#"Rep: %#", rep);
NSString *base64 = [rep encodeBase64];
NSLog(#"Base 64 is a %#", NSStringFromClass([base64 class]));
self.somestring = [#"hardcodedstring" stringByAppendingString:base64]; //encodeBase64 encodes it to base64
}
My best guess is that you're accidentally passing in the raw NSData instead of an NSString — but failing that, the above code should either work correctly or show exactly where things are breaking down.

#"Some String" isn't an object, it's a string literal. You can't send messages to it. You are going to need to do something else to join those strings.
Something like:
[NSString stringWithFormat:#"%#%#", #"String 1", #"String 2"];
Apparently, this isn't correct. String literals are treated as objects.
As mentioned in the comments, you may also have a problem with self.somestring as well. If you haven't declared a property or synthesized somestring then accessing it through self. is incorrect. You should just use
somestring = [NSString stringWithFormat:#"%#%#", #"String 1", #"String 2"];
If you've done:
#interface myClass {
NSString *somestring;
}
#property(nonatomic, retain) NSString *somestring;
#end
And:
#implementation myClass
#synthesize somestring;
#end
Then you can access the variable using self.somestring, which is really just syntactic sugar for [self somestring].
It is important to note also that #property and #synthesize are actually syntactic sugar bits themselves. They wind up doing something similar to this.
#interface myClass {
NSString *somestring;
}
-(NSString *)somestring;
-(void)setSomestring:(NSString *)value;
#end
And:
#implentation myClass
-(NSString *)somestring {
return somestring;
}
-(void)setSomestring:(NSString *)value {
somestring = value;
}
#end
So if you haven't declared somestring as a property and synthesized it, then you don't have those methods to answer the message being passed.

Related

application crashes when appendString for NSMutableString is used

I'm new to objective-c and I decided to start by working through Stanford's CS193s 2010F Session's lectures/assignments.
I was working on the second assignment, and I was stuck when I had to return a NSString that combines(concatenates) every strings inside NSMutableArray. (The MutableArray consists only NSString at its each indices)
My approach was to use a for loop to pass through the MutableArray's indicies(in the code below, the MutableArray is 'anExpression' with type 'id'). I declared a NSMutableString and added NSString at each indices of 'anExpression' array. Here is the code:
+ (NSString *)descriptionOfExpression:(id)anExpression{
NSMutableString *result = [NSMutableString string];
for (int i = 0;i<[anExpression count];i++){
[result appendString:[anExpression objectAtIndex:i]];
}
return result;
}
However, at
[result appendString:[anExpression objectAtIndex:i]];
xcode crashes with following error statements:
2012-07-17 01:44:51.014 Calculator[9470:f803] -[__NSCFNumber length]: unrecognized selector sent to instance 0x68732c0
2012-07-17 01:44:51.015 Calculator[9470:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber length]: unrecognized selector sent to instance 0x68732c0'
*** First throw call stack:
(0x13ca022 0x155bcd6 0x13cbcbd 0x1330ed0 0x1330cb2 0x12d2d18 0x13460d7 0x1397a8d 0x3a50 0x27ed 0x13cbe99 0x1714e 0x170e6 0xbdade 0xbdfa7 0xbd266 0x3c3c0 0x3c5e6 0x22dc4 0x16634 0x12b4ef5 0x139e195 0x1302ff2 0x13018da 0x1300d84 0x1300c9b 0x12b37d8 0x12b388a 0x14626 0x1ed2 0x1e45 0x1)
terminate called throwing an exception
I looked through apple's developer's document, saw 'NSString stringWithFormat:' method, and decided to use this method instead:
+ (NSString *)descriptionOfExpression:(id)anExpression{
NSMutableString *result = [NSMutableString string];
for (int i = 0;i<[anExpression count];i++){
[result appendString:[NSString stringWithFormat:#"%#",[anExpression objectAtIndex:i]]];
}
return result;
}
and it works now.
now I'm confused why second code works but the first doesn't.
I thought appending string only fails(and crashes) when it's passed a nil...
Is there something I'm missing?
Thank you in advance :)
It looks like the contents of anExpression are instances of NSNumber instead of NSString. The error you are getting is a hint as to how appendString works; it's first step is obviously to ask the passed "string" how long it is (presumably so it can allocate enough memory). This is obviously not a method on NSNumber (hence the crash) and stringWithFormat is designed to do type-checking and be more flexible.
I suspect you could also use stringValue just as well:
[result appendString:[[anExpression objectAtIndex:i] stringValue]];
+ (NSString *)descriptionOfExpression:(id)anExpression{
NSMutableString *result = [NSMutableString string];
for (int i = 0;i<[anExpression count];i++) {
[result appendString:[[anExpression objectAtIndex:i] stringValue]];
}
return result;
}
Converting it into string would help you!!
Use this function:
+ (NSString *)descriptionOfExpression:(id)anExpression
{
NSMutableString *result = [[NSMutableString alloc] init];
for (int i = 0;i<[anExpression count];i++)
{
NSString *str = [NSString stringWithFormat:#"%#",[anExpression objectAtIndex:i]];
if(str)
{
[result appendString:str];
}
//OR
//[result appendFormat:[NSString stringWithFormat:#"%#",[anExpression objectAtIndex:i]]];
}
return result;
}

Why does implicit initialization of a variable not work consistently on iPhone?

So here is my scenario -- In the header file of a class I do:
#interface MyClass : NSObject
{
NSString *string1;
NSString *string2;
}
- (void) methodOne: (NSString *) passedString;
- (void) methodTwo: (NSString *) passedString;
#end
In the implementation file I do this:
#import MyClass.h
#implementation MyClass
- (void) methodOne: (NSString *) passedString
{
NSLog(#"%#", passedString);
string1 = passedString;
}
- (void) methodTwo: (NSString *) passedString
{
NSLog(#"%#", passedString);
string2 = passedString;
}
What I am finding is that there is some kind of inconsistency when doing this versus [NSString alloc] initWithString:].
As you can see string1 and string2 are treated exactly the same, but what is happening is that string1 is getting set, but string2 is remaining empty. I get a bad access when I reference it later.
I thought maybe I was passing an empty string to methodTwo: so I added that NSLog which proves that it is not empty, but has the expected string.
Since I have noticed this inconsistency before I decided to change to this:
- (void) methodOne: (NSString *) passedString
{
NSLog(#"%#", passedString);
string1 = passedString;
}
- (void) methodTwo: (NSString *) passedString
{
NSLog(#"%#", passedString);
string2 = [[NSString alloc] initWithString: passedString];
}
Now both strings are working as expected. My question is why is there this inconsistency?
This is not the only time this has happened to me. It has happened with all kinds of objects. The only thing that seems to work every time is alloc init. Methods like stringWithString: work most of the time, but not always.
It's because in the first example, you don't retain or copy the strings. string2 is getting deallocated at some point before you use it. It's actually pure luck that string1 is OK. You should change your code to be something like this:
- (void) methodOne: (NSString *) passedString
{
NSLog(#"%#", passedString);
NSString* oldString = string1;
string1 = [passedString copy];
[oldString release];
}
- (void) methodTwo: (NSString *) passedString
{
NSLog(#"%#", passedString);
NSString* oldString = string2;
string2 = [passedString copy];
[oldString release];
}
and release in dealloc
-(void) dealloc
{
[string1 release];
[string2 release];
// other stuff
[super dealloc];
}
I strongly recommedn you create properties for string1 and string2 to handle all that reference counting stuff:
#interface MyClass : NSObject
{
NSString *string1;
NSString *string2;
}
- (void) methodOne: (NSString *) passedString;
- (void) methodTwo: (NSString *) passedString;
#property (copy) NSString* string1;
#property (copy) NSString* string2;
#end
#imlementation MyClasss
#synthesize string1, string2;
- (void) methodOne: (NSString *) passedString
{
NSLog(#"%#", passedString);
[self setString1: passedString];
}
- (void) methodTwo: (NSString *) passedString
{
NSLog(#"%#", passedString);
[self setString2: passedString];
}
// dealloc as before
#end
You are making memory management errors. You have to retain or copy the strings when you assign them to your ivars (and release them later).
It is possible that you can still access an object even though it has been deallocated when the memory it occupied has not been overwritten yet. But you cannot rely on it.
If the passed strings are autoreleased there is no retain when they are assigned. Constant strings (#str") essentially are never released, created strings such as by stringWithFormat need to be retained.
Please show the callers.
Using #properties with retain will eliminate many retain issues. Or consider using ARC, that eliminates the need for retain/release/autorelease.
As others have stated in this thread you have some memory management issues here, perhaps you aren't quite understanding the way that NSObjects get allocated and retained, you should read up on Objective-C memory management. In the mean time there are two approaches you could take to solve your above issue.
You could have your NSString member variables (string1 & string2) kept as properties of your class, aside from some other functionality declaring these as properties would give them setter and getter accessors, that you would call instead of method1 and method2. So this would change your code to look like the following in your header file
#interface MyClass : NSObject
{
NSString *string1;
NSString *string2;
}
#property( nonatomic, retain)NSString* string1;
#property( nonatomic, retain)NSString* string1;
Then remember to add the following to your source file (typically at the top of the file after the #implementation MyClass line)
#implementation MyClass
#synthesize string1;
#synthesize string2;
Then in the class where you were calling method1 and method2 from you can change the code to look like
//Lets assume somewhere you've called an init Method for your MyClass Object, something like
MyClass* myClassObject = [[MyClass alloc] init];
//you can then call the setters to set the string like so
[myClassObject setString1:#"some string"]; //or myClassObject.string1 = #"some string";
[myClassObject setString2:#"some string"]; //or myClassObject.string2 = #some other string";
//Calling these member variables either of the above ways is valid, I prefer the former as it's a bit easier on the eye for me
//and to get the values back out of the strings you could call
NSString* output = [myClassObject string1];
//or
NSString* output2 = myClassObject.string2;
Now you may for some reason not want to use an #property for the NSString member variables, so you could modify your original source (.m) file to look like
#implementation MyClass
- (void) methodOne: (NSString *) passedString
{
NSLog(#"%#", passedString);
if( string1 != nil )
{
[string1 release];
}
string1 = [[NSString alloc] initWithString:passedString];
}
- (void) methodTwo: (NSString *) passedString
{
NSLog(#"%#", passedString);
if( string2 != nil )
{
[string2 release];
}
string2 = [[NSString alloc] initWithString:passedString];
}
That should solve the issue of why your strings aren't valid, as you wont be overwriting the memory and trying to read back garbage this way. You will have to remember to release these NSStrings in your dealloc if they are not nil, otherwise you'll get a memory leak there too.
Hope this helps.

How to delete single characters in an UITextView

I have an UITextView which is for instance 380 characters in length:
NSLog(#"aTextView.text lenght %i", aTextView.text.length);
I now want to go through this text (backwards, char by char) and delete all characters which come before the last space (e.g. if the last words were "...this is an example", it want to reduce the string to "...this is an ":
for (int i = aTextView.text.length-1; i > 0; i--) {
NSString *checkedChar = [NSString stringWithFormat:#"%c", [aTextView.text characterAtIndex:i]];
NSLog(#"I currently check: %#", checkedChar);
if ([checkedChar isEqualToString:#" "]) {
// job done
i = 0; // this ends the loop
} else {
I need something like [aTextView.text removeCharacterAtIndex:i];
}
}
How do I achieve this? I couldn't find any methods in the docs and would be very grateful for suggestions.
EDIT:
NSString *myString = aTextView.text;
NSRange range = [myString rangeOfString:#" " options:NSBackwardsSearch];
NSString *oldText = [myString subStringToIndex:range.location];
NSString *newText = [myString subStringFromIndex:range.location];
NSLog(#"++++ OLD TEXT ++++: %#", oldText);
NSLog(#"++++ NEW TEXT ++++: %#", newText);
aTextView.text = oldText;
This crashes my app... I am calling this from - (BOOL)textView:(UITextView *)aTextView shouldChangeTextInRange:(NSRange)aRange replacementText:(NSString *)aText
I get the error message: * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFString subStringToIndex:]: unrecognized selector sent to instance 0x4e33850'
And xCode gives me the warning the subStringToIndex may not respond...
You don't need a loop to do this - take a look at NSString' rangeOfString:options: and substringToIndex: methods. For example :
NSRange range = [myString rangeOfString:#" " options:NSBackwardsSearch];
NSString *newString = [myString substringToIndex:range.location];
Hope that helps.
NB Don't forget to check that your string definitely contains a space ;)
This is very easy in iOS 5 or later:
// This is your delete button method.
-(IBAction)btnDelete:(id)sender
{
// txtView is UITextView
if([txtView.text length] > 0)
{
[txtView deleteBackward];
}
}

Javascript style objects in Objective-C

Background: I use a ton of NSDictionary objects in my iPhone and iPad code. I'm sick of the verbose way of getting/setting keys to these state dictionaries.
So a little bit of an experiment: I just created a class I call Remap.
Remap will take any arbitrary set[VariableName]:(NSObject *) obj selector and forward that message to a function that will insert obj into an internal NSMutableDictionary under the key [vairableName].
Remap will also take any (zero argument) arbitrary [variableName] selector and return the NSObject mapped in the NSMutableDictionary under the key [variableName].
e.g.
Remap * remap = [[Remap alloc] init];
NSNumber * testNumber = [NSNumber numberWithInt:46];
[remap setTestNumber:testNumber];
testNumber = [remap testNumber];
[remap setTestString:#"test string"];
NSString * testString = [remap testString];
NSMutableDictionary * testDict = [NSMutableDictionary dictionaryWithObject:testNumber forKey:#"testNumber"];
[remap setTestDict:testDict];
testDict = [remap testDict];
where none of the properties testNumber, testString, or testDict are actually defined in Remap.
The crazy thing? It works... My only question is how can I disable the "may not respond to " warnings for JUST accesses to Remap?
P.S. : I'll probably end up scrapping this and going with macros since message forwarding is quite inefficient... but aside from that does anyone see other problems with Remap?
Here's Remap's .m for those who are curious:
#import "Remap.h"
#interface Remap ()
#property (nonatomic, retain) NSMutableDictionary * _data;
#end
#implementation Remap
#synthesize _data;
- (void) dealloc
{
relnil(_data);
[super dealloc];
}
- (id) init
{
self = [super init];
if (self != nil) {
NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
[self set_data:dict];
relnil(dict);
}
return self;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
NSString * selectorName = [NSString stringWithUTF8String: sel_getName([anInvocation selector])];
NSRange range = [selectorName rangeOfString:#"set"];
NSInteger numArguments = [[anInvocation methodSignature] numberOfArguments];
if (range.location == 0 && numArguments == 4)
{
//setter
[anInvocation setSelector:#selector(setData:withKey:)];
[anInvocation setArgument:&selectorName atIndex:3];
[anInvocation invokeWithTarget:self];
}
else if (numArguments == 3)
{
[anInvocation setSelector:#selector(getDataWithKey:)];
[anInvocation setArgument:&selectorName atIndex:2];
[anInvocation invokeWithTarget:self];
}
}
- (NSMethodSignature *) methodSignatureForSelector:(SEL) aSelector
{
NSString * selectorName = [NSString stringWithUTF8String: sel_getName(aSelector)];
NSMethodSignature * sig = [super methodSignatureForSelector:aSelector];
if (sig == nil)
{
NSRange range = [selectorName rangeOfString:#"set"];
if (range.location == 0)
{
sig = [self methodSignatureForSelector:#selector(setData:withKey:)];
}
else
{
sig = [self methodSignatureForSelector:#selector(getDataWithKey:)];
}
}
return sig;
}
- (NSObject *) getDataWithKey: (NSString *) key
{
NSObject * returnValue = [[self _data] objectForKey:key];
return returnValue;
}
- (void) setData: (NSObject *) data withKey:(NSString *)key
{
if (key && [key length] >= 5 && data)
{
NSRange range;
range.length = 1;
range.location = 3;
NSString * firstChar = [key substringWithRange:range];
firstChar = [firstChar lowercaseString];
range.length = [key length] - 5; // the 4 we have processed plus the training :
range.location = 4;
NSString * adjustedKey = [NSString stringWithFormat:#"%#%#", firstChar, [key substringWithRange:range]];
[[self _data] setObject:data forKey:adjustedKey];
}
else
{
//assert?
}
}
#end
Cool class. I like it.
I can't think of a way to suppress all your warnings, but we can get it down to one line per property. Add this to your Remap.h:
#define RemapProperty(PROP) \
#interface Remap(PROP) \
#property (nonatomic, retain) id PROP; \
#end \
#implementation Remap(PROP) \
#dynamic PROP; \
#end
Now you can suppress all remap warnings for a given property by putting this at the top of the file that's giving you a warning:
RemapProperty(propertyName);
This requires some extra work, but it gives you dot-syntax as a reward.
remap.propertyName = #"Foo";
With a little more work, you could define a similar macro that adds properties directly to NSDictionary, thereby making the Remap class unnecessary.
If I'm reading your code right, I think a potential problem with this approach might be that you can't have key names such as hash (or other methods from NSObject, assuming your Remap inherits from NSObject). You will end up with the Remap instance's hash value rather than letting Remap look up a key called hash within _data, because [remap hash] will not invoke forwardIncovation:, as far as I can tell.
As an alternative for making dictionaries more like general purpose objects, what I have done is make categories of NSDictionary that wrap getters and setters for specific keys. Just use very descriptive names since you are filling a global namespace.
#interface NSDictionary (MyGetters)
#property (nonatomic,readonly) id something;
-(id) something;
#end
#interface NSDictionary (MyGetters)
-(id) something { return [self objectForKey:#"something"]; }
#end
#interface NSMutableDictionary (MySetters)
-(void) setSomething:(id)inValue;
#end
#interface NSDictionary (MySetters)
-(void) setSomething:(id)inValue { return [self setObject:inValue forKey:#"something"]; }
#end
The only problem with setter properties is that you must define the getter in both categories to avoid a warning.
You still have to declare everything, but you are going to have to do that anyway to get rid of warnings for Remap.

Simple calculator app crashes when a third number key is punched

I am a newbie to the iphone app world. So I thought I try my luck with a calculator app.
Unfortunately I am running into an issue where if I press a third key in the calculator the app crashes. Sometimes I get this error EXC_BAD_ACCESS. Here is a code in my CalculatorViewController.m file.
#import "CalculatorViewController.h"
#implementation CalculatorViewController
#synthesize screenText;
- (IBAction)buttonPressed:(id)sender {
NSString *title = [sender titleForState:UIControlStateNormal];
[self collect:title];
}
- (void)collect:(NSString *)digitz {
NSString * newText = nil;
if ([digitz isEqualToString:#"+"]) {
[self add:result];
big_digit = nil;
}
else if ([digitz isEqualToString:#"+"]) {
[self sub:result];
}
else if ([digitz isEqualToString:#"x"]) {
[self multiply:result];
}
else if ([digitz isEqualToString:#"="]) {
[self equate:result];
}
else {
if (big_digit != nil && [big_digit isEqualToString:#"0"] == FALSE)
big_digit = [big_digit stringByAppendingFormat:#"%#",digitz];
else
big_digit = (NSMutableString *) digitz;
result = (int) big_digit;
newText = [[NSString alloc] initWithFormat:
#"%#",big_digit];
}
screenText.text = newText;
[newText release];
}
- (void)add:(int)res {
NSString * newText = nil;
ans = ans + res;
newText = [[NSString alloc] initWithFormat:
#"%#",ans];
screenText.text = newText;
[newText release];
}
Can anyone spot an obvious issue here. Here is the respective header file too.
#import <UIKit/UIKit.h>
#interface CalculatorViewController : UIViewController {
UILabel *screenText;
int number;
int result;
int ans;
//NSString *big_digit;
NSMutableString * big_digit ;
}
#property (nonatomic, retain) IBOutlet UILabel *screenText;
- (IBAction)buttonPressed:(id)sender;
- (void)collect:(NSString *)digitz;
- (void)add:(int)num;
- (void)sub:(int)num;
- (void)multiply:(int)num;
- (void)equate:(int)num;
#end
Well, you probably don't want to just cast a string to an integer (ala (int)big_digit). Instead you want to use [big_digit integerValue];
I think what is happening is that your big_digit property is not retained. In this line, you just assign a string to it that is autoreleased:
big_digit = [big_digit stringByAppendingFormat:#"%#",digitz];
On the next pass through, big_digit is != nil, but [big_digit isEqualToString:#"0"] == FALSE fails because big_digit now points to an invalid memory location.
What you want to do is make big_digit a property in your interface, like so...
#property (nonatomic, retain) NSMutableString *big_digit;
I know reading docs sucks, but looking at your code I think you would really find reading through this useful. Memory management in objective c is quite a bit different from regular old C.
http://developer.apple.com/iphone/library/documentation/cocoa/conceptual/memorymgmt/Articles/mmPractical.html#//apple_ref/doc/uid/TP40004447-SW1
In your format strings, you're doing this:
newText = [[NSString alloc] initWithFormat:#"%#", ans];
But according to your #interface, ans is an integer. So that line should read:
newText = [[NSString alloc] initWithFormat:#"%d", ans];
since %d is the format specifier for an integer.