8

Property for ivar that points to a two-dimensional array of pointers to NSString...

 3 years ago
source link: https://www.codesd.com/item/property-for-ivar-that-points-to-a-two-dimensional-array-of-pointers-to-nsstrings.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Property for ivar that points to a two-dimensional array of pointers to NSStrings

advertisements

I want to create a class that contains a dynamic, two-dimensional c-array of pointers to NSStrings. I know I can simulate a two-dimensional array using an NSArray containing multiple NSArrays, but if possible I'd like to do this using a traditional two-dimensional c-array. ARC won't allow a simple assignment of a pointer to an NSString to an element of a c-array unless you use "__unsafe_unretained":

@interface NumberStringsArray : NSObject
{
  @public
  NSString * __unsafe_unretained **_array;
}

To avoid memory leaks and to give an object in the class ownership of each NSString assigned to the c-array, I add a pointer to each NSString object to an NSMutableArray. In -(void)dealloc I free the memory acquired to create the two-dimensional c-array.

Here's my question: How do I declare a property based on the _array ivar so that I can refer to the i,j element of the array as "foobar.array[i][j]" rather than "foobar->array[i][j]"?

Later amplification: I did it in a very similar manner to the answerer except for the __bridge stuff. I don't know if that makes a difference. I allocate the two-dimensional array here:

self->_array = (NSString * __unsafe_unretained **)calloc(_columnCount, sizeof(void *));
if (!self->_array)
  return nil;
for (UINT16 i = 0; i < _columnCount; i++)
{
  self->_array[i] = (NSString * __unsafe_unretained *)calloc(_rowCount, sizeof(void *));
  if (!self->_array[i])
  {
    for (UINT16 a = 0; a < _columnCount; a++)
      if (self->_array[a])
        free(self->_array[a]);
    if (self->_array)
      free(self->_array);
    return nil;
  }
}

I put pointers to the NSString objects into the array using substrings generated from a file of comma-separated values:

NSArray *numbers = [line componentsSeparatedByString: @","];
for (UINT16 i = 0; i < _columnCount; i++)
{
  NSString *number = @"";
  if (i < [numbers count])
    number = [numbers objectAtIndex: i];
  //
  // save it in owners
  //
  [self.owners addObject: number];
  self->_array[i][j] = number;
}

In -(void)dealloc I free all the memory:

-(void)dealloc
{
  for (UINT16 i = 0; i < self.columnCount; i++)
    if (self->_array[i])
      free(self->_array[i]);
  if (self->_array)
    free(self->_array);
}


Declare this property:

@property (nonatomic) NSString * __unsafe_unretained **_array;

Then you can allocate the pointers to objects:

_array= (NSString * __unsafe_unretained **) malloc(M*sizeof(CFTypeRef) );
for(NSUInteger i=0; i<M;i++)
{
    _array[i]= ((NSString * __unsafe_unretained *) malloc(N*sizeof(CFTypeRef) );
    for(NSUInteger j=0; j<N;j++)
    {
        _array[i][j]= (__bridge NSString*) (__bridge_retained CFTypeRef) [[NSString alloc]initWithCString: "Hello" encoding: NSASCIIStringEncoding];
        // I see that you got habit with C so you'll probably like this method
    }
}

Then when you don't need it anymore, free the array:

for(NSUInteger i=0; i<M; i++)
{
    for(NSUInteger j=0; j<N;j++)
    {
        CFTypeRef string=(__bridge_transfer CFTypeRef) _array[i][j];
    }
    free(_array[i]);
}
free(_array);




About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK