Referring to an NSString in output of UIAlertView? - iphone

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

Related

NSstring with format error in IBAction

I have declared NSString with some string value in ViewdidLoad like..
int i=1;
strval=[NSString stringWithFormat:#"%03d",i];
strval=[NSString stringWithFormat:#"S%#",strval];
NSLog(#"Value %#",strval);
it gives correct result as S001, but when i print this same in IBAction like,
- (IBAction)stringvalue:(id)sender {
NSLog(#"Value %#",strval);
}
it gives unknown values each time.Sometimes it throws EXEC_BAD_ACCESS error.
Please help me..
Try something like this
in .h
#property (nonatomic, strong) NSString *strval;
in .m
#synthesize strval = _strval
- (void)viewDidLoad
{
int i = 4;
// ARC
_strval = [NSString stringWithFormat:#"hello %d", i];
// None ARC
// strcal = [[NSString alloc] initwithFormat:#"hello %d",i];
NSLog(#"%#", _strval);
// Prints "hello 4" in console (TESTED)
}
- (IBAction)buttonPress:(id)sender
{
NSLog(#"%#", _strval);
// Prints "hello 4" in console (TESTED)
}
using ARC. This has been tested and works the way the question has been asked.
Looks like you aren't using ARC, so the string is being released the next time the autorelease pool drains. You need to explicitly retain it in viewDidLoad and explicitly release it in your overwridden dealloc method:
- (void)viewDidLoad
{
...
strval = [[NSString stringWithFormat:#"%03d", i] retain];
....
}
- (void)dealloc
{
[strval release];
...
[super dealloc];
}
(I am assuming you've actually declared strval as an instance method).
in .h
#property (nonatomic, strong) NSString *strval;
in .m
#synthesize strval = _strval
- (void)viewDidLoad
{
...
self.strval = [NSString stringWithFormat:#"%03d", i];
....
}
- (void)dealloc
{
self.strval = nil;
...
[super dealloc];
}
This one works either, with ARC and without.
Just one addition: With ARC the statement [super dealloc]; must be omitted.

How to solve a error when I call the method [self somemethod]

I have this code:
// .m
- (void)viewDidLoad {
NSMutableArray *array = [[NSMutableArray alloc] init];
[self addToArray];
}
- (void)addToArray {
NSString *stringA;
[stringA isEqualToString:#"door"];
NSString *stringB;
[stringB isEqualToString:textField.text];
[array addObject:stringA];
if ([stringA isEqual:stringB]) {
[stringA isEqual:nil];
[tableView reloadData];
} else {
[array addObject:stringB];
[tableView reloadData];
}
}
When I call the method addToArray it keeps returning me an error called Thread 1: Program recived signal "EXC_BAD_ACCESS", and the debugger output says : Single stepping until exit from function objc_msgSend, which has no line number information. at the line [self addToArray]. Any idea of how to solve it? I have wasted to much time with it, please help me!
As was said by others, array should be an instance variable or property of the class, declared in the .h file:
#property (strong) NSMutableArray *array;
Or, without ARC:
#property (retain) NSMutableArray *array;
Now you #synthesize array; in your implementation file and can access it from anywhere. Then you can do:
- (void) viewDidLoad
{
self.array = [[NSMutableArray alloc] init];
[self addToArray];
}
You seem to assume that isEqualToString does an assignment. It doesn't, it checks strings for (textual) equality. Try this:
- (void) addToArray
{
NSString *stringA = #"door";
NSString *stringB = textField.text;
[array addObject: stringA];
if (![stringA isEqualToString: stringB])
[array addObject: stringB];
[tableView reloadData];
}
These two variables are uninitialized and will cause you big problems:
NSString *stringA;
[stringA isEqualToString:#"door"];
NSString *stringB;
[stringB isEqualToString:textField.text];
You have not assigned anything to either stringA or stringB. Besides the result of your call to isEqualToString is never used.
Two things I can notice in your code:
1) Make array a class variable, so you can access it from your -[addToArray] method. Better do this in your .h file, for example:
#interface MyViewController : UIViewController {
#private
// ...skipped...
NSMutableArray * array;
// ...rest of class skipped...
}
#end
Then, in your .m file the method should look like this:
// .m
- (void)viewDidLoad {
array = [[NSMutableArray alloc] init];
[self addToArray];
}
And don't forget to release the array:
- (void)dealloc {
[array release];
[super dealloc];
}
2) Do not mess up -[NSString isEqualToString:] method with simple assigment to a variable. So in your -[addToArray] method, for example, replace this:
NSString *stringA;
[stringA isEqualToString:#"door"];
with this:
NSString *stringA = #"door";
And this:
NSString *stringB;
[stringB isEqualToString:textField.text];
with this:
NSString *stringB = textField.text;
3) Check the logic of -[addToArray] method - it is not very clear what are you going achieve.

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.

Memory leak in NSMutableArray

while(sqlite3_step(selectstmt) == SQLITE_ROW) {
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
//Expenseentry* temp=[[[Expenseentry alloc]init]autorelease];
//Expenseentry* temp=[[Expenseentry alloc]init];
temp=nil;
temp=[[Expenseentry alloc]init];
//memory leak here
temp.ID=[NSString stringWithFormat:#"%d",primaryKey];
//memory leak here
int i=1;
#try{
//Expenseentry* temp=[[Expenseentry alloc]init];
//tried this but no luck
NSString *s=[[NSString alloc]initWithFormat:#"%f",sqlite3_column_double(selectstmt, 1)];
temp.amount=s;
[s release];
[arrreturn addObject:temp];
//[temp release];
//if i uncomment this app crashes
//[formatter release];
//printf("\n daata count %d ",[arrreturn count]);
}
#catch(id ex )
{
printf("ooooopssss exception ");
}
i++;
}
my expense entry class
#interface Expenseentry : NSObject {
NSString *ID;
NSString *amount;
}
#property (nonatomic, retain) NSString *ID;
#property (nonatomic, retain) NSString *amount;
#end
and .m is just
- (void)dealloc {
[ID release];
[amount release]
}
It looks like temp is an instance variable for that class
Make sure you release temp when you are done or right before you use it again
Try doing the following
[temp release];
temp=[[Expenseentry alloc]init];
temp.ID=[NSString stringWithFormat:#"%d",primaryKey];
The other option is to release after your done with it inside of the while(sqlite3_step) loop
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
...
temp=[[Expenseentry alloc]init];
temp.ID=[NSString stringWithFormat:#"%d",primaryKey];
... //Use temp
[temp release];
temp = nil; //Best practice to set it to nil
If the temp.ID string is leaking you need to look into the Expenseentry class to make sure your doing proper memory management there.
Edit: I now see the rest of your code posted
[arrreturn addObject:temp];
//[temp release];
//if i uncomment this app crashes
The reason why it is probably crashing is as I said before make sure you set it to nil after releasing
Edit 2: You are reusing the same object inside of the while loop also
You will want to move the temp allocation into the while loop or else every object in that array will point to the same object. I am not sure what you goal is with the code but take at a look at the following code.
while(i>5)
{
temp=[[Expenseentry alloc]init];
temp.ID=[NSString stringWithFormat:#"%d",primaryKey];
#try
{
NSString *s=[[NSString alloc]initWithFormat:#"%f",sqlite3_column_double(selectstmt, 1)];
temp.amount=s;
[s release];
[arrreturn addObject:temp];
}
#catch(id ex )
{
printf("ooooopssss exception ");
}
[temp release];
temp = nil;
i++;
}
the temp=nil seems a bit odd. whenever you assign the variable temp to a new object don't forget to release the previous object.
if you write:
Expenseentry* temp=[[Expenseentry alloc]init];
temp=nil;
you get a memory leak because you have created an Expenseentry object and then said good riddance to the object basically. You need to do a [temp release]; before assigning to nil on the iphone.
there could be other leaks like in your Expenseentry but you don't show how it looks like i.e. how the properties ID are declared.
Ok I found my mistake just posting if any one can explain this behavior:
memory leak cause array and array-object were not released.If I would release any of it app crashes.
mistake 1:[super dealloc] missing in expenseentry's dealloc.
doubt:why is it required to release super? when apple doc says you have to release object you own.
mistake 2:array being returned by this function is stored in instance variable(and synthesized property with retain as attribute) of caller.
and I have released that property in dealloc as it is retained.
receivedArr=fun()
in dealloc
[receivedArr release]

iPhone SDK: NSMutableArray count causes EXC_BAD_ACCESS

This is really twisting my mind… I'm trying to access an NSMutableArray in an IBAction which I defined in viewDidLoad. Unfortunately I keep getting a EXC_BAD_ACCESS.
I'm new to all this so I'd really appreciate some insight in what I'm doing wrong.
Below find the corresponding code excerpts.
CounterViewController.h:
#interface CounterViewController : UIViewController{
NSMutableArray *countHistoryArray;
}
#property(nonatomic, retain) NSMutableArray *countHistoryArray;
CounterViewController.m:
#implementation CounterViewController
#synthesize countHistoryArray;
- (void)viewDidLoad {
[super viewDidLoad];
//Fill array with some dummy data
self.countHistoryArray = [[NSMutableArray alloc] init];
NSDate *now = [[[NSDate alloc] init] autorelease];
CurrentCount *historicCount = [[[CurrentCount alloc]
initWithCount:[NSNumber numberWithInteger:22]
description:#"Testcount"
dateAndTime:now] autorelease];
[self.countHistoryArray addObject: historicCount];
//Do some logging - everything is working fine here!
NSLog(#"%#", [self.countHistoryArray description]);
}
//Later on we click on a button and want to use the array
- (IBAction)doSomeStuff {
//Let's look at the array again - and now it crashes with EXC_BAD_ACCESS
NSLog(#"%#", [self.countHistoryArray description]);
}
Thanks a lot!
Manuel
EDIT Additional code as asked for by #jamapag
CurrentCount.h
#import <Foundation/Foundation.h>
#interface CurrentCount : NSObject {
NSNumber *counterLevel;
NSString *description;
NSDate *dateAndTime;
}
- (id)initWithCount:(NSNumber *)newCounterLevel description:(NSString *)newDescription dateAndTime:(NSDate *)newDateAndTime;
#property(nonatomic, copy) NSNumber *counterLevel;
#property(nonatomic, copy) NSString *description;
#property(nonatomic, copy) NSDate *dateAndTime;
#end
CurrentCount.m
#import "CurrentCount.h"
#implementation CurrentCount
#synthesize counterLevel;
#synthesize description;
#synthesize dateAndTime;
- (id)initWithCount:(NSNumber *)newCounterLevel description:(NSString *)newDescription dateAndTime:(NSDate *)newDateAndTime{
self = [super init];
if(nil != self){
self.counterLevel = newCounterLevel;
self.description = newDescription;
self.dateAndTime = newDateAndTime;
}
return self;
}
-(void) dealloc{
self.counterLevel = nil;
self.description = nil;
self.dateAndTime = nil;
[super dealloc];
}
#end
Are you sure that your code actually looks like this?
- (IBAction)doSomeStuff {
//Let's look at the array again - and now it crashes with EXC_BAD_ACCESS
NSLog(#"%#", [self.countHistoryArray description]);
}
Your question title says "NSMutableArray count causes EXC_BAD_ACCESS" - if that line of code actually says NSLog(#"%#", [self.countHistoryArray count]);, you'll almost certainly get a crash, since NSLog will attempt to treat a primitive type (the type returned by -[NSArray count]) as an object. In order to use -[NSArray count] in NSLog, use %u instead of %#:
- (IBAction)doSomeStuff {
// This time it should work!
NSLog(#"Array Count = %u", [self.countHistoryArray count]);
}
Remove autorelease from:
currentCount *historicCount = [[[CurrentCount alloc]
initWithCount:[NSNumber numberWithInteger:22]
description:#"Testcount"
dateAndTime:now] autorelease];
It looks like you are accidentally releasing countHistoryArray somewhere. Try removing all calls to it except for those two you showed. Additionally you can try enabling zombies to debug the problem.
Oh and by the way you probably don't really want a public NSMutableArray property and if you do you probably want it to be copy, not retain. Otherwise incapsulation kinda goes down the drain.
I know this question has already been solved and accepted but its for others who are or will face this issue.
I was facing the same issue, I tried all solutions but no solution worked for me. The project I am working on is NON-ARC.
I tried and made a simple change in property
Previously my property for NSMUTABLEARRAY was
#property (nonatomic, assign) NSMutableArray * dataArray;
I changed it to:
#property (nonatomic, retain) NSMutableArray * dataArray;
Changed it from ASSIGN to RETAIN
And it solved my problem