I'm a beginner to XCode.
Below is my code. I want to add an object to a mutablearray. From the debugger window I can see there is one object added to the array "words". I can also see the property "flag" of that object is "NO". The problem is another property "str" is shown as "out of scope".
Can anyone help me with this issue? Thanks a loooooot! Stucked on this one for the whole afternoon.
NSMutableArray * words=[[NSMutableArray alloc] initWithCapacity:numberOfWords];
Word *w=[[Word alloc] init];
[w setStr:#"abc" flag:NO];
[words addObject: w];
[w release];
--
#interface Word : NSObject{
NSString *str;
BOOL flag;
}
-(void) setStr: (NSString *) s flag:(BOOL) b
{
self.str=s;
flag=b;
}
Do you have a property declaration for your string? Are you retaining the string you are setting?
Still AFAIK 'out of scope' does not necessarily mean it was not set or that nothing has been set. Try an NSLog of the value or something. You might find that there is nothing wrong.
Have a look at this question that talks about scope in GDB:
Objective-C: instance variables out of scope in debugger
Your problem is that the string #"abc" is a temporary object who's scope only exists during the [w setStr:#"abc" flag:NO] method call. You should be able to resolve this problem by making str a #property of Word:
#interface Word : NSObject{
NSString *str;
BOOL flag;
}
#property (retain) NSString* str;
#end
And in your implementation file
#implementation Word
#synthesize str;
-(void) setStr: (NSString *) s flag:(BOOL) b
{
self.str=s;
flag=b;
}
#end
Related
I tried initializing the array :
In .h file
#property (nonatomic, retain) NSArray *accounts;
In .m file :
#synthesize accounts;
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *arrList = [acAccountStore accountsWithAccountType:accountType];
// This returns array
self.accounts = [NSArray arrayWithArray:arrList]; // I tried debug after
// this and it gives me data in debugger.
// Note array List have 3 data in it.
}
Now On button click i call a method:
- (IBAction) ButtonClicked :(id) sender {
NSLog(#" data : %#",[self.accounts objectAtIndex:0]); // Breaks at this point.
// When i tried with debug it gives me (no Objective-C description available)
}
Is the initialization of array correct Or If the code is not right please let me know.
Main concern is when i do debug in viewDidLoad, the self.accounts show me proper values. But after doing the click event its empty and throws EXEC_BAD_ACCESS error.
Thanks for help in advance
hm looks fine. A couple of questions then:
Where are you calling the self.accounts = [NSArray arrayWithArray:arrList];
I assume that the array is being setup before your button is being pressed?
There's no real reason that arc should be clearing out the variable. Have you set a strong reference to it or a weak one? If you're using self. on a variable, you should have :
#property (nonatomic, strong) NSArray *accounts;
or similar to that in the .h file and then
#synthesize accounts;
in the .m file.
If you've got weak instead of strong then ARC may possibly clear the memory but it still shouldn't.
Update:
Create a property for your account store as well. I had this exact issue recently and this fixed it.
#property (nonatomic, strong) ACAccountStore *accountStore;
Original Answer
Because you're using ARC, you need to change your property declaration from
#property (nonatomic, retain) NSArray *accounts;
to:
#property (nonatomic, strong) NSArray *accounts;
With the latest LLVM compiler, you don't need to synthesize properties either. So you can remove #synthesize accounts.
You should always use defensive coding as well, so in your - buttonClicked: method, you should do:
- (IBAction)buttonClicked:(id)sender {
if (self.accounts) {
NSLog(#"data: %#", [self.accounts objectAtIndex:0]);
}
}
This makes sure that the pointer to the array is valid.
You can also check to make sure an item in an array exists before trying to read it by doing:
- (IBAction)buttonClicked:(id)sender {
if (self.accounts.count > 0)
NSLog(#"data: %#", [self.accounts objectAtIndex:0]);
}
}
I have a simple Answer class that looks like this:
#interface Answer : NSObject {
NSString *_text;
NSNumber *_votes;
}
#property(nonatomic, retain) NSString *text;
#property(nonatomic, retain) NSNumber *votes;
+(id)initFromAnswerData:(NSSet *)data;
-(id)initWithText:(NSString *)answer;
#end
The implementation looks like this:
#import "Answer.h"
#import "AnswerData.h"
#import "AppDelegate.h"
#implementation Answer
#synthesize text = _text;
#synthesize votes = _votes;
-(id)initWithText:(NSString *)answer {
if( (self=[super init])) {
_text = answer;
_votes = 0;
}
return self;
}
#end
If I create an array of Answers in a view controller using the initWithText: method I inevitably have EXC_BAD_ACCESS errors when I take an Answer in the array and try to find it's text value.
However if I initialize a new Answer, set the text value and then add it to the array I don't have this access issue.
So this causes problems down the line:
[arrayOfAnswers addObject:[[Answer alloc] initWithText:#"Hello"]];
But this doesn't:
Answer *newAnswer = [[Answer alloc] initWithText:nil];
newAnswer.text = #"Hello";
[arrayOfAnswers addObject:newAnswer];
Can anyone explain why?
You're using the attribute _text and _votes directly but not their setters.
So, you're not retaining the input parameter answer for the line
_text = answer;
You should either change to
_text = [answer retain];
or
self.text = answer;
Are you retaining the array that you put your Answers into? That would be my guess at what's wrong.
as you see , your
#property(nonatomic, retain) NSString *text; // this property is retain.
so the setter method of this should be- (void) setText:(NSString*)text{
[_text release];
_text = text;
[_text retain];
so when you call newAnswer.text = #"hello" ,it works, newAnswer holds the text.
but in your initWithText, there's no retain symbol, so sucks.
I have implemented the following code to assign NSMutableArray to a property -
NSMutableArray * anArray = [responseDictionary valueForKeyPath:#"tags"];
NSLog(#"The array length is=%d",[anArray count]);
for (NSString *s in anArray) {
NSLog(#"you are %#", s);
}
[self setActiveTagArray:anArray];
It prints out the string values fine. But in the setter function, if I place a breakpoint I see that it shows there are two objects but they are "Out of Scope". What does this mean? What am I doing wrong? My getter also does not fetch any values. The property functions -
-(void)setActiveTagArray:(NSMutableArray *)tags
{
activeTagArray = [[NSMutableArray alloc] init];
activeTagArray = tags;
//NSLog(#"%#",[activeTagArray count]);
}
-(NSMutableArray *)getActiveTagArray
{
return activeTagArray;
}
Is activeTagArray a class variable as well as a property. Consider using _activeTagArray as the class variable name. And then in the .m file just use #synthesize activeTagArray = _activeTagArray;, and for get the second two methods completely.
Response to comment:
You said "I have implemented the following code to assign NSMutableArray to a property". I took this to mean you have "#property (nonatomic, retain) NSMutableArray *activeTagArray;" in your .h file. If this is the case then you would access it thru otherObject'sNameForYourClassHere.activeTagArray.
#synthesize create accessors & mutators for you.
I have a doubt about initializing string with synthesize keyword.
In my Event.h class I have
#interface Event : NSObject {
NSString *title;
}
#property (nonatomic, retain) NSString *title;
and in Event.h I have
#synthesize title;
However when I want to set the title from my main class and I display the content in the console, I get null:
[self.currentEvent.title stringByAppendingString:#"hello"];
NSLog(#"%#", self.currentEvent.title); //this is null
Is because I don't properly initialize the title variable in Event? Isn't synthesize initializing it for me?
[self.currentEvent.title stringByAppendingString:#"hello"];
You call stringByAppendingString: on a null object (since it was never initialized), so it doesn't do anything. Plus, even if it were to return something, you're not storing the return value anywhere.
if(self.currentEvent.title==nil){
self.currentEvent.title = #"hello";
}
else{
self.currentEvent.title = [self.currentEvent.title stringByAppendingString:#"hello"];
}
#synthesize creates the setter and getter methods for you, but does not initialize
Fastest way to get up to speed with this stuff is to watch "Developing Apps for iOS" by Paul Hegarty / Stanford University, available free on iTunes.
You are not storing the result of your call into a variable. I also suggest using this method since it's a little bit cleaner because you do not need to have an if statement.
[self setTitle:[NSString stringWithFormat:#"hello %#", [self title]]];
I have an Address interface as this:
#interface AddressCard : NSObject
{
NSString *name;
NSString *email;
}
#property (copy, nonatomic) NSString *name, *email;
-(void) print;
-(void) setName:(NSString *) theName andEmail:(NSString *) theEmail;
-(void) dealloc;
#end
And implementation as:
#import "AddressCard.h"
#implementation AddressCard
#synthesize name, email;
-(void) setName:(NSString *) theName andEmail: (NSString *) theEmail
{
self.name = theName;
self.email = theEmail;
}
-(void) print
{
NSLog (#"==============================");
NSLog(#"| %-21s |", [self.name UTF8String]);
NSLog(#"| %-21s |", [self.email UTF8String]);
NSLog (#"==============================");
}
-(void) dealloc
{
[name release];
[email release];
[super dealloc];
}
#end
When I run it I keep getting an EXEC_BAD_ACCESS during the pool drain. I'm unable to find the cause and any help is appreciated. This is my first step into Objective-C so please bear with me.
thanks
Sunit
Since the error occurs when draining the pool, I might be suspicious that you've already deallocated the object by that point, and the object is over-released (although generally you'll get a "malloc double free" error for this) or perhaps the memory has already been overwritten by something else. I'd suggest running it with zombies enabled, as in this answer — if you have Snow Leopard you can use the Zombies tool in Instruments from Xcode's Run menu. Good luck!
That example looks quite familiar - I just worked through that book myself! The code you've posted above is fine, so the problem must be elsewhere. You might try checking out the author's forum - the source code for each of the steps for that chapter is posted there.
As others have suggested, you might want to look for extra 'release' calls.
Since you are releasing the strings in your dealloc method it would appear that your AddressCard object assumes ownership of the strings but you use this line to define the properites:
#property (copy, nonatomic) NSString *name, *email;
Using copy means that your object is not retaining the strings. Try changing that line to this:
#property (retain, nonatomic) NSString *name, *email;
Using retain means that your object will retain the strings until you release them in your dealloc.
Hopefully that will solve the problem.