NSString out of scope problem? - iphone

I'm really pulling my hair out, this must be a simple problem, but I just can't see it.
I'm just trying to assign a value to a variable from a text field.
In my h file I have
NSString *currentPass;
#property (nonatomic, retain) NSString *currentPass;
My m file.
#synthesize currentPass;
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:
(NSInteger)buttonIndex{
if (alertView.tag == AlertPasswordAsk) {
UITextField* theTextField = ((UITextField*)[alertView viewWithTag: 5]);
currentPass = [NSString stringWithFormat:#"%#", theTextField.text];
if ([theTextField isEditing]) {
[theTextField resignFirstResponder];
}
}
}
- (void)alertView:(UIAlertView *)alertView
didDismissWithButtonIndex:(NSInteger)buttonIndex{
NSLog(#"didDismissWithButtonIndex tag=%i", alertView.tag);
if (alertView.tag == AlertPasswordAsk) {
if(buttonIndex == 1){
NSUserDefaults *myDefaults = [NSUserDefaults standardUserDefaults];
NSString *strPassword = [NSString alloc];
strPassword = [myDefaults stringForKey:#"pass"];
// ######### ERROR OCCURS HERE #########
NSLog(#"currentPass=%# strPassword=%#", currentPass, strPassword);
if (![currentPass isEqualToString:strPassword]) {
[6337:207] didDismissWithButtonIndex tag=10
Current language: auto; currently objective-c
(gdb) continue
Program received signal: “EXC_BAD_ACCESS”.
(gdb) bt
#0 0x02894903 in objc_msgSend ()
#1 0x00000000 in ?? ()

You need to retain the object you assign to currentPass:
self.currentPass = [NSString stringWithFormat:#"%#", theTextField.text];

- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:
(NSInteger)buttonIndex{
if (alertView.tag == AlertPasswordAsk) {
UITextField* theTextField = ((UITextField*)[alertView viewWithTag: 5]);
//assigning to member variable will not retain your object.
// current address is just pointing to auto released object not retaining it.
// currentPass = [NSString stringWithFormat:#"%#", theTextField.text];
// use currentPass as with accessor:
self.currentPass = [NSString stringWithFormat:#"%#", theTextField.text];
if ([theTextField isEditing]) {
[theTextField resignFirstResponder];
}
}
}

Related

No known class method for selector 'myStaticUsername'

So I'm trying to access the variable 'username' from another class and append it to a URL as a string. I'm getting the error "No known class method for selector 'myStaticUsername'" and don't really know how to solve it. Any help would be appreciated.
FirstViewController.h
+(NSString *) username;
FirstViewController.m
static NSString *myStaticUsername = nil;
#implementation FirstViewController
+(NSString *) username{
return myStaticUsername;
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
NSLog(#"Cancel Tapped.");
}
else if (buttonIndex == 1) {
myStaticUsername= Textbox.text;
NSLog(myStaticUsername);
}
My ViewController.m class where I'm trying to access it:
- (void)viewDidLoad
{
NSString *email = [FirstViewController myStaticUsername];
NSString *website =[NSString stringWithFormat:#"http://www.nameofwebsite?un=:%#", email]; //append the username right here
Thanks.
In your viewDidLoad you need to change this:
NSString *email = [FirstViewController myStaticUsername];
to this:
NSString *email = [FirstViewController username];
myStaticUsername is the name of your static NSString, but the name of the class method you wrote to access it is username.

how to update a string variable with another string variable

i have a string declare as such
NSString *str = [[NSString alloc] initWithFormat:#"I require an average GPA of at least %.2f to achieve my Goal of %# this semester - NTU GPA Calculator", pgagoal,(NSString *)[myPickerDelegate.myGoal objectAtIndex: [myPicker selectedRowInComponent:0]]];
i declared a global variable
NSStrinng *tweetString
and wants to copy the the string in str to tweetString. how should i copy it? since both are pointers, i tried:
tweetString = str;
or
tweetString = [NSString stringWithFormat:#"%#", str];
but it doest work.
EDIT:
my code:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex1{
NSLog(#"buttonindex 1 clicked");
NSString *str2;
NSLog(#"tweetString before if: %#", tweetString);
if (pgagoal < 0) {
NSString *str2 = [[NSString alloc] initWithFormat:#"Confirm, Guarantee, Chop and Stamp! I can achieve my Goal of %# this semester - NTU GPA Calculator", (NSString *)[myPickerDelegate.myGoal objectAtIndex: [myPicker selectedRowInComponent:0]]];
NSLog(#"tweetString: < 0 %#", str2);
}
else if (pgagoal > 5){
NSString *str2 = [[NSString alloc] initWithFormat:#"Its impossible!, i need an average GPA of at least %.2f to achieve %# this semester - NTU GPA Calculator", pgagoal,(NSString *)[myPickerDelegate.myGoal objectAtIndex: [myPicker selectedRowInComponent:0]]];
NSLog(#"tweetString: >5 %#", str2);
}
else{
NSString *str2 = [[NSString alloc] initWithFormat:#"I require an average GPA of at least %.2f to achieve my Goal of %# this semester - NTU GPA Calculator", pgagoal,(NSString *)[myPickerDelegate.myGoal objectAtIndex: [myPicker selectedRowInComponent:0]]];
NSLog(#"tweetString with else: %#", str2);
}
//did i update tweetString correctly?
tweetString = [NSString stringWithString:str2]; <-- stop working from this point EXC_BAD_ACCESS
NSLog(#"tweetString after if else: %#", tweetString);
[self sendEasyTweet:tweetString];
NSLog(#"tweetString: %#", tweetString);
[str2 release];
}
- (void)sendEasyTweet {
// Set up the built-in twitter composition view controller.
TWTweetComposeViewController *tweetViewController = [[TWTweetComposeViewController alloc] init];
// Set the initial tweet text. See the framework for additional properties that can be set.
[tweetViewController setInitialText:tweetString];
// Create the completion handler block.
[tweetViewController setCompletionHandler:^(TWTweetComposeViewControllerResult result) {
switch (result) {
case TWTweetComposeViewControllerResultCancelled:
// The cancel button was tapped.
NSLog(#"Tweet cancelled");
break;
case TWTweetComposeViewControllerResultDone:
// The tweet was sent.
NSLog(#"Tweet done");
break;
default:
break;
}
// Dismiss the tweet composition view controller.
[self dismissModalViewControllerAnimated:YES];
}];
// Present the tweet composition view controller modally.
[self presentModalViewController:tweetViewController animated:YES];
}
EDIT2:
Debbuger output:
2011-12-29 09:54:22.963 GPA[487:707] buttonindex 1 clicked
2011-12-29 09:54:22.966 GPA[487:707] tweetString before if: NTU GPA Calculator <-- i init the string at viewDidLoad
2011-12-29 09:54:22.968 GPA[487:707] tweetString with else: I require an average GPA of at least 1.56 to achieve my Goal of Third Class Honors this semester - NTU GPA Calculator
(gdb)
EDIT3:
my tweetString is declared in view controller.h as
#interface GPAMainViewController : UIViewController <GPAFlipsideViewControllerDelegate>{
UIPickerView * myPicker;
GPAAppDelegate * myPickerDelegate;
IBOutlet UITextField *txtGPA;
IBOutlet UITextField *txtTotalAU;
IBOutlet UITextField *txtRemainingAU;
double pgagoal;
NSString *tweetString;
}
#property (nonatomic, retain) IBOutlet UIPickerView * myPicker;
#property (nonatomic, retain) IBOutlet GPAAppDelegate *myPickerDelegate;
#property (nonatomic, retain) UITextField *txtGPA;
#property (nonatomic, retain) UITextField *txtTotalAU;
#property (nonatomic, retain) UITextField *txtRemainingAU;
#property (nonatomic, retain) NSString *tweetString;
-(IBAction)finishEditing:(id)sender;
-(IBAction)calculateGoal: (id) sender;
-(IBAction)showInfo:(id)sender;
-(IBAction)nextField:(id)sender;
-(IBAction)resetField:(id)sender;
-(void)sendEasyTweet:(id)sender;
The reason that it doesn't work (it is probably crashing with an EXC_BAD_ACCESS) is because the scope of the variable str is only within the block in which it is declared, the block of the else part of your if/else statement. Try something like this:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex1 {
NSString* str; //declare string here so it is in scope the entire method
.
. //your code
.
.
if(yourConditionHere) {
//make sure you initialize str here as well so if the else part of the statement
// isn't executed, you aren't trying to access an uninitialized variable
} else {
str = [[NSString alloc] initWithFormat:#"I require an average GPA of at
least %.2f to achieve my Goal of %# this semester - NTU GPA Calculator",
pgagoal,(NSString *)[myPickerDelegate.myGoal objectAtIndex: [myPicker
selectedRowInComponent:0]]]; //give str a value
NSLog(#"tweetString with else: %#", str);
} //Variable str is going out of scope here the way you have your code set up now
tweetString = [str copy];
NSLog(#"tweetString after if else: %#", tweetString);
[self sendEasyTweet:tweetString];
NSLog(#"tweetString: %#", tweetString);
[str release];
}
If you want to copy the string, or use the string after you assign it, you either need to copy it or retain it.
NSString *someString = #"This is a string";
NSString *copiedString = [NSString stringWithFormat:#"%#", someString"];
Within a few seconds, both strings will be nil or some other non value. What you must do is :
NSString *someString = #"This is a string";
NSString *copiedString = [NSString stringWithFormat:#"%#", someString"] retain];
By doing this, you will keep both variables in memory as long as they are viable. But in my opinion a better way, especially when dealing with strings is to use copy, like this :
NSString *someString = #"This is a string";
NSString *copiedString = [NSString stringWithFormat:#"%#", someString"] copy];
This will make someString just go away in a few seconds or clock ticks, but copiedString will live on until the function is finished or the class released.
I suspect that you are not getting the string value inside tweetString because both variables have gone from memory when you want to use it.
If you need a variable to stay around, you must copy or retain it.

Referring to an NSString in output of UIAlertView?

I have an NSString, testString which is set to a value in my app. Then as a response to a button press in UIAlertView I have the following code:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
NSLog(#"String: %#", testString);
}
}
But for sme reason, this always causes the app to crash. I can't seem to figure out why.
Probably you create your string with one of convenience methods and don't retain it, so when it comes to alert's clickedButtonAtIndex it's already autoreleased.
You should define it as
#property (nonatomic, retain) NSString *testString;
In implementation:
#synthesize testString;
On creating:
self.testString = [NSString stringWithFormat:#"%#", #"My test string"];
and [testString release]; on dealloc.
Then when you use it in clickedButtonAtIndex you can be sure your testString has a right value

Trying to find out why my app crashes?

This is my code:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSLog(#"location for url1 B %#", locationForURL1);
if ((alertView.tag <= 3) && (alertView.tag >= 1)) {
if (buttonIndex == 1) {
NSLog(#"location for url1 %#", locationForURL1);
The locationForURL1 had an entry in it in the rest of the code up until that point, but it crahes at the first NSLog here.
So i added nszombieenabled and got message sent to deallocated instance 0x508eda0. How do i use this to find out my problem? I've heard people saying put it in the init method, which confused me as i can't find an init method. I've never done debugging like this before.
EDIT:
I am allocating it like this:
#interface RewriteViewController : UIViewController <MPMediaPickerControllerDelegate> {
NSString *locationForURL1;
}
#property (nonatomic,retain) NSString *locationForURL1;
I think it's something to do with the self.VARIABLE thing, but i can never figure out when i'm meant to put the self. and if i'm meant to put something else instead.
This is all the references i have to locationForURL1 in the .m file:
#synthesize locationForURL1;
-(void)getWeatherLocation {
if (currentResult == 1) {
self.locationForURL1 = locationTown;
locationForURL1 = [locationForURL1 stringByAppendingString:#","];
locationForURL1 = [locationForURL1 stringByAppendingString:locationCountry];
}
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if ((alertView.tag <= 3) && (alertView.tag >= 1)) {
if (buttonIndex == 1) {
NSLog(#"location for url1 %#", self.locationForURL1);
self.weatherFullURL = [self.weatherFullURL stringByAppendingString:self.locationForURL1];
}
}
}
-(void)dealloc {
[locationForURL1 release];
[super dealloc];
}
self.locationForURL1 = locationTown;
locationForURL1 = [locationForURL1 stringByAppendingString:#","];
locationForURL1 = [locationForURL1 stringByAppendingString:locationCountry];
You are retaining locationTown by using self.locationForURL1, then immediately overwriting that assignment with two autoreleased objects. So, you are leaking one object and then your crash happens when the autorelease pool reaps the result of stringByAppendingString:.
http://www.markj.net/iphone-memory-debug-nszombie/
You must not be retaining locationForURL1 where ever you are creating it. I would suggest adding it as a property to your class:
#interface YourClass : UIViewController {
NSString *locationForURL1;
}
#property (nonatomic, copy) NSString *locationForURL1;
Then in your viewDidLoad (or where ever you are creating that string), do something like:
NSString *location = [[NSString alloc] initWith....];
self.locationForURL1 = location;
[location release];
Then in your -alertView:clickedButtonAtIndex: method, just refer to it as self.locationForURL1 and you should be fine.

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.