exc_bad_access when Property added - iphone

I have a TabBarController in one tab I have a TableViewController inside a NavigationController.
When I add a property like
#property CGFloat rowHeight;
or add something like
if ([self.modelTypeCell isEqualToString:#"TypeOneCell"])
I get an
error: gdb remote returned an error: E08 EXC_BAD_ACCESS (Code=1....
in this line
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
I cant debug anything and no breakpoint get hit before the error occurs.
EDIT: Zombies didnt give me informations, in Instruments and on a real device no error was thrown...
EDIT2:
I found out the problem should lay here
-(void)setupControllerDictionaries
{
self.masterViewControllerDictionary = [[NSMutableDictionary alloc] init];
TableMasterViewController *master = [[TableMasterViewController alloc] initWithModelType:ModelTypeCustomer];
[self.masterViewControllerDictionary setObject:master forKey:[NSNumber numberWithInt:ModelTypeCustomer]];
[master release];
}
when I comment out the master release the error is gone, maybe its the error maybe its somewhere else

Property can be best used when written like this:
#property(nonatomic, assign) CGFloat rowHeight;
nonatomics is for that the property can perform in multiple threads and assign means that property should use assignment property while assigning to property something. The retain can not be used with this as this variable is not a pointer type

Related

Objective c: setting an object attribute ; attribute not updating

Wow. I have had a total mental failure this morning stuck on this 101 problem.
In ViewController, I have this code. But after it executes, the value of [proposalInfo expanded] is still NO. Can somebody see what I'm doing wrong?
- (void)showFullProposal:(id) sender {
// update proposalinfo
ProposalInfo *proposalInfo = [self.proposalInfoArray objectAtIndex:index.section];
[proposalInfo setExpanded:YES];
}
The variables are declared as follows:
ViewController:
#interface ViewController()
#property (nonatomic, strong) NSMutableArray* proposalInfoArray;
#end
ProposalInfo.h:
#interface ProposalInfo : NSObject
#property (assign) BOOL expanded;
#end
ProposalInfo.m:
#synthesize expanded;
Please help!!
If you never alloc/init your proposalInfoArray array, you could experience behavior like this (i.e. get no error, but always get NO back because when you send a message to a nil object, you get nil back). If not precisely this, it's going to be something simple like that. Check proposalInfoArray and make sure it's not nil. Also check the proposalInfo object you got back, make sure it's not nil.
To illustrate your likely problem, this reproduces the behavior you describe (e.g. expanded looks like it's NO, regardless, but you still don't get any exception):
self.proposalInfoArray = nil; // This obviously won't work
[self.proposalInfoArray addObject:[[ProposalInfo alloc] init]];
ProposalInfo *proposalInfo = [self.proposalInfoArray objectAtIndex:0];
NSLog(#"before=%d", proposalInfo.expanded); // OK, IT'S "0"
proposalInfo.expanded = YES;
NSLog(#"after=%d", proposalInfo.expanded); // HEY, IT'S STILL "0" -- BAD!
Whereas this works properly:
self.proposalInfoArray = [[NSMutableArray alloc] init];
[self.proposalInfoArray addObject:[[ProposalInfo alloc] init]];
ProposalInfo * proposalInfo = [self.proposalInfoArray objectAtIndex:0];
NSLog(#"before=%d", proposalInfo.expanded); // OK, IT'S "0"
proposalInfo.expanded = YES;
NSLog(#"after=%d", proposalInfo.expanded); // HEY, IT'S NOW "1" -- GOOD!
In terms of how to identify these issues in the future, use NSAssert. We would have found this problem if we had the following line of code before the objectAtIndex line:
NSAssert(self.proposalInfoArray, #"proposalInfoArray must be initialized!");
or, after the objectForIndex:
NSAssert(proposalInfo, #"proposalInfo must not be nil!");
The nice thing about NSAssert statements is that you can put them in your code, and when you build for debugging, they help you find your program logic mistakes, but when you build your final release version, they're automatically omitted, making your code more efficient. So, use NSAssert liberally!
Imme, the following line seems to be strange:
ProposalInfo *proposalInfo = [self.proposalInfoArray objectAtIndex:index.section];
Actually, what do you have in your array, means in proposalInfoArray.
Have you checked your object?

Simple functions giving me a crash on Objective-C

I'm coding a simple calculator and I want to make an unique function for all 4 arithmetic buttons. I got here:
-(IBAction)simbolo1:(UIButton*)sender{
if (isNumeric(campo1.text)) {
NSString *str=campo1.text;
campo2.text=str;
int S=1;
NSString *cmp1 = [NSString stringWithFormat:#"%d", S];
sinal.text=cmp1;
campo1.text=#"";
} else {
campo1.text=#"Only numeric values";
}
}
But, for some reason, I cant get this to work. Everytime I click in the button, I get a crash.
So, I check where really was the error and I deleted the whole code:
-(void)simbolo1:(UIButton*)sender{
campo1.text=#"Only numeric values";
}
Those lines of code appear to gave me the same error as before
I'm getting a 'green :marker' on this file:
#import <UIKit/UIKit.h>
int main(int argc, char *argv[]){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil); <--------- This line right here
[pool release];
return retVal;
}
EDIT---------------
On the debud console im getting this:
2011-09-30 09:17:14.319 Teste iPhone[28432:fb03] Applications are expected to have a root view controller at the end of application launch
2011-09-30 09:17:21.714 Teste iPhone[28432:fb03] -[Teste_iPhoneAppDelegate simbolo1]: unrecognized selector sent to instance 0x6b7c2d0
2011-09-30 09:17:21.715 Teste iPhone[28432:fb03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Teste_iPhoneAppDelegate simbolo1]: unrecognized selector sent to instance 0x6b7c2d0'
*** First throw call stack:
(0x166d062 0x17fed0a 0x166ecfd 0x15d3f10 0x15d3cf2 0x166eed9 0x16eb2 0x16e4a 0xbc3e6 0xbc8af 0xbbb6e 0x3c2a0 0x3c4c6 0x22c74 0x16399 0x1557fa9 0x16411d5 0x15a6042 0x15a492a 0x15a3dd4 0x15a3ceb 0x1556879 0x155693e 0x1438b 0x272d 0x26a5)
terminate called throwing an exception(gdb)
There is not enough information to help you. You need to look in the debugger console and show us the error and the stack.
However, I'm going to take a wild guess and say that you didn't connect the campo1 IBOutlet to its UIView in Interface Builder, and that it's nil. To fix, edit the view in Interface Builder (or in Xcode 4, just click on it), and drag the little circle next to the campo1 outlet (in the Connections tab) onto the UIView component that you want it to correspond to.
If that's not it, the error isn't here, but is probably caused by something else in your program.
[EDIT after seeing console]: Your connections look misconfigured. Why would it try to send the simbolo1 selector to Teste_iPhoneAppDelegate? It should send it to your ViewController. Did you play around with the connections (specifically, the delegate one) in Interface Builder -- or the class?
to set text in UITextField use
[campo1 setText:#"Only numeric values"];
and also don't forget to link IBOutlet UITextField* campo1; to proper UITextField in XCode IB

iPhone EXC_BAD_ACCESS when using blocks

Im trying to create a simple callback using blocks.
I have a MainViewController which addSubView another DatePickerViewController.view i created a block like this
typedef void(^DateChangedBlock)(NSDate*);
And i have a method on my DatePickerViewController called
setOnDateChangedCallback:(DateChangedBlock)callback
I store the callback in a property of the DatePickerViewController. The DatePickerViewController's view is a UIDatePicker instance, ive bound an IBAction to the value changed to a method that does this.
- (IBAction)dateChanged:(id)sender {
if (dateChangedCallback != nil)
{
dateChangedCallback(nil);
}
}
Here is how i register the block in the MainViewController
DatePickerViewController *dateController = [[DatePickerViewController alloc] initWithNibName:#"DatePickerView" bundle:nil];
self.datePicker = dateController;
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 100, 200)];
[self.view addSubview:textView];
DateChangedBlock myBlock = ^(NSDate *newDate) {
textView.text = #"testing";
};
[self.datePicker setOnDateChanged: myBlock];
[self.datePicker dateChanged:self]; // force trigger (this works).
When i force trigger the dateChanged method on the DatePickerViewController it works no problem. But when the datepicker itself triggers the method thru the IBAction i get a EXC_BAD_ACCESS error. The error occurs in this method on the "int retVal" line.
#import <UIKit/UIKit.h>
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil); // THREAD 1: program received EXC_BAD_ACCCESS.**
[pool release];
return retVal;
}
What am i doing wrong?
You should copy your block when passing it to other method (such as attribute setter in your situation). So when setting the callback block do this:
[self.datePicker setOnDateChanged:[[myBlock copy] autorelease]];
You get the EXC_BAD_ACCESS cause block's variables used when creating the block don't get retained by the block itself. So when calling the block - variables do not exist anymore.
The accepted answer is wrong. You don't need to copy it in your MainViewController. Rather, the setOnDateChangedCallback: method which takes a block argument is responsible for copying it if it needs to store it in an instance variable (which I see it is doing, in the variable dateChangedCallback that is later used by another method). If dateChangedCallback is a synthesized property, you can accomplish this by declaring the property as copy instead of retain.
You can only update the UI from the UI thread. Since your block is running on another thread, you're getting the exception when updating the text of the textView. You can run code on the UI thread from within a block by using the main queue (dispatch_get_main_queue()).

instance variables not accessible

Serious Problem here... i'm getting ECX_BAD_ACCESS if i try to NSLog an instance variable of my custom object. Following Function is called in my ViewController, payload holds String Data which is pulled from a url.
- (void) initVcardWithData:(NSString *)payload {
NSLog(#"1. initVcardWithData");
aVCard = [[vcardItem alloc] initWithPayload:payload];
VCardViewController *aVCardViewController = [[VCardViewController alloc] initWithVCard:aVCard];
[self presentModalViewController:aVCardViewController animated:YES];
[aVCard release];
}
So far so good. The initWithWithVCard function is as follows, theVCard and theVCardN are defined in #implementation and also set as a #property (nonatomic, retain) in (.h).:
-(id)initWithVCard:(vcardItem *)aVCard {
if(self = [super init]) {
theVCard = [aVCard retain];
theVCardN = [theVCard.PersonName retain];
}
NSLog(#"---- vCardViewController :: initWithVcard :: FirstName: %#", theVCard.PersonName.FirstName);
return self;
}
If i access the theVCardN object in my ViewController aVCardViewController within ViewDidLoad everything works like a charm. I set some labels with data from that object.
If i then try to access the instance variables from theVCardN within a function which is called from an IBAction which is connected to a button in View, i get an EXC_BAD_ACCESS error at the debugger console. The Function which tries to pull data from the instance variables is as follows:
-(IBAction)addressbookButtonTapped {
NSLog(#"RETAIN COUNT FOR theVCard: %i", [theVCard retainCount]);
NSLog(#"RETAIN COUNT FOR theVCardN: %i", [theVCardN retainCount]);
NSLog(#"Save to Adressbook: %#", theVCardN.FirstName);
//[self dismissModalViewControllerAnimated:YES];
}
The RetainCounter for theVCardN right before calling NSLog outputs "1". The NSLog Line then returns EXC_BAD_ACCESS in Debugger Console.
Any idea ?
Do not call -retainCount. Absolute retain counts are useless.
retainCount returns the absolute retain count of an object. The actual value will be an implementation detail that is very often completely out of your control as the system frameworks may do any number of things internally to cause the retain count to be modified in ways you don't expect.
It is useless for debugging and their are a wealth of tools that are specifically focused on tracking down these kinds of issues.
First, if there is a crash, there is a backtrace. Post it. Probably not that interesting in this case, but, still, always look to the backtrace to at least confirm that it is crashing where/how you think it is.
From the evidence posted, it sounds like theVCardN.FirstName is either set to garbage or the underlying string has been over-released. Turn on zombie detection mode and see if that is the case. Since it is crashing on FirstName, then show the code related to creating/storing the FirstName.
Also, instance variables and methods should always start with a lowercase letter; PersonName should be personName & FirstName should be firstName.
Maybe i'm reading the code wrong or misunderstanding your class structure, but it looks like you logging:
NSLog(#"Save to Adressbook: %#", theVCardN.FirstName);
Above, where you say it is still working, you are logging:
theVCard.PersonName.FirstName
Are you missing the "PersonName"? Meaning you should be logging:
NSLog(#"Save to Adressbook: %#", theVCardN.PersonName.FirstName);

What is NSString in struct?

I've defined a struct and want to assign one of its values to a NSMutableDictionary. When I try, I get a EXC_BAD_ACCESS. Here is the code:
//in .h file
typedef struct {
NSString *valueOne;
NSString *valueTwo;
} myStruct;
myStruct aStruct;
//in .m file
- (void)viewDidLoad {
[super viewDidLoad];
aStruct.valueOne = #"firstValue";
}
//at some later time
[myDictionary setValue:aStruct.valueOne forKey:#"key1"]; //dies here with EXC_BAD_ACCESS
This is the output in debugger console:
(gdb) p aStruct.valueOne
$1 = (NSString *) 0xf41850
Is there a way to tell what the value of aStruct.valueOne is?
Since it is an NSString, why does the dictionary have such a problem with it?
------------- EDIT -------------
This edit is based on some comments below.
The problem appears to be in the struct memory allocation. I have no issues assigning the struct value to the dictionary in viewDidLoad, as mentioned in one of the comments. The problem is that later on, I run into an issue with the struct. Just before the error, I do:
po aStruct.oneValue
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00000000
0x9895cedb in objc_msgSend ()
The program being debugged was signaled while in a function called from GDB.
GDB has restored the context to what it was before the call.
To change this behavior use "set unwindonsignal off"
Evaluation of the expression containing the function (_NSPrintForDebugger) will be abandoned.
This occurs just before the EXC_BAD_ACCESS:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MM-dd-yy_HH-mm-ss-A"];
NSString *date = [formatter stringFromDate:[NSDate date]];
[formatter release];
aStruct.valueOne = date;
So the memory issue is most likely in my releasing of formatter. The date var has no retain. Should I instead be doing
NSString *date = [[formatter stringFromDate:[NSDate date]] retain];
Which does work but then I'm left with a memory leak.
I recreated your code and put the NSDictionary setValue method, right under the aStruct.valueOne = #"firstValue" line. It works perfectly without any error. So, your problem is not with the NSString, but with one of the objects (either aStruct or myDictionary) getting deallocated somewhere down the line. You can try the following:
static myStruct aStruct;
To print the value of aStruct.valueOne, you may use:
NSLog(#"aStruct.valueOne = %# \n", aStruct.valueOne);
Also, you can check the retain counts of myDictionary to see if it is still allocated. However, trying to check for the retain count of an already deallocated object will result in an error. But it will tell you in the error log, that the object is already deallocated.
NSLog(#"Retain Count of myDictionary = %i \n", myDictionary.retainCount);
Hope that helps.
Not sure why it's crashing, but instead of p, use po and it will print the contents of the NSString or description of any NS/CF object.
Try to enable zombies to check where do you over-release objects. Project -> Edit Active Executable -> Arguments tab -> Add variable NSZombieEnabled and assign it YES. (and set checkbox to YES).
Then you should get more info about your error in the trace.
Don't forget to disable NSZombieEnabled checkbox then.
EDIT:
When you assign a valueOne:
aStruct.valueOne = #"firstValue";
you actually create NSString object and put it into autorelease pool. So later when you try to get that object to pass it to your dictionary, it might be autoreleased already, that's why you are getting EXC_BAD_ACCESS. You have to implement some method which will do memory management for you when you assign new pointers to your struct. Something like this:
- (void)setValueOne:(NSString *)newValueOne {
[aStruct.valueOne autorelease];
aStruct.valueOne = [newValueOne retain];
}
So in your viewDidLoad you have to use your new method:
- (void)viewDidLoad {
[super viewDidLoad];
// make sure it is nil "on startup" because setValueOne: method will send autorelease method
aStruct.valueOne = nil;
aStruct.valueTwo = nil;
[self setValueOne:#"firstValue"];
}
Any 'class *instance' is a pointer to an object. That $1 = (NSString *) 0xf41850 you see is actually the pointer to the memory space that is currently allocated to hold valueOne. The issue usually associated with EXEC BAD ACCESS is that the memory space is not permanently allocated to hold valueOne, and is reclaimed later on, usually as soon as the method finishes execution (called garbage collection). Then, when you later try to access it, like from a different method or even the same method but on a subsequent execution, the system says 'hey, that memory address is used for something else", it throws the Exec Bad Access error.
Is there a way to tell what the value
of aStruct.valueOne is?
Well, the debugger, at the moment you establish the value, should be able to pick up on the definition and show you the literal value; it should know that the memory space at 0xf41850 maps to an NSString class, which is an array of bytes of some length, and that the bytes at that address are encoded a certain way, and thus should map into some string that can be displayed on your display in the debugger. However, later on, no, the system has no (valid) idea of what that space contains, since it could contain, well, anything.
So, when you run into EXEC BAD ACCESS, it means that you are not retaining that value for long enough period, either because you have not purposely retained it, or have released it (on purpose or inadvertently let the system release it).