Properties are initiated with an invalid address - iphone

I have en error that I suspect could be the compiler... I'm not an expert myself, but I checked some other code with the exact same behavior with an expert and we couldn't figure it out.
I setup a property as such:
#interface aViewController ()
#property (nonatomic, strong) NSArray *listOfTitles;
#end
#implementation aViewController
#synthesize listOfTitles = _listOfTitles;
- (NSArray *)listOfTitles
{
if (!_listOfTitles)
_listOfTitles = [NSArray arrayWithObjects:#"first", #"second", #"third", #"fourth", nil];
return _listOfTitles;
}
However, the app crashes (the array would be more complex and serve to setup textLabel.text properties on UITableViewCell).
What's bothering me, it's that the NSArray always have an invalid address (0x00000001). What am I missing? Isn't this the proper way to do lazy instantiating?
Like I mentionned, I experienced the exact same thing (property instantiated with 0x00000001 ) with other classes, in other projects. That's why I'm suspecting the compiler to be the issue. But really, I'm all ears for solutions!...

The most obvious solution is to set the ivar to nil in your init function.
-(id)init{
if (self = [super init]){
_listOfTitles = nil;
}
}
The real question is why isn't this being done for you, since all ivars should be initialized to nil. I suspect it has something to do with the property being declared in the .m file. Either way it will cause no harm to nil out the ivar yourself.

Related

getting EXC_BAD_ACCESS_CODE, objective C

What I am doing is
//ClassB.h
#property (strong, nonatomic) NSString *name;
and
//ClassA.h
#interface ClassA : NSObject
+(ClassA*)methodA:(NSData*)data;
-(id)initWithData:(NSData*)data;
#property (nonatomic, strong) NSMutableArray *arr;
#property (nonatomic, strong) RXMLElement *rxmlRoot;
#end
//ClassA.m
#implementation ClassA
#synthesize arr;
#synthesize rxmlRoot;
+(ClassA*)methodA:(NSData*)data {
return [[ClassA alloc] initWithData:data];
}
-(id)initWithData:(NSData*)data {
self = [super init];
if (self) {
arr = [NSMutableArray array];
rxmlRoot = [RXMLElement elementFromXMLData:data];
/*****edit : just been added to make codes clear*****/
NSString *node = #"players.player";
[rxmlRoot iterate:node with:^(RXMLElement *e){
ClassB *classB = [[[ClassB alloc] init] autorelease];
[classB setName: [e attribute:#"name"]];
// adding ClassB into arr
[arr addObject:classB];
}];
}
return self;
}
#end
So now I am having ClassA object whose arr contains ClassB
Question : later on, when I try to access an particular property of ClassB like
((ClassB*)[classA.arr objectAtIndex:0]).name
and I am getting EXC_BAD_ACCESS at above line..
Please advice me on this issue and how to correct the error. Any comments are welcomed here
Thanks
This line
[arr addObject:ClassB]
makes no sense. Is your intention to put an instance of ClassB into that array, or the class itself (i.e. [ClassB class])? Presumably you must intend to put an instance of ClassB in there, otherwise trying to access its properties later on (e.g. firstName) would make no sense. Also, does your ClassB even have a firstName property, because the piece of ClassB's interface that you show us only mentions a name property.
Update:
Since you are using manual memory management, you need to retain the objects (arr, rxmlRoot) you create in your initializer using convenience constructors, which return autoreleased objects. For example, the code should be
arr = [[NSMutableArray array] retain];
Post your ClassB.m .
Are you making the #synthesize name?
Also make the Alloc for arr.
This line is so wrong:
((ClassB*)[classA.arr objectAtIndex:0]).firstName
Your string is called name , not firstName. It should be :
((ClassB*)[classA.arr objectAtIndex:0]).name
The code in the question has changed substantially, so my previous answer now makes no sense and I have removed it. Given revised code, the first thing to do is to log what's going on.
NSLog(#"classA: %#", classA);
NSLog(#"classA.arr: %#", classA.arr);
((ClassB*)[classA.arr objectAtIndex:0]).name
If it blows up on the first log statement, things are really bad. But then at least you know that classA is pointing to something rotten and you can work back from there.
You can achieve the same thing in the debugger, by setting a break point ahead of the line and inspecting. Given that you are getting an EXC_BAD_ACCESS one of the pointers is pointing to a dodgy object, e.g. one that has been released. It looks as if you are using ARC (because you have strong in your property), which should help manage the memory - but then again, you have an autorelease in there, so maybe not.

iPhone Properties

I a few simple questions to make sure I am using properties right in my application. I read a lot online but it is still unclear. Thanks a lot for any help or suggestions.
(1) I am not quite sure that the statement does, and why is it needed.
#synthesize personName = _personName;
Why do you need the _personName variable? What is the benefit of doing that as opposed to just creating a property and synthesizing that variable personName.
#property (nonatomic, retain) NSString *personName;
(2) In my application should I be accessing the property variable self.personName or use the _personName variable. I believe the self.personName is correct by then again why is the _personName even there?
(3) Also I am a little confused to which variable I should release in dealloc() and which variable should I set to nil in viewDidLoad(). I also do not know if any changes should be made to the didReceiveMemoryWarning() method.
#interface ViewController : UIViewController
{
NSString *_personName;
}
#property (nonatomic, retain) NSString *personName;
#end
#implementation ViewController
#synthesize personName = _personName;
- (void)viewDidLoad
{
[super viewDidLoad];
self.personName = [[NSString alloc] initWithString:#"John Doe"];
NSLog(#"Name = %#", self.personName);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void)dealloc
{
[super dealloc];
}
#end
#synthesize personName = _personName;
That statement creates the accessor methods for the personName property. You've specified that the accessors should use an instance variable named _personName. If you just had #synthesize personName;, the accessors would use personName as the instance variable instead.
You should usually use the accessor methods, as in self.personName or somePerson.personName or somePerson.personName = #"Joe";. If you don't care what the name of the ivar that backs up the personName property, you don't need to specify it.
Use the accessors in -viewDidLoad, as in: self.personName = nil;. Same for -didReceiveMemoryWarning:. Whether to use the ivar or property in -dealloc is debatable, and to some degree a matter of taste. The main concern with using the property accessors in -dealloc is that it can cause problems if your class is subclassed and the accessors are overridden. Often, you don't need to worry about that because you know that your class won't be subclassed.
Setting an ivar to nil after releasing is also debatable. Many people feel that it's good style to do so, others feel like it's a waste of time. Use your best judgement. It's certainly not necessary, but rather something that some feel is a matter of good housekeeping.

When needing to reference an NSString later that was passed to a function in a class, what is the proper way? (iPhone dev)

In this example:
#interface something : something
{
NSString *saveString;
}
-(void)saveStringForLater:(NSString*)myString
{
//do stuff with myString
...
//then save it for later
saveString = myString;
}
-(void)someOtherTimeInFuture
{
//do stuff with saveString
...
}
So given the above, my questions are:
1) Is this safe/proper way of doing this?
2) Will I need to worry about releasing saveString?
3) Should I be copying the string instead of just saving the pointer?
Excuse my ignorance as I am fairly new to Obj-C but have a C++ and C# background.
Thanks!
This is what #properties are for. They manage getter and setter code for you, so you don't have to think about these questions.
.h
#interface MyClass : NSObject
{
NSString *myString;
}
#property (nonatomic, retain) NSString *myString;
#end
.m
#implementation MyClass
#synthesize myString;
-(void)dealloc
{
[myString release];
[super dealloc];
}
#end
With those things in place, you can now talk about self.myString and not worry about memory. When you assign to it it'll do a retain. If you assign again, it'll release the first object and retain the new one. And then it'll stick around retained until your viewcontroller unloads.
You can by all means accomplish this same end with an iVar (which is what you're doing in your code sample), but then memory management is yours to handle, and it can be a bit fiddly. Best to use the #property system to create appropriately memory-managing setter code.
You have 3 optins,
Copy - should be using if the string can change or when getting called from a code you have on control of like third party
Retain - will increase the reference count to the object and will prevent destruction of it
In both these options you have to release it when you done with it
Last you can define a property with retain,copy attribute - this will let the system worry about managing it and probably the best option in most cases

Crash when accessing a NSMutableArray member variable

I'm having some trouble with a NSMutableArray. I'm sure i'm doing something wrong with the allocation of the NSMutableArray but it's not obvious to me being an iPhone newbie. When i run the code below i can add the object MyObject to the array objects_ and set the name etc. The NSLog displays the correct data.
But when i try to access the objects_ member from the function printObject i get a SIGABRT. Looks like the memory has been deallocated or something?
Any help appreciated.
#interface MyObject : NSObject {
NSString *name;
}
-(void) SetName:(NSString*) name_str;
-(NSString*) GetName;
#end
#interface ObjectListViewController : UITableViewController {
NSMutableArray* objects_;
}
-(void) initTableData;
#end
#implementation ObjectListViewController
- (void)initTableData {
objects_ = [[NSMutableArray alloc] initWithCapacity:10];
MyObject *obj = [MyObject alloc];
[obj SetName:#"Test"];
[objects_ addObject:obj];
MyObject* testObj = (MyObject*)[objects_ objectAtIndex:0];
NSLog([testObj GetName]);
}
- (void)printObject {
MyObject* testObj = (MyObject*)[objects_ objectAtIndex:0];
NSLog([testObj GetName]);
}
We can eliminate the lack of an init call on MyObject as the cause of the crash as in this case it will be benign. Calling init on NSObject will just return self, so calling it in this case won't change the behaviour. So I don't think the first two answers here will make any difference:
An object isn’t ready to be used until it has been initialized. The init method defined in the NSObject class does no initialization; it simply returns self.
Chuck correctly points out that init is a fundamental step in object allocation and initialization and you should be calling it when you allocate MyObject.
I am not sure the third answer is correct either. I don't really see how adding synthesise on the objects_ array will make any difference. You haven't defined it as a property, and I don't really see why you would need to, given it is just data internal to the class.
The comment on the question Well, for starters, you never define printObject in the #interface. from eykanal doesn't really help you either, because you must be calling printObject internally, otherwise you wouldn't be hitting the crash.
Reading the through the code, I can't see an obvious error. The retain count on objects_ after initTableData finishes should be one, the retain count on the instance of MyObject should also be one. So I think there must be some other code that is releasing objects_ elsewhere?
I am assuming it is crashing on the objectAtIndex call? Is there any info in the console? What does the call stack look like?
MyObject *obj = [MyObject alloc];
should be:
MyObject *obj = [[MyObject alloc] init];
#interface ObjectListViewController : UITableViewController {
NSMutableArray* objects_;
}
#property (nonatomic, retain) NSMutableArray *objects_;
-(void) initTableData;
-(void) printObject;
#end
add the synthesize in the implementation
#implementation ObjectListViewController
#synthesize objects_;
Here are some issues in your code:
You never initialise your MyObj object. Although it inherits directly from NSObject and NSObject is documented to do nothing except return self, you never know if other stuff happens behind the scenes, so put it in just to eliminate the posssibility.
Your methods don't follow the normal naming conventions. method names should begin with a lower case letter and "get" should only be used when passing back data by reference through the parameters as in e.g. NSData -getBytes:length:. Your getter and setter should be -name and -setName: respectively. This may seem like a minor nitpick, but it'll help you later on if you start to use KVO and KVC.
Never do NSLog(someStringVariable) always NSLog(#"%#", someStringVariable). As you have it now, if the object's name contains a percent formatting sequence e.g. %#, %d, %s etc, your program will crash on the NSLog. However, this is not the cause of your current problem - it would be crashing on the NSLog in -initTableData
you don't need to cast the result of -objectAtIndex:
Having said all that, I can't see anything that would cause the particular issue you have. It may be that the getter or setter for the name in MyObject is incorrect. Please post them.

What are Setters and Getters?

I don't really have a solid understanding of Setters and Getters for objective-c. Can someone provide a good guide for beginners? I noticed that this comes into play when trying to access variables in another class, which I am trying to do right now. I have two classes, lets say A and B. I have a NSString variable in A with the #property (retain) NSString *variable. Then I go ahead and synthesize it. Now when the view loads in the class I set the value for the variable to "hello". Now what I want to do is access the string from class B. I have imported the the class A, and initialized it with this code:
AClass *class = [[AClass alloc] init];
NSLog(#"Value:%#", class.variable);
[class release];
However in the debugger it returns a value of "(null)", which I don't really understand. If someone could lead me into the right path I would greatly appreciate it.
Thanks,
Kevin
The particular section of interest to you is Declared Properties.
b's interface should look like:
#interface b : NSObject {
NSString *value;
}
#property (nonatomic, retain) NSString *value;
- (id) initWithValue:(NSString *)newValue;
#end
Your implementation of b should look something like:
#implementation b
#synthesize value;
- (id) initWithValue:(NSString *)newValue {
if (self != [super init])
return nil;
self.value = newValue;
return self;
}
#end
Which you could then call like:
b *test = [[b alloc] initWithValue:#"Test!"];
NSLog(#"%#", test.value);
The Getting Started with iOS guide in the iOS Reference Library outlines the reading material you should go through to nail down basics like this. Apple's guides are clearly written and thorough, and you'll be doing yourself a huge favor by hunkering down and just reading them.