NSZombieEnabled prevents my app from crashing - iphone

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.

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.

Iterate through NS array of obs

I need to take this data structure, an nsmutablearray, and iterate through each index and print each field into a textfield. every "forward" button increments the data ahead and "backwards" goes back. I am having a really hard time getting this to work properly, does anyone know what im doing wrong. Keep in mind, the object held in the array, called info_holder, is an object that holds 3 strings and one counter:
#import "ZDViewController.h"
#implementation ZDViewController
#synthesize password;
#synthesize count;
#synthesize web;
#synthesize username;
#synthesize header;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *array = [[NSMutableArray alloc] init];
info_holder *set1 = [[info_holder alloc] init];
info_holder *set2 = [[info_holder alloc] init];
info_holder *set3 = [[info_holder alloc] init];
info_holder *set4 = [[info_holder alloc] init];
info_holder *set5 = [[info_holder alloc] init];
[set1 SetUser: #"info1"]; //temporary information until big is fixed
[set1 SetPass: #"info2"];
[set1 SetKey: #"webinfo1"];
[set1 SetCount: 0];
[set2 SetUser: #"info3"];
[set2 SetPass: #"info4"];
[set2 SetKey: #"webinfo2"];
[set2 SetCount: 0];
[set3 SetUser: #"info5"];
[set3 SetPass: #"info6"];
[set3 SetKey: #"webinfo3"];
[set3 SetCount: 0];
[set4 SetUser: #"info7"];
[set4 SetPass: #"info8"];
[set4 SetKey: #"webinfo4"];
[set4 SetCount: 0];
[set5 SetUser: #"info9"];
[set5 SetPass: #"info10"];
[set5 SetKey: #"Webinfo5"];
[set5 SetCount: 0];
}
- (void)viewDidUnload
{
[self setHeader:nil];
[self setWeb:nil];
[self setPassword:nil];
[self setCount:nil];
[self setUsername:nil];
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (IBAction)increment:(id)sender {
if(username.text==#"test")
username.text=#"test2";
else
username.text=#"test";
//this should print a new username NSSTRING, wedsite NSTRING, password NSTRING and INEGER counter, heald in the info_holder object, incremented per click backwards
}
- (IBAction)decrement:(id)sender {
}
- (IBAction)Inc:(id)sender {
}
- (IBAction)textFieldDoneEditing:(id)sender {
[sender resignFirstResponder];
}
- (IBAction)backgroundTap:(id)sender {
[web resignFirstResponder];
[username resignFirstResponder];
[count resignFirstResponder];
[password resignFirstResponder];
}
#end
and my main is:
#import <UIKit/UIKit.h>
#import "ZDAppDelegate.h"
#import "info_holder.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([ZDAppDelegate class]));
}
}
- (IBAction)forwards:(id)sender {
//this should print a new username NSSTRING, wedsite NSTRING, password NSTRING and INEGER counter, heald in the info_holder object, incremented per click forward
for(int i=0;i<your_array.count;i++){
username.text=[your_array objectAtIndex:i];
password.text=[your_array objectAtIndex:i];
key.text.text=[your_array objectAtIndex:i];
}
}
Note-1: I assume your texrfield names as username, password and key
Note-2: Your question is too long an i think no one will read so many code to find your matter. Just share what you need .
First, Class names should start in Caps and method names should start in lower case.
Second, your setters in info_holder class (which should be InfoHolder) have potential issues.
an example setter should look like:
- (void)setUser:(NSString *)username
{
[username retain];
[uname release];
uname=username;
}
You didn't state what's not working, but one problem is that you're not retaining those strings.
BASED ON COMMENTS
You need to declare logins a property.
in ZDViewController.h
#interface ZDViewController : UIViewController
#property (strong, nonatomic) NSMutableArray *logins;
Then in ZDViewController.m
#implementation ZDViewController
#synthesize logins;
.
.
.
- (void)viewDidLoad {
logins = [NSMutableArray array];
.
.
.
}
Then you can access self.logins from anywhere in your class
did you stored your info_holder objects into the NSMutableArray instance, If so then you can access the element(info holder instances in your case) of mutable array by either one of the below method,for(ClassName *tmp in _arrayName){ tmp.property1;tmp.property2;..... }or if you want it as index specific for(int index=0;index<[_arrayName count];index++){ ClassName *tmp = [_arrayName objectAtIndex:index];tmp.property1;tmp.property2;.....}. I exactly can't understand your problem but from your writings i guess thee above can be the solution. If not let me know your question , if this certainly helped you then accept the answer. Note: As #dbrajkovic suggest , always follow the naming convention in your programs, that give more flexible readability.

multiple thread app crash, log said Unable to restore previously selected frame

interface file:
// ...
UITextView *statusTextView_;
UITableView *accountListTableView_;
NSMutableArray *accountList_;
NSString *lastStatus_;
// ...
#property (retain) UITextView *statusTextView;
#property (retain) UITableView *accountListTableView;
#property (retain) NSMutableArray *accountList;
#property (retain) NSString *lastStatus;
// ...
implement file:
// ...
#synthesize statusTextView=statusTextView_;
#synthesize accountListTableView=accountListTableView_;
#synthesize accountList=accountList_;
#synthesize lastStatus=lastStatus_;
- (void)aBtnTapAction:(id)sender
{
[self.lastStatus release];
NSString *buf = [[NSString alloc] initWithString:self.statusTextView.text];
self.lastStatus = buf;
[buf release];
for (NSDictionary *dict in self.accountList) {
if (TRUE == [[dict objectForKey:#"checked"] boolValue]) {
NSString *selectorName = [[NSString alloc] initWithFormat:#"%#:", [dict objectForKey:#"name"]];
SEL sel = NSSelectorFromString(selectorName);
[selectorName release];
if (YES == [self respondsToSelector:sel]) {
[self performSelectorInBackground:sel withObject:dict];
}
}
}
}
selectorName is one of followings
- (void)sina:(NSDictionary *)info
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
SinaController *sina = [[FooController alloc]
initWithUsername:[info objectForKey:#"username"]
andPasswd:[info objectForKey:#"passwd"]];
code = [sina post:self.lastStatus];
[sina release];
[pool release];
}
- (void)qq:(NSDictionary *)info
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
QQController *qq = [[FooController alloc]
initWithUsername:[info objectForKey:#"username"]
andPasswd:[info objectForKey:#"passwd"]];
code = [qq post:self.lastStatus];
[qq release];
[pool release];
}
app always crash in qq or sina thread, log said:
warning: check_safe_call: could not restore current frame
warning: Unable to restore previously selected frame.
Testing environment: MacOS10.6.7, XCode4 & Simulator.
I can't find any useful information by XCode Product -> analyze or Profile -> memory leaks.
I'm following Memory Management Programming Guide and try my best to fix it, but it still crash.
What's wrong with my code, why it crash ?
What are best practices that Objective-C coder when writing multiple thread pragram ?
Thanks for reply.
By releasing using the dot notation, you are over-releasing.
[self.lastStatus release];
should just be
self.lastStatus = nil;
Otherwise you are calling a release on lastStatus and then when you assign the new value using
self.lastStatus = buf;
Then this is first calling a release on the already released object. For more information read up about properties, the dot notation and memory management.

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.

Array is empty after function

I am newbie with Cocoa Touch, I have a problem that I try to figure out. I will appreciate if anyone could help.
I would like to create a tableDataList to display on the table. AsyncViewController will call TableHandler fillList method to initialize table data. But after fillList call, the tableDataList return empty.
Can anyone explain me this problem?
In "AsyncViewController.m":
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[self.myHandler fillList];
[super viewDidLoad];
}
In "TableHandler.m":
#implementation TableHandler
#define ItemNumber 20
#synthesize tableDataList;
- (void) fillList {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:(NSUInteger) 20];
for (NSUInteger i = 0; i < ItemNumber; i++) {
[array addObject:[NSString stringWithFormat:#"Row %d", i]];
}
tableDataList = [NSArray arrayWithArray:array];
}
Thanks
tableDataList needs to retain the new array, or it will be autoreleased soon after your call.
If tableDataList is a #property with retain, just change the line above to:
self.tableDataList = [NSArray arrayWithArray:array];
and the setter will handle it for you.
The equivalent of a #property (retain) NSArray *tableDataList; is in code,
- (void)setTableDataList:(NSArray *)anArray
{
if (tableDataList != nil) {
[tableDataList autorelease];
}
tableDataList = [anArray retain];
}
The above code will automatically release and retain objects when you replace the variable, using self.tableDataList = SOMETHING. However, if you just use tableDataList = SOMETHING you are not using the above setter, you're setting the variable directly.
Are you sure it's empty and not nil? You may need to alloc the tableDataList before you use it