Question

I was wondering if there is any sample code out there for objective-C for implementing a NSMutableArray of type struct. Inside, I need there to be 2 mutable arrays (via NSMutableArray also) declared in the struct. All the code samples in my book show me how to make an array of defined size via C array syntax (with the brackets), but I don't know how to get one going with NSMutableArray. Has anyone else done this before? Here's my code so far...It compiles fine I have defined the size of the arrays (2 and 5 are used in my code below as an example, but I need to set it so I can have them mutable. I can work with simple structs when they just have some of the "easier-to-understand" data types like int, double, short, long, BOOL (you get the idea). When it gets into pointers though, this is where I become lost (I can use pointers fine, but knowing how to put them in a struct is the difficult part). Once the code is working with NSMutableArray's, would I put "network" in the interface as a pointer to type "Network"? I tried this before, but I got errors. In the end, I basically want to be able to write

network.input[2].list[1].value = 5.0;

on an arbitrarily defined array of type "Network". Could anyone offer suggestion or links to information about making a NSMutableArray of type "Network" which includes a struct of two NSMutableArray's? Thanks for any help!

SomeFile.h

#import <Foundation/Foundation.h>

struct lists{
    double value;
};

// supporting structs
struct inputs{
    struct lists list[2];
};

struct Network {
    struct inputs input[5];
    struct lists output[5];
}

@interface SomeFile : NSObject {

}

@end

SomeFile.m

#import "SomeFile.h"
@implementation SomeFile
@end
Was it helpful?

Solution

This is not be a complete answer; I’m not sure what you mean by not knowing how to put pointers in structs. I’m going to proceed by assuming you want to model an network of multiple inputs and outputs with a dynamic number of both.

You have a few choices here:

  1. Use value objects instead of structs to store your values:

    [[[network inputs] objectAtIndex:2] replaceObjectAtIndex:1 withObject:[NSNumber numberWithDouble:5.0]];
    
  2. Model your Network with an object:

    @interface Network : NSObject {
        // ivars
    }
    
    - (void) setInput:(double)value atIndex:(NSInteger)valueIndex ofInputAtIndex:(NSInteger)inputIndex;
    - (double) outputAtIndex:(NSInteger)index;
    @end
    
  3. Just use structs like you’re already doing; if you need to change the size up-front, use your friend malloc:

    struct Network_value {
      double value;
    }
    
    struct Network {
        struct Network_value **inputs;
        struct Network_value *outputs;
    };
    
    void Network_alloc(Network *n, unsigned inputs, unsigned input_values, unsigned outputs) {
        n->outputs = calloc(sizeof(Network_value), outputs);
        n->inputs = calloc(sizeof(Network_value *), inputs);
        while (inputs --> 0) {
            n->inputs[inputs] = calloc(sizeof(Network_value), input_values);
        }
    }
    
    void Network_free(Network *n, unsigned inputs) {
        free(n->outputs);
        while (inputs --> 0) {
            free(n->inputs[inputs]);
        }
        free(n->inputs);
    }
    
    Network network;
    Network_alloc(&network, 5, 2, 5);
    
    network.inputs[2][1].value = 5.0;
    
    Network_free(&network, 2);
    
  4. Combine ideas 2 and 3 by presenting a Network object but internally store the values with structs. This is probably a good idea if the number of inputs and outputs is very large.

OTHER TIPS

NSArray and NSMutableArray can only contain Objective-C objects, so you can't store structs in them. If the contents must be structs and you want something similar to NSArray, use NSPointerArray, available in 10.5 and later.

You can store pointers to Objective-C objects (like NSPointerArray* or id) inside a struct just like any other pointer type. For example, you could declare a struct for a doubly-linked list node that stores an Objective-C object like this:

typedef struct DoublyLinkedListNode {
    id object;
    __strong struct DoublyLinkedListNode *next;
    __strong struct DoublyLinkedListNode *prev;
} DoublyLinkedListNode;

The __strong attribute is used in connection with garbage collection in Objective-C 2.0, since pointers to Objective-C objects act as strong references, but C pointer types do not by default. This way, as long as one node in the list is referenced from a __strong reference, the list won't disappear. (Read the Garbage Collection Programming Guide for details, and particularly the second half of Using Core Foundation with Garbage Collection.) You'll probably want to consider doing this for your structs.

As far as your desired syntax, I may not have fully understood your question, but you won't be able to use the bracket syntax to access objects in a Cocoa collections like an NSPointerArray. (Also, odds are you'll have to use the "->" operator instead of "." for the structs, since they're likely to be allocated on the heap. All Objective-C objects must be, and I assume you'll want to store these structs outside of the local scope of a method.)

Since Objective-C doesn't have generics, you also can't "implement [an] NSMutableArray of type struct". In fact, one of your previous SO questions has more detail on the subject. If that's not what you meant, feel free to clarify.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top