4

Here's a situation I come across a lot, enough that the boilerplate code is wasteful and enough that I'm sure I can't be the only one. Is this unidiomatic, is there a better way, or do I just have to do it each time?

@interface SomeUIElement : UIView
@property CGFloat insetMargin; // <-- just an example of a UI parameter
@end

@implementation SomeElement
- (void)setInsetMargin:(CGFloat)insetMargin {
    _insetMargin = insetMargin;
    [self setNeedsDisplay]; // <-- the only thing that stops it being synthesized
}
@end

now this raises a compile warning, that I don't have a getter, to get rid of that I can add

- (CGFloat)insetMargin {
    return _insetMargin;
}

but now, it complains I don't have an ivar (because a defined getter and setter means one isn't created for me), so I need to add

@interface SomeUIElement () {
    CGFloat _insetMargin;
}

which means we're at a substantial overhead for just wanting to force a display update when a property changes.

Is there (a) some way to tell ObjC that I did intend it to create the getter and ivar for me, so I only need to write the setter, or (b) a better way to request a display update when a property related to the visual appearance changes?

How does Apple's SDKs do this (I'm assuming I haven't missed some way of viewing, say the UILabel source)?

Ian
  • 3,619
  • 1
  • 21
  • 32
  • Do you need the property to be atomic? That's what's causing the failure of synthesis and thus the compiler complaints. – jscs Aug 03 '13 at 01:02
  • Ah, I don't really need atomicity (or, on the rare times I do, I dont mind jumping hoops) so if I put in nonatomic everywhere, even on single-word data types, it would create the ivar for me? I did not know that, thanks. You should put it in an answer! – Ian Aug 03 '13 at 01:04
  • If you declare the property as `@property (nonatomic, assign) CGFloat insetMargin` then you shouldn't need the getter or the ivar. – rmaddy Aug 03 '13 at 01:05
  • rmaddy - surely assign is irrelevant since I'm writing my own setter and explicitly 'assign'ing it. Or have I missed something there too? – Ian Aug 03 '13 at 01:11
  • 2
    You didn't put the `@` before my username so I didn't get your comment earlier. Using `assign` in the property declaration signifies a "contract". You are letting clients of the code know the semantics of the property. Of course you want your implementation to honor that contract. – rmaddy Aug 03 '13 at 04:21
  • @rmaddy - excellent point – Ian Aug 03 '13 at 15:06

1 Answers1

5

You can get "partial synthesis" if the property is declared nonatomic:

@property (nonatomic) CGFloat insetMargin;

The default (for unknown reasons) is atomic. In order to implement that atomicity, both of the accessors have to use the same locking mechanism. That mechanism isn't exposed when the methods are synthesized, though. Therefore you have to either implement both accessors and create your own lock or let the compiler do both and use its lock.

If the property is not atomic, however, you can explicitly implement any combination of the three elements: ivar, setter, or getter, and the compiler will take care of the rest. If you want to change the name of the ivar from the default (currently the property name with a prepended underscore), you will also need an explicit @synthesize.

jscs
  • 63,694
  • 13
  • 151
  • 195