Chocobouc
Chocobouc

Reputation: 113

Custom object array of pointers all points to the same object

This is my first post, so sorry if it is messy.

I want to dynamically add custom objects Pixra that I created in an NSMutableArray. Because it uses an interface, I instanciate my objects with a pointer as so : Pixra* pix = [Pixra alloc];.

When I parse my array, I can see that all the pointers I added points to the same object because the values of the property quality is the same for all the element of the array. Here is my implementation of the loop that adds the element in the array.

NSMutableArray* imagesRaw = [NSMutableArray array];
double j=0.0;
for (UIImage* img in images){
  Pixra* pix = [Pixra alloc];
  [pix setMatrix:img];
  [pix setQuality:j];
  [imagesRaw addObject:pix];
  cout << [imagesRaw[0] getQuality] << "\n";
  j++;
} 

The console log shows that the quality is iterating while it shouldn't because I only display the first element of the array.

Pixra.mm

#import <Foundation/Foundation.h>
#import "Pixra.h"
@implementation Pixra

UIImage* matrix;
double quality;

-(void) setMatrix:(UIImage*)matrixArg{
  matrix = matrixArg;
}
-(UIImage*) getMatrix{
  return matrix;
}
-(void) setQuality:(double)qualityArg{
  quality = qualityArg;
}
-(double) getQuality{
  return quality;
}
-(id) pixraInit:(UIImage*)img:(double)quality{
  self = [super init];
  self.matrix = img;
  self.quality = quality;
  return self;
}
+(instancetype) pixraInit:(UIImage*)img:(double)quality{
  Pixra* pix = [[Pixra alloc] pixraInit:img :quality];
  return pix;
}
@end

Pixra.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class Pixra;
@interface Pixra : NSObject
-(void) setMatrix:(UIImage*)matrixArg;
-(UIImage*) getMatrix;
-(void) setQuality:(double)qualityArg;
-(double) getQuality;
+(instancetype) pixraInit:(UIImage*)img :(double)quality;
@end

As you can see, I tried to do it with an initalizer that returns the instance but it didn't work either. How can I create pointers on different instances of my custom objects ?

Upvotes: 1

Views: 128

Answers (2)

Itachi
Itachi

Reputation: 6070

When you write in the class implementation file like this, the compiler takes it as global variables. There is only one block of memory for each one.

UIImage* matrix;
double quality;

With these properties, all the Pixra object instances use the global variables to save them, it used in Sington Instance design pattern generally.

So how to correct it? If you are looking for the right properties to save the matrix and quality value for each Pixra instance, use @property like this.

@interface Pixra : NSObject

@property (strong) UIImage *matrix;
@property (assign) CGFloat quality;

@end

Note that this property implementation has covered the setMatrix and matrix property method. Check out more detail about Objective-C Class Property in google.

Upvotes: 3

mag_zbc
mag_zbc

Reputation: 6992

You forgot init

Pixra* pix = [Pixra alloc];

From documentation of NSObject's init() method:

An object isn’t ready to be used until it has been initialized.

In some cases, a custom implementation of the init() method might return a substitute object. You must therefore always use the object returned by init(), and not the one returned by alloc or allocWithZone:, in subsequent code

So replace

Pixra* pix = [Pixra alloc];

with

Pixra* pix = [[Pixra alloc] init];

or

Pixra* pix = [Pixra new];

Upvotes: 1

Related Questions