NSArray assignment - objective-c

I have two viewControllers and one has to pass an array to another, but on receiving side i am always getting count 0. here is what i did
classA.h
Class A : UIViewController
{
#private
NSMutableArray *_array;
}
#property (nonatomic, retain ) NSMutableArray *array;
#end
classA.m
#implementation
#synthesis array =_array;
-(void) nowShow
{
int objCount = [ _array count ]; // This is always coming as 0 though i tried various ways (listed below )
}
#end
classB.m
-(void) method:(id)sender {
NSMutableArray *msgArray = [[NSMutableArray alloc] initWithCapacity:1];
for ( int i = 0 ; i <objCount; i++ ){
unsigned int idMsg = msgId[i];
[msgArray addObject:[NSNumber numberWithUnsignedInt:idMsg]];
}
classA *classAController = [[classA alloc] initWithStyle:UITableViewStylePlain];
//[ classAController.array arrayWithObject
//[classAController.array addObjectsFromArray:msgArray];
[ classAController.array initWithArray:msgArray];
//[classAController.array setArray:moveArray];
[self presentModalViewController:classAController animated:YES];
}
Any suggestion guys

You shouldn't call any init method unless it's immediately after calling alloc.
With properties, all you need to use is assignment:
classAController.array = msgArray;

The keyword should be #synthesize not #synthesis
edit: also you want to synthesize the property "array", not the instance variable _array

Related

Objective-C: How to create object instance with constructor that references arrays

I'm trying to create an array of objects, but it's not working as expected. I have a Person class with a name property and I'm trying to instantiate Person objects with the names from another array like the code below. Instead of the names in the names array being used, the program outputs "(null)". So that means that it's not working as expected.
ViewController.m
names = [NSArray arrayWithObjects:#"Mike", #"John", #"Jimmy", #"Tim", nil];
personsArray = [[NSMutableArray alloc] initWithCapacity:4];
for (int i = 0; i <= 4; i++) {
Person *person = [[Person alloc] initWithName:[names objectAtIndex:i]];
NSLog(#"%#", [person name]); // outputs "(null)"
[personsArray addObject:person];
}
Person.m
#import "Person.h"
#implementation Person
-(id)initWithName:(NSString *)name {
if (self = [super init]) {
name = name;
}
return self;
}
#end
Person.h
#import <Foundation/Foundation.h>
#interface Person : NSObject
#property (nonatomic, strong) NSString *name;
-(id)initWithName:(NSString *)name;
#end
Please help!
This line in -[Person initWithName:] is your problem:
name = name;
You are just assigning the argument variable to itself. You need to assign the instance variable. You probably want to copy the input string, so:
_name = [name copy];

Checking NSMutableArray for 0 elements causes a crash; why?

I have declared a NSMutableArray as a singleton; when I try to check for the array count, the app crashes! Here is the code:
// clear array that holds selected servcies
SingletonArrayOfSelectedRows *arrayOfSelectedRows = [SingletonArrayOfSelectedRows sharedArrayOfSelectedRows];
if([arrayOfSelectedRows count] > 0)
[arrayOfSelectedRows removeAllObjects];
This code is the same code I have found all over SO and Google. Using XCode5, I have checked to make sure the singleton is allocated (and it is), and there is a valid count (0) for the singleton.
UPDATE
Here is the code for the singleton.h file:
#interface SingletonArrayOfSelectedRows : NSMutableArray {
}
#property (nonatomic, retain) NSMutableArray *arrayOfSelectedRows;
+ (id)sharedArrayOfSelectedRows;
#end
Here is the code for the singleton.m file:
#implementation SingletonArrayOfSelectedRows {
}
#synthesize arrayOfSelectedRows; // rename
// sharedSelectedCellIndexes
+ (id)sharedArrayOfSelectedRows {
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) {
arrayOfSelectedRows = [[NSMutableArray alloc] init];
}
return self;
}
#end
Don't subclass NSMutableArray to do this. NSMutableArray is a class cluster. All of the actual array implementation is inside subclasses of NSMutableArray. If you subclass NSMutableArray then your subclass won't actually implement any array behavior unless you write it yourself.
According to the documentation :
Any subclass of NSArray must override the primitive instance methods count and objectAtIndex:.
Since you are subclassing NSMutableArray you will need to override the following NSMutableArray primitive methods as well:
insertObject:atIndex:
removeObjectAtIndex:
addObject:
removeLastObject
replaceObjectAtIndex:withObject:

Set readonly attribute in ObjC

