views:

176

answers:

5

Hello, is it possible to specify that a NSMutableArray can only contain a certain type of objects. For example, if I want to store only this kind of objects :

@interface MyObject : NSObject {
    UInt8 value; 
}

In order to be able to use the instance variable like this :

- (void)myMethod:(NSMutableArray *)myArray{
    for (id myObject in myArray){
        [self otherMethod:myObject.value];
    }
}

because I'm getting this error :

request for member 'value' in something not a structure or union

Thank you for your help

A: 

Objective-C doesn't work like that. You need to use [myObject value] (which will work irrespective of the kind of object, as long as it responds to -[value]. If you only want one type of objects in it, insert only that type of objects.

Williham Totland
[myObject value] wasn't working... because there were other choices for this method... I renamed my instance variable in "myValue" and now [myObject myValue] works..
Leo
Introduced in Objective-C 2, you can also use dot-notation to access properties, or any method that doesn't require arguments, really. So `myObject.value` is perfectly good syntax-wise.
Douwe Maan
only if the compiler knows the receiver type, for some reason.
Williham Totland
A: 

You would have to write a wrapper-class for the NSMutableArray, see for example this question.

gammelgul
Thank you for for the link, I might need to use it soon. Good to know
Leo
+2  A: 

It sounds like you're coming from a Java/C# type background where limits can be imposed on collections.

Collections in Cocoa don't follow that pattern. There is no way to set a restriction on what type of objects can be inserted (unless you write a wrapper class that enforces this).

Objective-C, by design, follows the "if it walks like a duck and it quacks like a duck, then it most probably is a duck" philosophy. That is to say that rather than checking whether an object is a particular type, you should be checking whether it can do what you want it to do regardless of its type.

You can do this using respondsToSelector:.

Finally, your problem isn't actually related to the fact that the array has no restrictions. Your object doesn't appear to declare the instance variable value as a property, or expose any accessor methods for it.

This is why you're seeing the error when you try myObject.value. That syntax in Objective-C is how you access properties.

The default scope for instance variables in Objective-C is @protected, which means anything outside your class can't access them without going through an accessor method of some kind.

You need to declare and define the methods - (UInt8)value and - (void)setValue:(UInt8)aValue and use them.

Alternatively, you could declare is as property.

Jasarien
A: 

Subclass NSMutableArray and override methods that mediate the addition of objects to the array. You would check the object type in these overridden methods, only calling [super addObject:xyz] if the type is accepted.

Alex Reynolds
This is a *bad* idea. `NSMutableArray` is an abstract class, you can't really subclass it without writing your own implementation of an array.
Williham Totland
Rather than subclass, create a wrapper. The wrapper class can contain a private instance of an NSArray and expose an interface that allows you to do the type checking.
Jasarien
+3  A: 

You are getting that error, because for as far as Objective-C is concerned, myObject is of the non-type id, which doesn't support the value property. To make Objective-C aware of the fact it's always dealing with a MyObject in this loop, you'll have to tell it the myObject object is an instance of MyObject.

for (MyObject *myObject in myArray) {

Also, you have to make sure the value ivar is accessible using dot-notation by implementing getter and setter methods for it. You can do this yourself by implementing -value and -setValue:, or you can use @property and @synthesize to let Objective-C do this.

Douwe Maan