0

I have a property

@property (strong, nonatomic, readonly) NSMutableArray*     myArray;

and I want to lazily create the array in the getter

- (NSMutableArray*)myArray
{
    if(_myArray == nil)
    {
        _myArray = [NSMutableArray arrayWithCapacity:4];
    }
    return _myArray;
}

but this breaks the automatic synthesis of the iVar (`_myArray), negating some of the benefits of automatic synthesis meaning you have to do things the old way.

This is a very common pattern and it would be nice to have automatic synthesis of a lazy-create version of the getter. I guess this would take an extension to the Objective-C language and compilers, for example with an additional property attribute like this:

@property (strong, nonatomic, readonly, lazycreate) NSMutableArray*     myArray;

Any class that implements a pre-defined class method (in a similar way to object subscripting described here) such as + (ClassType*)defaultConstructor could support the lazycreate property attribute and automatic synthesis could then synthesize the getter in my example like this:

- (NSMutableArray*)myArray
{
    if(_myArray == nil)
    {
        _myArray = [NSMutableArray defaultConstructor];
    }
    return _myArray;
}

Am I right that this would require a language extension, or is there a clever way to achieve it now?

Are there any problems or pitfalls with this idea and what are they?

How do I propose this idea into the Objective-C language?

jhabbott
  • 18,461
  • 9
  • 58
  • 95
  • It only breaks it if you use the readonly option. In the cases where you use that, is it really so hard to write, @synthesize myArray = _myArray;? – rdelmar Aug 21 '12 at 02:46
  • No, it's not hard. The primary benefit of synthesized code is that it is more reliable (less error-prone) than manually written code. Not having to type a line is a relatively minor benefit. – jhabbott Aug 21 '12 at 02:54

2 Answers2

1

Adding a new property attribute like lazycreate requires modifying the compiler. You can ask Apple to add it by opening a new problem at http://bugreport.apple.com. The product is “Developer Tools” and the classification is “Feature (New)”.

You could define a macro like this:

#define synthesizeLazy(Type, Property) \
    synthesize Property = _##Property; \
    - (Type *)property { \
        if (_##Property == nil) { _##Property = [[Type alloc] init]; } \
        return _##Property; \
    }

and then use it to synthesize your lazy properties like this:

@synthesizeLazy(NSMutableArray, myArray);

There's no good way to fake it with completely automatic synthesis.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • That's a really good idea for how to do it now. Then the default constructor method could be added to supported classes in categories. Also, if considered as a language extension an alternate @synthesize might be more appropriate than a property attribute. I don't actually want to do this in my code - I'm just exploring how the language might be extended and improved even more than it already is. – jhabbott Aug 21 '12 at 10:00
0

You should check out the metaprogramming methods available on NSObject, such as -implementationForMethod. This allows you to provide an implementation of a missing method at runtime.

You can use this to provide a getter/setter dynamically for any declared properties.

You might then read from a dictionary of default values..

You could also try overriding -valueForUndefinedKey:

This might help: https://gist.github.com/2370784

nielsbot
  • 15,922
  • 4
  • 48
  • 73