Why is NSMutableArray showing count size of 0? - objective-c

Very confused here...
I have a NSObject subclass called "Section" with a NSMutableArray property called "content"
Section *sectionName = [[Section alloc] init];
[[sectionName content] addObject:#"test"];
[[sectionName content] addObject:#"test2"];
[[sectionName content] addObject:#"test3"];
NSLog(#"COUNT IS %i", [[sectionName content] count]);
Why is my NSLOG showing "COUNT IS 0"??

Are you initializing content in your subclass? If not, that can be the problem!
Your init method should look like this:
- (id)init
{
if (self = [super init])
{
_content = [[NSMutableArray alloc] init];
}
return self;
}
If you're not using ARC your dealloc should look like this:
- (void)dealloc
{
[_content release];
[super dealloc];
}

Are you initializing array content inside Section? are you doing something like - content = [[NSMutableArray alloc] init]; ?
Lemme know if this helps.

You probably need to allocate your NSMutableArray -- that is normally what causes this issue.
In your Section.m:
- (id) init {
//...
content = [[NSMutableArray alloc] init];
//...
}

Related

nsmutabledictionary returning null when accessed outside of class

I have searched around a bit and not found an answer to my question. I am a beginner to objective-c and I am currently experimenting around with dictionaries. I have a class called "SETestBank" that creates 3 dictionaries of images and then adds them to a large dictionary. I am doing it this way because down the line I may add more smaller dictionaries. I've created a specific "accessBank" method to pull objects out via other classes.
SETestBank.m
#import "SETestBank.h"
#implementation SETestBank
#synthesize mathBankA, mathBankB, mathBankC, mathTest;
- (id)init
{
[self createBankA];
[self createBankB];
[self createBankC];
[self createTest];
return 0;
}
- (NSMutableDictionary *)createBankA
{
mathBankA = [[NSMutableDictionary alloc] init];
for (int i=0; i < 11; i++) {
NSString *aKey = [NSString stringWithFormat:#"%da", i];
NSString* imageName = [NSString stringWithFormat:#"%da.png",i];
[mathBankA setObject:imageName forKey:aKey];
NSLog(#"%#", aKey);
}
return mathBankA;
}
//same occurs to generate bankB and bankC
- (NSMutableDictionary *)createTest
{
mathTest = [[NSMutableDictionary alloc] init];
[mathTest addEntriesFromDictionary:mathBankA];
[mathTest addEntriesFromDictionary:mathBankB];
[mathTest addEntriesFromDictionary:mathBankC];
return mathTest;
}
- (NSString *)accessBank:(NSString *)accessor
{
NSString *img = [mathTest objectForKey:accessor];
return img;
}
#end
now this code seems to work fine. The dictionaries are created and console logs display the correct keys and object filenames (the images are all in the project and properly named)
However, when I access it in my view controller and try to apply an image to a UIImageView I get nothing.
SEViewController:
- (void)viewDidLoad
{
SETestBank *mathTest = [[SETestBank alloc] init];
UIImage *img = [UIImage imageNamed:[mathTest accessBank:#"1a"]];
NSString *test = [mathTest accessBank:#"1a"];
NSLog(#"%#", test);
[imageView setImage:img];
[self.view addSubview:imageView];
[super viewDidLoad];
}
the log here simply returns null along with a "CUICatalog: Invalid asset name supplied: (null), or invalid scale factor: 1.000000" error which I gather is from trying to assign null to an image. I'm stumped on this one. If I hardcode the image to display "1a.png" rather than trying to access it by key it works fine but that is not what I'm trying to accomplish. imageView is connected to a UIImageView in storyboard and the view controller is set to use SEViewController as it's class.
Thanks for any help!
In the init method, you return a 0, which means nothing (nil)
- (id)init
{
[self createBankA];
[self createBankB];
[self createBankC];
[self createTest];
return 0;
}
Change this to
- (id)init
{
if (self = [super init]) {
[self createBankA];
[self createBankB];
[self createBankC];
[self createTest];
}
return self;
}
may solve your problem.
Your init in SETestBank is returning 0, so your mathTest object is nil when you do
SETestBank *mathTest = [[SETestBank alloc] init];

Set NSMutableArray to the new NSMutableArray

#implementation RightViewController{
NSMutableArray * tableArray;
}
#synthesize tableView;
- (void)viewDidLoad {
[super viewDidLoad];
tableArray = [[NSMutableArray alloc] init];
}
- (void)refreshTable: (NSMutableArray*)resultsArray{
[tableArray setArray:resultsArray];
NSLog(#"resultsArray : %d : %d", [tableArray count] , [resultsArray count]);
[self.tableView reloadData];
}
It shows me : resultsArray : 0 : 78
Why can't I set information to this array?
I do call refreshTable from another controller like this:
[[[RightViewController alloc] init] refreshTable:resultsArray];
Updated:
tableArray = [NSMutableArray arrayWithArray:resultsArray];
worked for me.
After that i do
- (IBAction)reloadTableButton:(id)sender {
[self refreshTable:tableArray];
}
and it's shows me : resultsArray : 0 : 0
Why is tableArray array empty?
Try setting your tableArray variable like so :
tableArray = [NSMutableArray arrayWithArray:resultsArray];
You might not be retaining your mutable array I would suggest making a #property for your tableArray. Place this before your #synthesize
#property (retain, nonatomic) NSMutableArray *tableArray;
Option 1:
- (void)viewDidLoad {
[super viewDidLoad];
//don't do anything with the array here!
//refreshTable may well be called before the view is loaded
}
- (void)refreshTable: (NSMutableArray*)resultsArray{
if (!self.tableArray) // if it does not exist, then create it on the fly.
self.tableArray = [[NSMutableArray alloc] init];
[tableArray setArray:resultsArray];
[self.tableView reloadData];
}
Option 2:
- (MyClass*) init {
self = [super init];
if (self) {
self.tableArray = [[NSMutableArray alloc] init];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
//don't do anything with the array here!
}
- (void)refreshTable: (NSMutableArray*)resultsArray{
[tableArray setArray:resultsArray]; // you can be sure that init was invoked earlier.
[self.tableView reloadData];
}
Option 3:
- (void)viewDidLoad {
[super viewDidLoad];
//don't do anything with the array here!
}
- (void)refreshTable: (NSMutableArray*)resultsArray{
self.tableArray = [NSMutalbeArray arrayWithArray:resultsArray]; //This creates a new array as a copy of resultsArray and assigns it to tableArray. No need to initialize anything.
[self.tableView reloadData];
}
i believe it should work
RightViewController *controller = [[RightViewController alloc] init];
[controller refreshTable:resultsArray];
#implementation RightViewController{
NSMutableArray * tableArray;
}
#property (strong, nonatomic) NSMutableArray *tableArray; //use the keyword "retain" instead of "strong" in below iOS 5
#synthesize tableView;
#synthesize tableArray;
- (void)viewDidLoad {
[super viewDidLoad];
self.tableArray = [[NSMutableArray alloc] init];
}
- (void)refreshTable: (NSMutableArray*)resultsArray{
self.tableArray = resultsArray;
NSLog(#"resultsArray : %d : %d", [tableArray count] , [resultsArray count]);
[self.tableView reloadData];
}

Memory leak in objective-c class init method

I'm having problems with a leak in the init method of a class I have created. To keep it simple, I have the following (simplified) problem:
ViewController initialises an instance of
ClipData class which initialises an instance of
AnimationData class which initialise a string
ViewController:
myClipData = [[ClipData alloc] init];
ClipData:
- (id)init
{
self = [super init];
if (self) {
animData = [[AnimationData alloc] init]; //LEAK HERE
}
return self;
}
AnimationData:
- (id)init
{
self = [super init];
if (self) {
name = [NSString string];
}
return self;
}
All the objects in the classes are declared as (nonatomic, retain). I'm aware that doing this bumps up the retain count, but how do I initialise the AnimationData without leaking the animData???
Probably a very stupid question, so any help much appreciated.
Thanks,
Duncs
You are never releasing the animData. You need to add dealloc to your class:
- (void)dealloc {
[animData release];
[super dealloc];
}
Similarly, you need to add a similar dealloc to AnimationData.
On a related note, you need to retain and later release the string created in -[AnimationData init], what you are doing right now is essentially a noop, except that it leaves behind a garbled pointer.
When you have an alloc you must also have a release.
You should also reference the properties through self so you access the properties rather than the underlying members.
So you should really do :
ClipData *clip = [[ClipData alloc] init];
self.myClipData = clip;
[clip release];
And
if (self) {
AnimationData *data = [[AnimationData alloc] init];
self.animData = data;
[data release];
}
Make sure you also release the properties in the dealloc of the class by setting them to nil.
self.myClipData = nil;
self.animData = nil;

How do I add another object to my singleton code?

Here is my singleton code:
#synthesize listOfSites;
+ (id)sharedInstance
{
static dispatch_once_t dispatchOncePredicate = 0;
__strong static id _sharedObject = nil;
dispatch_once(&dispatchOncePredicate, ^{
_sharedObject = [[self alloc] init];
});
return _sharedObject;
}
-(id)init
{
self = [super init];
if (self) {
listOfSites = [[NSMutableArray alloc] init];
}
return self;
}
#end
It's pretty much textbook... however, I want to add another array, similiar to "listOfSites" (call it "listOfReadings"). The code that says "if (self)" confuses me.
How do I add another array to this code?
if (self) { does nothing but to verify that the [super init] has worked - and that it hasn't return NULL or anything...
Other than that, you can do this normally, like :
declare a listOfReadings array (as an ivar/property?)
set it up
listOfReadings = [[NSMutableArray alloc] init];
or
listOfReadings = [[NSMutableArray alloc] initWithObjects:nil];
or (if it's a property)
[self setListOfReadings:[[NSMutableArray alloc] initWithObjects:nil]];
Example :
-(id) init {
self = [super init];
if (self) {
listOfSites = [[NSMutableArray alloc] init];
listOfReadings = [[NSMutableArray alloc] init];
}
return self;
}
after having declared the new NSMutableArray in your .h file :
NSMutableArray* listOfReadings;
-(id) init {
self = [super init];
if (self) {
listOfSites = [[NSMutableArray alloc] init];
listOfReadings = [[NSMutableArray alloc] init];
}
return self;
}
if (self) in other words means "If current object is successfully created then..."

Finding the cause of EXC_BAD_ACCESS

I have a class with the following init method:
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
StateStack* s = [[StateStack alloc] init];
state = s;
[s push:NONE]; //<--EXC_BAD_ACCESS on load here
[s release];
}
return self;
}
And StateStack has the following init code:
- (id)init {
self = [super init];
if (self) {
NSMutableArray* s = [[NSMutableArray alloc] init];
stack = s;
[s release];
NSLog(#"%d",[stack retainCount]);
}
return self;
}
Oddly, if I remove the NSLog line, the EXC_BAD_ACCESS moves to StateStack's dealloc method:
- (void)dealloc {
[stack release]; //<--EXC_BAD_ACCESS
[super dealloc];
}
Searching around seems to suggest that EXC_BAD_ACCESS is caused by overreleasing, but I can't see how I've overreleased anything. Does anyone know what the cause might be?
In your init function:
StateStack* s = [[StateStack alloc] init];
state = s;
[s push:NONE]; //<--EXC_BAD_ACCESS on load here
[s release];
you are allocating an instance of StateStack; this gets a retain count of 1. Then at the end of the function you call release, retain count goes to 0 and the object is ready to be released. So, when later dealloc is executed, the state ivar is sent another release and that is causing the bad access. You don't need to release s, since you want that state be retained. The same error pattern occurs in the other init method.
This would be correct:
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
StateStack* s = [[StateStack alloc] init];
state = s;
[s push:NONE]; //<--EXC_BAD_ACCESS on load here
}
return self;
}
- (id)init {
self = [super init];
if (self) {
NSMutableArray* s = [[NSMutableArray alloc] init];
stack = s;
}
return self;
}
NB: I don't want to generate misunderstandings. Using retain count to check for correct memory allocation is useless. This is true. Anyway, reasoning in terms of retain count helps understanding what happens when you allocate/release/autorelease an object. It is the basic mechanism, but it is too difficult to track it usage to check for correctness of memory management.
state = s is not copying the NSMutableArray object, it's just copying the pointer to it. So when you call [s release] the object referred to by both s and state is deallocated. You'll get an EXC_BAD_ACCESS whenever you use either from that point on.
Also, don't use [object retainCount] to debug memory management problems. It lies. Google NSZombies.
- (id)init{
self = [super init];
if (self) {
// Initialization code here.
state = [[StateStack alloc] init];
[state push:NONE];
}
return self;
}
StateStack
- (id)init {
self = [super init];
if (self) {
stack = [[NSMutableArray alloc] init];
}
return self;
}