Is there a way to set a value to readonly attribute in Objective-C?
I actually don't care how nasty the code is unless it isn't stable anymore.
Never mind my comment, here's the two ways you do it:
#interface Grimley : NSObject
#property (readonly, copy) NSString * blabber;
#property (readonly, copy) NSString * narwhal;
- (id) initWithBlabber:(NSString *)newBlabber;
#end
#implementation Grimley
#synthesize blabber;
#synthesize narwhal = unicorn;
- (id) initWithBlabber:(NSString *)newBlabber {
self = [super init];
if( !self ) return nil;
// Any object can of course set its own ivar regardless
// of how the property it backs is declared.
blabber = [newBlabber copy];
// Refer to the _ivar_, not the property.
unicorn = #"One horn";
return self;
}
#end
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Grimley * g = [[Grimley alloc] initWithBlabber:#"Excelsior"];
// This is how you get around the property.
[g setValue:#"Nimitz" forKey:#"blabber"];
// Again, use the name of the variable, not the property
[g setValue:#"Pearly horn" forKey:#"unicorn"];
NSLog(#"%#", [g blabber]);
NSLog(#"%#", [g narwhal]);
[g release];
[pool drain];
return 0;
}

Could there be an issue with the max. memory capacity? Or why is this variable partly released?

I'm developing an iPad app and I ran into a really weird issue here. I'll try to explain it as good as possible.
I have a class named TranslationObject which is holding a key and a textual value. I have created this class as the following:
#interface TranslationObject : NSObject {
NSNumber *_key;
NSString *_value;
}
#property (nonatomic, retain) NSNumber *key;
#property (nonatomic, retain) NSString *value;
- (id) initWithKey:(NSNumber *) key andValue:(NSString *) value;
#end
The translations will be pulled from a XML or DB in the future, but for now I do the following:
#interface Translation : NSObject {
NSMutableArray *m_extfeat;
}
#property (nonatomic, retain) NSMutableArray *extfeat;
+ (Translation *) getInstance;
- (id) init;
- (NSMutableArray *) getExtFeat;
#end
Implementation:
#implementation Translation
#synthesize extfeat = m_extfeat;
- (id) init {
self = [super init];
if (self) {
m_extfeat = [[self getExtFeat] retain];
}
return self;
}
- (NSMutableArray *) getExtFeat {
TranslationObject *obj1 = [[[TranslationObject alloc] initWithKey:[NSNumber numberWithInt: 0] andValue:#"Animal house"] autorelease];
.... more items declared ....
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12, obj13, obj14, obj15, obj16, obj17, nil];
return [array autorelease];
}
#end
These translations are being used in a UITableViewController and are being fetched in the viewDidLoad method as:
- (void)viewDidLoad
{
_data = [[Translation getInstance].extfeat retain];
}
I use these values at its cellForRowAtIndexPath, where I call a method to configure the cell:
- (void) configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *) indexPath {
TranslationObject *object = (TranslationObject *) [_data objectAtIndex:indexPath.row];
//Crashes here at 13th item:
NSLog("Object key: %#", [object.key stringValue]);
}
As the snippet above says, strangely, the app crashes when fetching the key value only if the _data array contains more than 12 items. So if I only fill the _data variable with 12 items or less, my code works fine. If I add more than 12, the app crashes as soon as it fetches the 13th object.
So I enabled NSZombies and so when I check the 13th item in that method, the value is still fine, but it's only the key that turned into a Zombie. And again.. Only from the 13th item on!
Does anyone know how this is possible? Is it maybe so that there is a maximum number of items that can be stored in the memory? Is the memory full at the 12 item? But if that'd be the case, then why would the value still be there. How would it be possible that it's just the key that is being released before?! And how?!
I hope this explanation makes sense and someone can shine a light over this case.. =/
Thanks!
EDIT: Here's the implementation of the initWithKey method of the TranslationObject:
- (id) initWithKey:(NSNumber *) key andValue:(NSString *) value {
self = [super init];
if (self) {
_key = key;
_value = value;
}
return self;
}
Make sure your using the property accessors in the TranslationObject or retaining the number:
#implementation TranslationObject
#synthesize key=_key, value=_value;
- (id) initWithKey:(NSNumber *) key andValue:(NSString *) value {
self = [super init];
if (!self) return nil;
self.key = key; // ensures key is retained
self.value = value;
return self;
}
…
#end
Specifics:
self.key = key;
is the syntax for calling the accessor methods for the property; in this case the set accessor. Given you declared your property with the nonatomic and retain attributes as follows:
#property (nonatomic, retain) NSNumber *key;
the set accessor will look something like
- (void)setKey:(NSNumber *)value {
if (value != _key) {
id old = _key;
[value retain];
_key = value
[old release];
}
}
The set accessor is automatically generated by the compiler when you added:
#synthesize key=_key;
Conversely, calling
_key = key;
simply copies the value of the pointer in key to _key, but does not retain the object referred to by key. TranslationObject does not assume ownership of key. If you did not want to use the accessor, the correct implementation would be
_key = [key retain];

#property retain OR copy

First I read this article
I think I should use "copy" in my programe.
Problem is using NSMutableDictionary copy it will terminate.
***** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary removeAllObjects]: mutating method sent to immutable object'**
I have no idea about "mutating method sent to immutable object".
I didn't set NSDictionary to NSMutabledictionary pointer.
Here is my code
.h file
#interface Button : NSObject {
#private
NSString* gID;
NSString* gBackColor;
NSString* gIconImage;
int gIndex;
BOOL gEnable;
BOOL gVisible;
NSString* gText;
NSMutableDictionary* gEvents;
BOOL gUseCircle;
}
#property (nonatomic,copy) NSString *ID;
#property (nonatomic,copy) NSString *BackColor;
#property (nonatomic,copy) NSString *IconImage;
#property int Index;
#property BOOL Enable;
#property BOOL Visible;
#property (nonatomic,copy) NSString *Text;
#property (nonatomic,getter=getEvents,retain) NSMutableDictionary *Events;
#property BOOL UseCircle;
#end
.m file
#implementation Button
#synthesize ID = gID;
#synthesize BackColor = gBackColor;
#synthesize IconImage = gIconImage;
#synthesize Index = gIndex;
#synthesize Enable = gEnable;
#synthesize Visible = gVisible;
#synthesize Text = gText;
#synthesize Events = gEvents;
#synthesize UseCircle = gUseCircle;
-(NSMutableDictionary*) getEvents
{
if (!gEvents)
{
gEvents = [[NSMutableDictionary alloc] initWithCapacity:20];
}
return gEvents;
}
- (id) init
{
self = [super init];
if (self != nil)
{
gID = #"";
gBackColor = #"";
gIconImage = #"";
gIndex = 0;
gText = #"";
gUseCircle = NO;
}
return self;
}
- (void) dealloc
{
[gID release];
[gBackColor release];
[gIconImage release];
[gText release];
[gEvents removeAllObjects];
[gEvents release];
gEvents = nil;
[super dealloc];
}
And implement
tBtnXML.Events = [self SplitEvents:tNode];
SplitEvents function:
-(NSMutableDictionary*) SplitEvents:(NSDictionary*)pEvents
{
NSMutableDictionary *tEvents = [[NSMutableDictionary alloc] initWithCapacity:5];
// code blabla
//.
//.
//.
[tEvents setObject:tEvent forKey:[NSNumber numberWithInt:tEventName]];
[tEvent release];
return [tEvents autorelease];
}
But I chage NSMutableDictionary* gEvents property from copy to retain , it execute normal.
Colud anyone tell me what's wrong with my code?
If my code is incorrect with dealloc,please tell me.
Thank you appriciate.
Yes, So I fixed my setter:
-(void) setEvents:(NSMutableDictionary*) pEvents
{
NSMutableDictionary* tNewDict = [pEvents mutableCopy];
[gEvents removeAllObjects];
[gEvents release];
gEvents = tNewDict;
}
This work with no error.
It helps me a lot.
But I can't vote up >"<~
So thank you Bavarious :)
In general, mutable properties should be retain instead of copy. When you declare a property as being copy, the synthesised setter method sends -copy to the object that’s being assigned to the property. In the case of mutable objects (e.g. NSMutableDictionary), sending -copy to them makes an immutable copy, effectively creating an object of immutable type (e.g. NSDictionary) instead.
So in:
tBtnXML.Events = [self SplitEvents:tNode];
the synthesised setter sends -copy to [self SplitEvents:tNode], thus creating an immutable copy of that dictionary (i.e., an NSDictionary instance), and assign it to gEvents. This is the cause of your error: gEvents is declared as NSMutableDictionary but points to an NSDictionary instead.
For the record, mutable classes usually declare a -mutableCopy method that does make a mutable copy. It is not used by declared properties, though. If you do not want to use retain, you need to implement a custom setter that uses -mutableCopy.