Do I need to override the getter for a property to return an immutable copy? - objective-c

Suppose that I have a class that holds a mutable array. I want to make sure that if other classes ask for the array they will get a non-mutable type, but in the owning class, it is actually an instance of NSMutableArray, so that I can add and remove items.
#import "Person.h"
#class Asset;
#interface Employee : Person
{
NSMutableArray *_assets;
}
#property (nonatomic,copy) NSArray *assets;
-(void)addAssets:(Asset *)a;
The question is, do I have to modify the accessor methods into something like this, or will it automatically behave like I want?
#import "Employee.h"
#import "Asset.h"
#implementation Employee
/* Accessors for assets properties
-(NSArray *)assets
{
return [_assets copy];
}
-(void)setAssets:(NSArray *)assets
{
_assets = [assets mutableCopy ];
}
*/
-(void)addAssets:(Asset *)a
{
//is assets nil?
if (!_assets) {
//Create Array
_assets = [[NSMutableArray alloc]init];
}
[_assets addObject:a];
}

ppalancica's answer is incorrect. The copy attribute means only that the setter will take a copy when the property is set. The synthesized getter will not return a copy. You must implement that behavior yourself:
- (NSArray *)assets
{
return [_assets copy];
}
You might want to make an internal-only accessor that doesn't make a copy. You could also redeclare the property privately; client code will then be contracted to treat the array it requests as immutable.
This code demonstrates that the synthesized getter returns the uncopied object:
#import <Foundation/Foundation.h>
#interface ArrayReturner : NSObject
#property (copy, nonatomic) NSArray * array;
#end
#implementation ArrayReturner
{
NSMutableArray * _array;
}
- (BOOL)myArrayIsIdenticalTo:(NSArray *)otherArray
{
return _array == otherArray;
}
#end
int main(int argc, const char *argv[])
{
#autoreleasepool {
ArrayReturner * a = [ArrayReturner new];
[a setArray:#[#1, #2]];
NSArray * returnedArray = [a array];
// Does not throw
NSCAssert([a myArrayIsIdenticalTo:returnedArray],
#"Returned array is a separate instance.");
}
return 0;
}

Because you already specified the attribute "copy" for the array property, there is no need to override the getter and setter. The compiler will do all the heavy work for you.
If you specify "strong" instead, the getter and setter would look like:
-(NSArray *)assets
{
return _assets;
}
-(void)setAssets:(NSArray *)assets
{
_assets = assets;
}
And that may be a problem.
There is actually a WWDC conference that explains all these details. For NSString properties it is more recommended to use copy, and you can see it a lot like that in the iOS SDK frameworks.

Related

Objective-c readonly copy properties and ivars

I'm try to grok properties declared as both copy and readonly in objective-c, and specifically, whether I have to do the copy myself. In my init methods. Evidence suggests I do:
#interface A : NSObject
#property(nonatomic, copy, readonly) NSData *test;
- (instancetype)initWithData:(NSData *)data;
#end
#implementation A
- (instancetype)initWithData:(NSData *)data {
if ((self = [super init]) != nil) {
_test = data;
}
return self;
}
#end
int main (void) {
NSData *d1 = [NSMutableData dataWithBytes:"1234" length:5];
A *a = [[A alloc] initWithData:d1];
NSLog(#"%lx", (unsigned long)d1);
NSLog(#"%lx", (unsigned long)a.test);
return 0;
}
I had thought I could do self.test = data in my init method, but that is not permitted because it's readonly (not unexpectedly). Of course, self.test = [data copy] ensures two different objects.
So: Is there a way to create a readonly property in objective-c that copies the incoming value, or is it sufficiently an edge case that the combination is pointless and I have to do any copying myself manually anyway?
A #property declaration is merely shorthand for some accessor/mutator method declarations, and (in some cases) synthesized implementations for said accessor/mutator methods.
In your case, the #property(nonatomic, copy, readonly) NSData *test declaration expands to this equivalent code:
#interface A : NSObject
{
NSData* _test;
}
- (NSData*)test;
#end
#implementation A
- (NSData*)test
{
return _test;
}
#end
There is no setTest: mutator method because the property is declared as readonly, so the copy attribute has no effect.
You can implement your own mutator method:
- (void)setTest:(NSData*)newValue
{
_test = [newValue copy];
}
Or, you can have the compiler synthesize a mutator method for you by declaring a read/write property in a private class extension in your implementation file:
// A.m:
#interface A()
#property (nonatomic, copy) NSData* test;
#end
Both cases would allow you to use the test mutator method to copy a value to the _test instance variable:
- (instancetype)initWithData:(NSData *)data {
if ((self = [super init]) != nil) {
self.test = data;
}
return self;
}
The end result is:
#interface A : NSObject
#property(nonatomic, copy, readonly) NSData* test;
- (instancetype)initWithData:(NSData*)data;
#end
#interface A()
#property (nonatomic, copy) NSData* test;
#end
#implementation A
- (instancetype)initWithData:(NSData*)data {
if ((self = [super init]) != nil) {
self.test = data;
}
return self;
}
#end
In addition to what Darren said, the copy attribute describes what semantics the properties setter has. In your initializer, you're not using the setter, you're directly assigning to the instance variable.
It's maybe a bit hard to grok, but the instance variable is not the same thing as the property. It is used to implement the property in this case. But, assigning to the instance variable is not the same as setting the property.
If you want your initializer to also have the semantics that it copies the passed-in data, that's a separate design decision (although a good idea to go with the property's semantics). You could implement that by using a private setter as Darren suggests, but you could also just do:
_test = [data copy];
in the initializer.

no visible #interface for NSMutable Array declares selector 'addStock'

I cannot figure out why the addStock method is not working for my NSMutableArray object "giuPort" . I have properly connected all the class files. How do I make it so that the interface is visible / correct this error that comes up for each of the times I try using the addStock method?
The following snippet from my main.m file that is rendering the error is:
NSMutableArray *giuPort = [[NSMutableArray alloc]init];
[giuPort addStock:apple];
[giuPort addStock:lvs];
[giuPort addStock:verizon];
the class .h file in which I declare the NSMutableArray, etc:
#interface BNRPortfolio : NSObject
{
NSMutableArray *_stocks;
}
#property (nonatomic, copy) NSArray *stocks;
#property (nonatomic) float valueOfPort;
//instance methods
-(void)addStock:(BNRStockHolding *)s;
-(float)valueOfPort;
#end
the class .m file in which I implement the NSMutableArray, etc:
#implementation BNRPortfolio
// array get set stuff
-(void)setStocks:(NSArray *)s
{
_stocks = [s mutableCopy];
}
-(NSArray *)stocks
{
return [_stocks copy];
}
// instance methods
-(void)addStock:(BNRStockHolding *)s {
// check to see if array exists
if (!_stocks) {
_stocks = [[NSMutableArray alloc]init];
}
[_stocks addObject:s];
}
-(float)valueOfPort {
//take sum of all the stocks in this port
float sum = 0;
for (BNRStockHolding *s in _stocks) {
sum += [s valueInDollars];
}
return sum;
}
#end
The -addStock: method is a method of the BNRPortfolio class. You are attempting to call it on an instance of NSMutableArray. There's no such method on NSMutableArray, which is what the compiler is complaining about.
Apparently, you want to allocate and initialize an instance of BNRPortfolio and then call -addStock: on that.

Why does the object in this Objective C code not set?

I have the below code which simply read a bunch of cards and inputs their names into a Mutable Array if they are not present beforehand.
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSMutableArray *allCards = [[NSMutableArray alloc] init];
char cardAvailable = '\0';
do {
Card *newCard = [[Card alloc] init];
NSLog(#"What is the Card Name ?\n");
char cName[20];
scanf("%s",cName);
NSString *nName = [NSString stringWithCString:cName encoding:1];
[newCard setName:nName];
if([newCard wasMatch:allCards]) {
NSLog(#"Card Already Present");
} else {
NSLog(#" NEW CARD NAME %# %# %s",[newCard getName],newCard.name, cName);
[newCard addGlobal:newCard toArray:allCards];
}
NSLog(#"Is there another Card to Input?");
scanf("%c",&cardAvailable);
} while(cardAvailable != 'N' || cardAvailable != 'n');
NSLog(#":::: Card Names Are ::::");
for(Card *card in allCards)
{
NSLog(#"%#",card.name);
}
}
return 0;
}
However, first - The name is simply NOT SET. I don't know why this is happening. Today was my first day ever with Objective C, so please pardon me if this is too simple.
The Card class files are -
#import <Foundation/Foundation.h>
#interface Card : NSObject
#property(nonatomic) BOOL chosen;
#property (nonatomic, getter = getName) NSString *name;
-(BOOL)wasMatch:(NSMutableArray*) allCards;
-(void)addGlobal:(Card*) aCardName toArray:(NSMutableArray*) allCards;
-(void)setName:(NSString *)name;
-(void)setChosen:(BOOL)chosen;
#end
I get the error here - in the add global line.
#import "Card.h"
#implementation Card
#synthesize chosen = _chosen;
-(BOOL)chosen
{
return _chosen;
}
-(void)setChosen:(BOOL)chosen
{
_chosen = chosen;
}
#synthesize name = _name;
-(NSString*)getName
{
return _name;
}
-(void)setName:(NSString*)name
{
name = _name;
}
-(BOOL)wasMatch:(NSMutableArray *)allCards
{
for(Card *card in allCards)
{
if([self.name isEqualToString:card.name])
{
return true;
}
}
return false;
}
-(void)addGlobal:(Card *)aCardName toArray:(NSMutableArray *)allCards
{ NSLog(#" THE NS STRING %#",aCardName.name);
[allCards addObject:aCardName.name];
}
#end
Your setter is wrong.
-(void)setName:(NSString*)name
{
name = _name;
}
You assign the current instance variable (_name) to the parameter.
This should be the other way around.
-(void)setName:(NSString*)name
{
_name = name;
}
But you don't need this at all. There are various problems with your code.
Objective-C does not use getFoo for ordinary getters.
#property (nonatomic, getter = getName) NSString *name; should be
#property (copy, nonatomic) NSString *name;
And unless you are writing code in a ancient version of Objective-C (which you shouldn't) you don't need explicit getters and setters. In recent version you don't even have to explicitly synthesize.
In newer version of Objective-C your Card class should look more like this:
#interface Card : NSObject
#property (assign, nonatomic) BOOL chosen;
#property (copy, nonatomic) NSString *name;
-(BOOL)wasMatch:(NSMutableArray*) allCards;
-(void)addGlobal:(Card*) aCardName toArray:(NSMutableArray*) allCards;
#end
#import "Card.h"
#implementation Card
-(BOOL)wasMatch:(NSMutableArray *)allCards
{
for(Card *card in allCards)
{
if([self.name isEqualToString:card.name])
{
return YES;
}
}
return NO;
}
-(void)addGlobal:(Card *)aCardName toArray:(NSMutableArray *)allCards
{ NSLog(#" THE NS STRING %#",aCardName.name);
[allCards addObject:aCardName.name];
}
#end
Way less code. You might want to look for a more up to date learning resource.
The rest of your code looks questionable as well. I honestly don't see the point in addGlobal:toArray:. But I don't want to make this answer longer than necessary. ;-)
Also, for the love of your future self, don't use 1 in NSString *nName = [NSString stringWithCString:cName encoding:1]; use the constant. In your case NSASCIIStringEncoding. But because it's no longer 1980 you most likely want to use NSUTF8StringEncoding instead of ASCII.
As I said, please get more recent and decent learning resources.
In the -setName: property accessor method, you assign the the _name instance variable value to the name parameter. It should be swapped like this:
-(void)setName:(NSString*)name
{
_name = name;
}
To learn Objective-C i reccomment the most recent Stanford lectures by Paul Hegarty. CS193p the class is called. You can find all materials, and excellent videos on iTunes U. Other then Apple resource, there is no better then this.

Giving each subclass its own copy of a class variable

I have the following class in my iOS application (it is like an abstract class from the Java world).
#implementation WSObject
static NSDictionary* _dictionary = nil;
+(NSDictionary*) dictionary {
if (_dictionary == nil) {
_dictionary = [NSKeyedUnarchiver unarchiveObjectWithFile:[self localStorePath]];
}
return _dictionary;
}
...
#end
I then have multiple classes which implement this above WSObject with the class method dictionary. The problem is, that each of these classes should have their own _dictionary, but they are all sharing the same object from the super class. I could, of course, copy to all the subclasses, but that would break the reusability. Besides this getter, there are other class methods in WSObject which mutate the dictionary. Because of this, there would be a several class methods which should be in every subclass.
How can I solve this in a smart way? Please tell me if my description is insufficient.
Associative references seem like they'll do the trick. You can essentially tack some storage on to the class object itself. (I'm using NSStrings here, in place of the dictionaries you want to use, just for demonstration.)
Superclass:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#interface Stuper : NSObject
// Accessor method for the "class variable"
+ (NSString *) str;
// Analog to your +localStorePath
+ (NSString *) quote;
#end
#import "Stuper.h"
// The doc suggests simply using the address of a static variable as the key.
// This works fine, even though every class is (as in your problem) using
// the same key, because we are associating to a different class each time.
static char key;
#implementation Stuper
+ (NSString *) str {
NSString * s = objc_getAssociatedObject(self, &key);
if( !s ){
s = [self quote];
// You'll probably want to use OBJC_ASSOCIATION_RETAIN for your dictionary.
// self inside a class method is the class object; use that as
// the associator. The string is now tied to the associator, i.e.,
// has the same lifetime.
objc_setAssociatedObject(self, &key, s, OBJC_ASSOCIATION_COPY);
}
return s;
}
+ (NSString *) quote {
return #"It was the best of times, it was the worst of times.";
}
#end
Subclass:
#import "Stuper.h"
#interface Stub : Stuper #end
#import "Stub.h"
#implementation Stub
+ (NSString *) quote {
return #"Call me Ishmael.";
}
#end
Trying this out:
#import <Foundation/Foundation.h>
#import "Stuper.h"
#import "Stub.h"
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog(#"%#", [Stuper str]);
NSLog(#"%#", [Stub str]);
[pool drain];
return 0;
}
Each class object now has its own string, associated with it.
2011-12-05 23:11:09.031 SubClassVariables[36254:903] It was the best of times, it was the worst of times.
2011-12-05 23:11:09.034 SubClassVariables[36254:903] Call me Ishmael.
The only downside here is that you'll have to call the accessor method every time you want the object; you don't have a pointer you can use directly. You can call objc_getAssociatedObject in the superclass as an accessor, too, of course, since it has access to key.
In order to give each subclass its own dictionary, store a second dictionary object in your primary dictionary using the class name as the key. For example:
static NSMutableDictionary *_dictionary = nil;
+ (NSDictionary*)dictionary
{
if (_dictionary == nil)
_dictionary = [[NSKeyedUnarchiver unarchiveObjectWithFile:[self localStorePath]] mutableCopy];
NSString *key = NSStringFromClass( [self class] );
if ( [_dictionary objectForKey:key] == nil )
[_dictionary setObject:[NSMutableDictionary dictionary] forKey:key];
return [_dictionary objectForKey:key];
}
Perhaps you can return a copy of the dictionary
#implementation WSObject
static NSDictionary* _dictionary = nil;
+(NSDictionary*) dictionary {
if (_dictionary == nil) {
_dictionary = [NSKeyedUnarchiver unarchiveObjectWithFile:[self localStorePath]];
}
return [_dictionary copy];
}
...
#end
Keep in mind that if you modify _dictionary you will get a copy of that modified dictionary which may differ from what is on disk.
How often is this being called? is it really necessary to cache the file contents in this static _dictionary object?
Why not just fetch it every time form disk, assuming it isn't too often that performance comes into question.
#implementation WSObject
+(NSDictionary*) dictionary {
return [NSKeyedUnarchiver unarchiveObjectWithFile:[self localStorePath]];
}
...
#end

NSMutableArray - force the array to hold specific object type only

Is there a way to force NSMutableArray to hold one specific object type only?
I have classes definitions as follow:
#interface Wheel:NSObject
{
int size;
float diameter;
}
#end
#interface Car:NSObject
{
NSString *model;
NSString *make;
NSMutableArray *wheels;
}
#end
How can I force wheels array to hold Wheel objects only with code? (and absolutely not other objects)
Update in 2015
This answer was first written in early 2011 and began:
What we really want is parametric polymorphism so you could declare, say, NSMutableArray<NSString>; but alas such is not available.
In 2015 Apple apparently changed this with the introduction of "lightweight generics" into Objective-C and now you can declare:
NSMutableArray<NSString *> *onlyStrings = [NSMutableArray new];
But all is not quite what it seems, notice the "lightweight"... Then notice that the initialisation part of the above declaration does not contain any generic notation. While Apple have introduced parametric collections, and adding a non-string directly to the above array, onlyStrings, as in say:
[onlyStrings addObject:#666]; // <- Warning: Incompatible pointer types...
will illicit the warning as indicated, the type security is barely skin deep. Consider the method:
- (void) push:(id)obj onto:(NSMutableArray *)array
{
[array addObject:obj];
}
and the code fragment in another method of the same class:
NSMutableArray<NSString *> *oops = [NSMutableArray new];
[self push:#"asda" onto:oops]; // add a string, fine
[self push:#42 onto:oops]; // add a number, no warnings...
What Apple have implemented is essentially a hinting system to assist with automatic inter-operation with Swift, which does have a flavour of type-safe generics. However on the Objective-C side, while the compiler provides some extra hints the system is "lightweight" and type-integrity is still ultimately down to the programmer - as is the Objective-C way.
So which should you use? The new lightweight/pseudo generics, or devise your own patterns for your code? There really is no right answer, figure out what makes sense in your scenario and use it.
For example: If you are targeting interoperation with Swift you should use the lightweight generics! However if the type integrity of a collection is important in your scenario then you could combine the lightweight generics with your own code on the Objective-C side which enforces the type integrity that Swift will on its side.
The Remainder of the 2011 Answer
As another option here is a quick general subclass of NSMutableArray which you init with the kind of object you want in your monomorphic array. This option does not give you static type-checking (in as much as you ever get it in Obj-C), you get runtime exceptions on inserting the wrong type, just as you get runtime exceptions for index out of bounds etc.
This is not thoroughly tested and assumes the documentation on overriding NSMutableArray is correct...
#interface MonomorphicArray : NSMutableArray
{
Class elementClass;
NSMutableArray *realArray;
}
- (id) initWithClass:(Class)element andCapacity:(NSUInteger)numItems;
- (id) initWithClass:(Class)element;
#end
And the implementation:
#implementation MonomorphicArray
- (id) initWithClass:(Class)element andCapacity:(NSUInteger)numItems
{
elementClass = element;
realArray = [NSMutableArray arrayWithCapacity:numItems];
return self;
}
- (id) initWithClass:(Class)element
{
elementClass = element;
realArray = [NSMutableArray new];
return self;
}
// override primitive NSMutableArray methods and enforce monomorphism
- (void) insertObject:(id)anObject atIndex:(NSUInteger)index
{
if ([anObject isKindOfClass:elementClass]) // allows subclasses, use isMemeberOfClass for exact match
{
[realArray insertObject:anObject atIndex:index];
}
else
{
NSException* myException = [NSException
exceptionWithName:#"InvalidAddObject"
reason:#"Added object has wrong type"
userInfo:nil];
#throw myException;
}
}
- (void) removeObjectAtIndex:(NSUInteger)index
{
[realArray removeObjectAtIndex:index];
}
// override primitive NSArray methods
- (NSUInteger) count
{
return [realArray count];
}
- (id) objectAtIndex:(NSUInteger)index
{
return [realArray objectAtIndex:index];
}
// block all the other init's (some could be supported)
static id NotSupported()
{
NSException* myException = [NSException
exceptionWithName:#"InvalidInitializer"
reason:#"Only initWithClass: and initWithClass:andCapacity: supported"
userInfo:nil];
#throw myException;
}
- (id)initWithArray:(NSArray *)anArray { return NotSupported(); }
- (id)initWithArray:(NSArray *)array copyItems:(BOOL)flag { return NotSupported(); }
- (id)initWithContentsOfFile:(NSString *)aPath { return NotSupported(); }
- (id)initWithContentsOfURL:(NSURL *)aURL { return NotSupported(); }
- (id)initWithObjects:(id)firstObj, ... { return NotSupported(); }
- (id)initWithObjects:(const id *)objects count:(NSUInteger)count { return NotSupported(); }
#end
Use as:
MonomorphicArray *monoString = [[MonomorphicArray alloc] initWithClass:[NSString class] andCapacity:3];
[monoString addObject:#"A string"];
[monoString addObject:[NSNumber numberWithInt:42]]; // will throw
[monoString addObject:#"Another string"];
Since Xcode 7, generics are available in Objective-C.
You can declare a NSMutableArray as:
NSMutableArray <Wheel*> *wheels = [[NSMutableArray alloc] initWithArray:#[[Wheel new],[Wheel new]];
The compiler will give you a warning if you try to put non-Wheel objects in the array.
I could be wrong (I'm a noob), but I think, if you create a custom protocol and make sure the objects you are adding to the array follow the same protocol, then when you declare the array you use
NSArray<Protocol Name>
That should prevent objects being added that do not follow the said protocol.
as per i know.. before you added any object in wheels mutableArray, u have to add some check mark. Is the object which i am adding is class "wheel". if it is then add, other wise not.
Example:
if([id isClassOf:"Wheel"] == YES)
{
[array addObject:id)
}
Something like this. i dont remember the exact syntax.
I hope this will help (and work... :P )
Wheel.h file:
#protocol Wheel
#end
#interface Wheel : NSObject
#property ...
#end
Car.h file:
#import "Wheel.h"
#interface Car:NSObject
{
NSString *model;
NSString *make;
NSMutableArray<Wheel, Optional> *wheels;
}
#end
Car.m file:
#import "Car.h"
#implementation Car
-(id)init{
if (self=[super init]){
self.wheels = (NSMutableArray<Wheel,Optional>*)[NSMutableArray alloc]init];
}
return self;
}
#end
Xcode 7 allows you to define Arrays, Dictionaries, and even your own Classes as having generics. The array syntax is as follows:
NSArray<NSString*>* array = #[#"hello world"];
I don't believe there's any way to do it with NSMutableArray out of the box. You could probably enforce this by subclassing and overriding all the constructors and insertion methods, but it's probably not worth it. What are you hoping to achieve with this?
That's not possible; an NSArray (whether mutable or not) will hold any object type. What you can do is to create your own custom subclasses as already suggested by Jim. Alternatively, if you wanted to filter an array to remove objects that weren't of the type you want, then you could do:
- (void)removeObjectsFromArray:(NSMutableArray *)array otherThanOfType:(Class)type
{
int c = 0;
while(c < [array length])
{
NSObject *object = [array objectAtIndex:c];
if([object isKindOfClass:type])
c++;
else
[array removeObjectAtIndex:c];
}
}
...
[self removeObjectsFromArray:array otherThanOfType:[Car class]];
Or make other judgments based on the result of isKindOfClass:, e.g. to divide an array containing a mixture of Cars and Wheels into two arrays, each containing only one kind of object.
You can use the nsexception if you dont have the specific object.
for (int i = 0; i<items.count;i++) {
if([[items objectAtIndex:i] isKindOfClass:[Wheel class]])
{
// do something..!
}else{
[NSException raise:#"Invalid value" format:#"Format of %# is invalid", items];
// do whatever to handle or raise your exception.
}
}
Here's something I've done to avoid subclassing NSMutableArray: use a category. This way you can have the argument and return types you want. Note the naming convention: replace the word "object" in each of the methods you will use with the name of the element class. "objectAtIndex" becomes "wheelAtIndex" and so on. This way there's no name conflict. Very tidy.
typedef NSMutableArray WheelList;
#interface NSMutableArray (WheelList)
- (wheel *) wheelAtIndex: (NSUInteger) index;
- (void) addWheel: (wheel *) w;
#end
#implementation NSMutableArray (WheelList)
- (wheel *) wheelAtIndex: (NSUInteger) index
{
return (wheel *) [self objectAtIndex: index];
}
- (void) addWheel: (wheel *) w
{
[self addObject: w];
}
#end
#interface Car : NSObject
#property WheelList *wheels;
#end;
#implementation Car
#synthesize wheels;
- (id) init
{
if (self = [super init]) {
wheels = [[WheelList alloc] initWithCapacity: 4];
}
return self;
}
#end
protocol maybe a good idea:
#protocol Person <NSObject>
#end
#interface Person : NSObject <Person>
#end
to use:
NSArray<Person>* personArray;
There is one-header file project which allows this:
Objective-C-Generics
Usage:
Copy ObjectiveCGenerics.h to your project.
When defining a new class use the GENERICSABLE macro.
#import "ObjectiveCGenerics.h"
GENERICSABLE(MyClass)
#interface MyClass : NSObject<MyClass>
#property (nonatomic, strong) NSString* name;
#end
Now you can use generics with arrays and sets just as you normally do in Java, C#, etc.
Code: