Array Count is 0 after adding an element? - objective-c

I'm using the code below to add an Object of my Platform class (basic storage class, subclass of NSObject) to an NSMutableArray.
But the NSLog statement outputs 0.
How can this happen?
Platform *platform = [Platform platformWithLabel:label identifier:identfier];
[self.platforms addObject:platform];
NSLog(#"%i", [self.platforms count]);
This is the creation method of Platform:
+(Platform *)platformWithLabel:(NSString *)label identifier:(int)identifier
{
Platform *platform = [[Platform alloc] init];
platform.label = label;
platform.identifier = identifier;
return platform;
}
I'm using ARC. This is how I declare my platforms array:
#property (strong, nonatomic) NSMutableArray *platforms;

Probably you are forgetting to initialize the NSMutableArray itself. Check and make sure you're doing so.

Most likely you're not initializing your self.platforms array.

Don't forget to initializing the NSMutableArray :)
platforms = [[NSMutableArray alloc] init];

Related

Initializer element is not a compile time constant

Using objective-c to write a program. I'm getting an error (initializer element is not a compile-time constant) and am not sure I follow why it's occurring. I'm just trying to initialize an array. I'm also using xcode6. My questions are: how can I rewrite this correctly in Objective-c and what would it look like in the new Swift? Also why is there an error - I don't follow how to implement some of the other threads on this question?
Name.h
#import <Foundation/Foundation.h>
#interface Name : NSObject
#property (nonatomic, retain) NSMutableArray *myArray;
#end
Name.m
#import "Name.h"
#implementation Name
NSMutableArray *myArray = [[NSMutableArray alloc] init]; //error shows up here - initializer element is not a compile-time constant
[myArray addObject:#"Object 1"];
[myArray addObject:#"Object 2"];
[myArray addObject:#"Object 3"];
#end
You should init the variable only inside a method
try override
-(id) init
{
self = [super init];
if(self)
{
myArray = [[NSMutableArray alloc] init];
}
return self;
}
Error
As the error say, you can only initialize compile time constant in the implementation of your class
This will work:
NSString* abcd = #"test";
Because #"test" is a constant and will never change after the compilation of your code.
[[NSMutableArray alloc] init] is not a constant and this is why you got an error. You will have to implement an init method to initialize your array.
Swift
For the swift part of your question:
You can still use NSArray in swift or use the swift Array type.
You can check out the Working with Cocoa Data Types Documentation or the Apple collections types Swift Documentation.
If you still want to use NSArray in swift :
var array:NSMutableArray = NSMutableArray()
array.addObject("test1")
array.addObject("test2")
// or
array:NSMutableArray = ["test1", "test2"]
Or if you want to use the swift array :
var array:String[] = ["test1", "test2"]
// or
var array:String[] = String[]()
array.append("test1")
array.append("test2")
Try to edit you "Building Settings"->"Compile Sources As" to "Objective-C++", maybe can solve your problem.

Why is my NSMutableArray, located in a singleton, returning (null)?

I am working in Xcode 4.5.1 in Objective-C. I’m making a hearing test and want to store relevant data to each question in an array. I made a singleton MyManager. I use this to store data.
It is working fine for simple int/float values etc., but I’m stuck trying to use NSMutableArray. I’m new to Objective-C, so I’m assuming/hoping I've made some obvious mistake.
So, I want to fill mySNRArray with float values. I’ve come to understand that I can’t simply add floats, because it will only take objects. Thus, I use NSNumber.
Problem: When I try to read the data that I’ve supposedly added to the NSMutableArray, I get (null).
I will now provide the relevant code:
MyManager.h
#interface MyManager : NSObject
{
NSMutableArray *mySNRArray;
}
#property (readwrite) NSMutableArray *mySNRArray;
+ (id)sharedManager;
#end
MyManager.m
#implementation MyManager
#synthesize mySNRArray;
+ (id)sharedManager
{
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (id)init
{
if (self = [super init])
{
NSMutableArray *mySNRArray = [[NSMutableArray alloc]init];
}
return self;
}
#end
TestViewController.m
//First, I try to add a value to mySNRArray.
MyManager *Manager = [MyManager sharedManager];
NSNumber *tempStorage1 = [[NSNumber alloc] initWithFloat:mySNR];
[Manager.mySNRArray insertObject:tempStorage1 atIndex:questionNumber];
//The NSLog below is showing the correct value.
NSLog(#"%# : mySNR", tempStorage1);
...
for (n = 0; n < questionNumber; n++)
{
//Second, I try to acces the values I supposedly added to mySNRArray.
MyManager *Manager = [MyManager sharedManager];
//This NSLog below is showing (null).
NSLog(#"Value at %i in SNRArray = %#", n, [Manager.mySNRArray objectAtIndex:n]);
}
...
I hope somebody can explain my error.
change
NSMutableArray *mySNRArray = [[NSMutableArray alloc]init];
to
self->_mySNRArray = [[NSMutableArray alloc]init];
in your init method you are creating a local mutable array, but not assigning it to your property
Instead of creating a new object, use the ivar you created..in the init method.
_mySNRArray = [[NSMutableArray alloc]init];
Even you can ommit these, from your .h
{
NSMutableArray *mySNRArray;
}
+ (id)sharedManager
returns a value
static MyManager* sharedManager
Change the interface to
+ (MyManager*)sharedManager
and the compiler will tell you exactly what mistake you made.

Accessing NSDictionary in Singleton Class w/o Creating Copies

I have a singleton as follows, which creates an instance of NSDictionary to hold my data. Here is the .h:
#interface FirstLast : NSObject
#property (strong, nonatomic, readonly) NSArray *firstArray;
#property (strong, nonatomic, readonly) NSArray *lastArray;
#property (strong, nonatomic, readonly) NSDictionary *fl;
+ (FirstLast *) firstLast;
- (NSDictionary *) tempDic;
#end
Here is the .m
#implementation FirstLast
#synthesize firstArray = _firstArray;
#synthesize lastArray = _lastArray;
#synthesize fl = _fl;
+ (FirstLast *)firstLast {
static FirstLast *singleton;
static dispatch_once_t once;
dispatch_once(&once, ^{
singleton = [[FirstLast alloc] init];
NSLog(#"FirstLast instantiated");
});
return singleton;
}
- (NSDictionary *) tempDic{
_firstArray = [[NSArray alloc] initWithObjects:#"Bob", #"Joe", #"Sally", #"Sue", nil];
_lastArray = [[NSArray alloc] initWithObjects:#"Jones", #"Johnson", #"Thompson", #"Miller", nil];
_fl = [NSDictionary dictionaryWithObjects:_firstArray
forKeys:_lastArray];
NSLog(#"tempDic just made _fl at this address");
NSLog(#"%p", _fl);
return _fl;
}
#end
All of this works fine. In the view controller I instantiate all this for the first time (works fine too):
NSLog(#"VC is setting up tempDic");
[[WordsClues wordsClues] tempDic];
When I try to gain access to tempDic elsewhere, like this:
NSInteger rIndex = arc4random_uniform(4) + 1;
NSString *fname = [[[FirstLast firstLast].tempDic allValues] objectAtIndex:rIndex];
it works fine, but, when I repeat this process, each time I'm creating a new tempDic. I know this because the NSLog giving the address gives a different answer each time. I really want to access the existing dictionary, which is what I thought my singleton was going to accomplish. Clearly I'm either not accessing tempDic correctly or I misunderstand what the singleton can do for me or I have the tempDic set up wrong. The goal is to get a random value from a single copy of tempDic and not write local copies of tempDic all over the place. Thanks.
Why do you recreate the dictionary in -tempDic at all?
I.e. move the dictionary instantiation code to init and then just return _fl; in tempDic.
No worries -- we've all been there [new].
In your FirstLast class, implement the init method as something like:
- init
{
self = [super init];
if ( self ) {
_fl = ... create your dictionary here ...;
}
return self;
}
Then change -tempDic to:
- (NSDictionary*)tempDic {
return _fl;
}
I would highly recommend that you read a good intro to Objective-C book. I'm a purist and, thus, would recommend going to the source for the information, but there are lots of books available.
The questions you are asking are more in line with "What is object oriented programming and how does Objective-C work?".
To answer your question; FirstLast is a class and the singleton pattern makes sure there is exactly one instance of that class. By moving the creation of the dictionary to the init method -- which is called only once and who stores a reference to the created dictionary in an instance variable -- you avoid creating multiple dictionary instances.
Every time you call tempDic, you create a new copy of it. What you should do is add you code for creating the dictionary to your alloc instance, and then just retrieve it in your getter.
Alternativly you can do this
- (NSDictionary *) tempDic{
if( _fl == nil )
{
_firstArray = [[NSArray alloc] initWithObjects:#"Bob", #"Joe", #"Sally", #"Sue", nil];
_lastArray = [[NSArray alloc] initWithObjects:#"Jones", #"Johnson", #"Thompson", #"Miller", nil];
_fl = [NSDictionary dictionaryWithObjects:_firstArray
forKeys:_lastArray];
NSLog(#"tempDic just made _fl at this address");
NSLog(#"%p", _fl);
}
return _fl;
}

iOS - NSMutableArray shows objects out of bounds on setting property

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.

Objective-c simple memory question

If I have a variable in my view controler
viewcontroller.m
#interface MemoryTestViewController : UIViewController
{
NSMutableArray *array;
}
#end
in my implementation
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *aux = [[NSMutableArray alloc] initWithCapacity:1];
array = aux;
[aux release];
// Do i have to do array release?
}
Do i have to release my variable array somewhere? Theoricaly i havent allocated that variable...
I testes the memory leaks and even if i dont release anything the instruments doesn't detect any leak.
No, you don't need to release. All you do is assign the pointer of aux to your array variable.
array is invalid at the moment where you release aux.
This is probably not as intended. If you want to work with array, you'll have to retain it.
You've already released the array with [aux release]; -- you in fact have the opposite problem to a leak: an over-release.
Assignments in Objective-C are just assignments of pointers; there's no copying or automatic memory management. When you say array = aux;, array now points to the exact same object as aux. If you then get rid of aux by releasing it (and therefore letting it be deallocated), array doesn't point to anything anymore.*
You have a couple of options for fixing this:
(Simplest) Assign the newly-created array directly to array:
array = [[NSMutableArray alloc] initWithCapacity:1];
This gives you ownership of the new array, under the name array. Don't release it until you are done with it (possibly in dealloc; certainly not in this method).
(Best) Create a declared property for array and let that mechanism handle the memory management for you:
#interface MemoryTestViewController : UIViewController
{
NSMutableArray *array;
}
#property (copy, nonatomic, setter=setArrayByMutableCopy) NSMutableArray * array;
#end
#implementation MemoryTestViewController
#synthesize array;
// Properties can't automatically make mutable copies, so you need to create
// your own setter method.
- (void) setArrayByMutableCopy: (NSMutableArray *)newArray {
NSMutableArray * tmp = [newArray mutableCopy];
[array release];
array = tmp;
}
...
*Or, rather, it points to a place where there used to be a valid object, which is a great way to make your program crash.
No. Assigning an object to a variable does not retain it. However if you plan to use that variable for a while, you should retain it and release it when you are done with it.
alloc raised the retain counter to 1 and [aux release] set it to 0
You should add a property:
#property (nonatomic, retain) NSMutableArray *array;
and later in your viewDidLoad:
// wrong, leaks: self.array = [[NSMutableArray alloc] initWithCapacity:1];
array = [[NSMutableArray alloc] initWithCapacity:1];
and yes, somewhat later release it, probably in dealloc..