Trying to find out why my app crashes? - iphone

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.

Related

NSZombieEnabled prevents my app from crashing

So I've been debugging like a mad men using NSZombiesEnabled and NSZombies in Instruments. However when running the app using zombies it seems to resolve my issue. When I run the app without NSZombiesEnabled or NSZombies in instruments it crashes. Any idea on how to deal with this?
So the issue is that I am releasing something twice, but can't seem to find where I am doing this. Turning on NSZombieEnabled won't help as the program runs fine without telling me where I am over releasing.
So I think I kind of know where it's crashing, I have this globalArray Singleton class that I am creating:
extern NSString * const kClearDataSource;
#interface AHImageDataSource : NSObject
+ (AHImageDataSource *)sharedDataSource;
- (void) clearDataSource;
- (void) addObject:(id) object;
- (void) addObject:(id)object atIndex:(int) index;
- (int) count;
- (id) objectAtIndex:(int) index;
#end
NSString * const kClearDataSource = #"clearDataSource";
#interface AHImageDataSource()
{
NSMutableArray * imageDataSource_;
}
#property (nonatomic, retain) NSMutableArray * imageDataSource_;
#end
#implementation AHImageDataSource
#synthesize imageDataSource_;
+ (AHImageDataSource *)sharedDataSource {
static AHImageDataSource *_sharedClient = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedClient = [[self alloc] init];
});
return _sharedClient;
}
- (id)init {
self = [super init];
if (!self) {
return nil;
}
NSMutableArray * temp = [[NSMutableArray alloc] initWithCapacity:200];
self.imageDataSource_ = temp;
[temp release];
return self;
}
-(void) clearDataSource
{
if ([self.imageDataSource_ count] > 0){
[self.imageDataSource_ removeAllObjects];
}
}
- (void) addObject:(id) object
{
[self.imageDataSource_ addObject:object];
}
- (void) addObject:(id)object atIndex:(int) index
{
[self.imageDataSource_ insertObject:object atIndex:index];
}
- (int) count
{
return [self.imageDataSource_ count];
}
- (id) objectAtIndex:(int) index
{
if (index >= 0 && index < [self.imageDataSource_ count]){
return [self.imageDataSource_ objectAtIndex:index];
}
return nil;
}
- (void) dealloc
{
[super dealloc];
[imageDataSource_ release];
}
#end
at one point of the code I am trying to remove all of the objects in the array and then adding some stuff in. When that happen the crashed happened.
This part of the code crashes the second time it was executed:
NSArray *arr = [response valueForKey:#"data"];
if ([arr count] > 0){
[[AHImageDataSource sharedDataSource] clearDataSource];
}
for (NSDictionary * data in arr){
AHInstagramImageData * imgData = [[AHInstagramImageData alloc] initWithData:data];
[[AHImageDataSource sharedDataSource] addObject:imgData];
[imgData release];
}
You should definitely not do [super dealloc] first in your -dealloc method. It must come last.
Go go Product -> Analyze. The messages displayed will give you the solution or an idea.
Your app crashes when an object that has been deallocated is sent a message. NSZombiesEnabled prevents your app from crashing because it holds on to all deallocated objects (and thus leaks everything). It will print a message in the console when a deallocated object is sent a message (which would normally crash your app). Something to the affect of "message 'bar' sent to deallocated object 'foo'" (or something like that). It does not actually pause execution of your app.
When you've passed the point where you know your app generally crashes, check the console log for a message similar to the one above.

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 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.

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

NSString out of scope problem?

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