Can I override how #synthesize works in Objective C? - objective-c

I'm creating a base class that has an isDirty flag. It is set any time one of its properties changes, but since it's a base class, it doesn't know what its properties are. So basically, on every subclass, I have to override every - set: method to something like this:
- (id) setName:(NSString *)value {
if ([name isEqualToString:value]) {
return;
}
[name autorelease];
name = [value retain];
isDirty = YES; //Here's the important bit
}
Almost every line of that is what the automatically-synthesized setter would do. Is there any way I can override what #synthesize actually creates?
There are other options I have come up with, but they all seem like they would be much slower at runtime than this method. I've thought of things like adding an object to observe its own property changes, or creating a generic function to do all that and just pass in the address to the iVar and the new value, but that still requires overriding the setter.
Any ideas? If it makes a difference, it's for an iPhone app.

Several issues here:
(1) If you are concerned about setter performance, you shouldn't be using -isEqualToString: in your setter. Do a pointer compare instead because that is all that matters in this context.
(2) If you have an NSString attribute, you should be copying on set. Copy is free for immutable strings and will save your bacon for mutable strings (by preventing the caller from mutating the string out from under you).
(3) Again with performance; you checked for equality, but then use autorelease. That incurs unnecessary overhead.
(4) * they all seem like they would be much slower at runtime* indicates that you haven't actually tried it, haven't identified a performance problem, and are prematurely optimizing your code. Given (1) and (3), there is likely much more easily addressed performance issues.
My suggestions:
(1) Use #synthesize. It will generate correct and fast code, addressing (1) and (3).
(2) Use KVO or one of the other mechanisms. Until you identify a performance problem through instrumentation and quantification, you don't have a performance problem.
(3) Consider using CoreData (unless, of course, you are targeting OS 2.x). The example code is from something that is obviously a model object. If your code is nicely factored into model/view/controller, using CoreData at the model layer can both simplify your application and CoreData does a wonderful job of change tracking.

There's no way I know of that enables you to override what #synthesize does.
At the end of the day, it's used for creating basic accessor methods - ie. those that don't have specific behaviour.
Maybe you should look into Key Value Coding and Key Value Observing?

There isn't.
What you want to achieve is only possible by digging deep into the Objective-C runtime or by using proxy objects.
Why don't you have a look at KVO again?

If you write your own accessor method(s) #synthesize respects that. #synthesize gives precedence to accessors you write on your own. Just provide the accessor you like and #synthesize will be ignored on that one. For example you could implement an accessor that creates the property only in case it isn't already there.
Example:
#synthesize standardUserDefaults;
- (NSUserDefaults *)standardUserDefaults {
NSLog(#"standardUserDefaults");
if (!standardUserDefaults) {
NSLog(#"standardUserDefaults new");
self.standardUserDefaults = [NSUserDefaults standardUserDefaults];
}
return standardUserDefaults;
}
Here the "setter" is synthesized while the "getter" is not.

Related

Clarification on custom init methods / pointers in general for objective c objects

When I have my own init method with synthesized properties as such:
#property (copy, nonatomic) NSString *bookName;
#property (strong, nonatomic) NSMutableArray *book;
When I want to initialize with my own custom initializer I am shown to write it like this:
-(id) initWithName: (NSString *)name
{
self = [super init]
if (self) {
bookName = [NSString stringWithString: name];
book = [NSMutableArray array];
}
return self;
}
Now I want to clarify something. I know why it uses the stringWithString method, because instead of just passing the address to the passed in string it'll create a new object so that it owns the string itself. Could I not also just write it like so:
self.bookName = name;
Doing this should use the synthesized method and actually create a new object right? Basically both accomplish the same thing. I ask because there are methods else where that show doing it both ways so I just want to make sure there are no other issues that could crop up with using one way or the other. They both appear to do the same thing in different ways (using the synthesized method vs directly modifying the class variable but creating a new object in memory for it).
I'll also point out that this is in an ARC environment.
(Note that I am assuming the above is ARC code; otherwise it is incorrect.)
You should almost always use accessors to access your ivars (even in ARC). However, there is some controversy about whether init should use accessors or directly access its ivars. I have switched sides in this controversy, but it's not an obvious decision IMO.
The primary argument for not allowing init to use accessors is that it is possible that a future (unknown) subclass might create side-effects in the accessor. You generally don't want side effects happening during your init. For instance, you probably don't want to post change notifications when you're setting something to its initial value, and it is possible that your object is in an "undefined state" and would be dangerous to read at this point.
That said, and while this argument did finally sway me, I have never once encountered this situation on numerous projects of various sizes with several teams. I have many times encountered developers failing to retain when setting their ivars in init (as you have done above, and which would crash if it is not ARC). This is why for a long time I recommended using accessors even in init. But in theory it does create a danger, particularly if you are a closed-source framework writer (i.e. Apple). And so, for my own code I now avoid accessors in init. If I were working with a more junior teams on older retain/release code, I would probably still have them use accessors in init. It's just avoided so many crashes in my experience.
It is not controversial that you should avoid calling accessors in dealloc, however. This definitely can lead to bizarre side-effects in the middle of destroying your object.
You are correct, since bookName is declared as copy, assigning self.bookName would make a copy of the string passed in. I am not certain that copying would go through exactly the same code path as the [NSString stringWithString: name], but it would achieve the same purpose of creating a copy of the original string, shielding you from unexpected consequences of users passing in a mutable object and mutating its value behind your back.
Because the declared property is copy then yes, they are doing the same thing.
Many times however, it is a strong and then there would be a difference between the two methods so the first method would be the "correct" way of doing it.

Dynamic Getters and Setters with Objective C

I am in a situation where I want to dynamically generate getters and setters for a class at runtime (in a similar manner to what NSManagedObject does behind the scenes). From my understanding, this is possible using resolveInstanceMethod: on a specific class. At this point, you would have to use class_addMethod to dynamically add the method based on the selector. I understand this at a theoretical level, but I haven't delved much into the obj-c runtime, so I was curious if there were any great examples of how to do this. Most of my knowledge comes from this article:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html
Any thoughts / examples?
The only nice discussion I know is at Mike Ash's blog post. It's not that hard, actually.
I once needed to split a big NSManagedObject subclass into two, but decided to keep the fact an implementation detail so that I don't have to rewrite other parts of my app. So, I needed to synthesize getter and setter which sends [self foo] to [self.data foo], automatically.
To achieve that, I did the following:
Prepare the new method, already in my class.
- (id)_getter_
{
return objc_msgSend(self.data, _cmd);
}
- (void)_setter_:(id)value
{
objc_msgSend(self.data, _cmd,value);
}
Note that _cmd has the selector in it. So, usually, _cmd is either #selector(_getter_) or #selector(_setter_) in these methods, but I'm going to plug the implementation of _getter_ as the implementation of foo. Then, _cmd contains #selector(foo), and thus calls self.data's foo.
Write a generic synthesizing method:
+(void)synthesizeForwarder:(NSString*)getterName
{
NSString*setterName=[NSString stringWithFormat:#"set%#%#:",
[[getterName substringToIndex:1] uppercaseString],[getterName substringFromIndex:1]];
Method getter=class_getInstanceMethod(self, #selector(_getter_));
class_addMethod(self, NSSelectorFromString(getterName),
method_getImplementation(getter), method_getTypeEncoding(getter));
Method setter=class_getInstanceMethod(self, #selector(_setter_:));
class_addMethod(self, NSSelectorFromString(setterName),
method_getImplementation(setter), method_getTypeEncoding(setter));
}
Note that this is a class method. So self stands for the class. Note also that I didn't hardcode type encodings (which tells Objective-C runtime what the arguments of the particular method are). The syntax of type encodings is documented, but constructing by hand is very error-prone; I wasted a few days that way until Mike Ash told me to stop it. Generate it using an existing method.
Generate forwarders at the earliest possible time:
+(void)load
{
for(NSString*selectorName in [NSArray arrayWithObjects:#"foo", #"bar", #"baz",nil]){
[self synthesizeForwarder:selectorName];
}
}
This generates foo, setFoo:, bar, setBar:, and baz, setBaz:.
Hope this helps!
Another example is one I wrote, called DynamicStorage, available here:
https://github.com/davedelong/Demos
The primary impetus behind it was this question, which was asking how to use an NSMutableDictionary as the backing store for any object ivar. I wrote a class that will generate getters and setters for any #property, respecting things like a custom getter/setter name, the object memory management policy, etc. The neat thing about it is that it's using imp_implementationWithBlock() so that it only has to calculate the appropriate property name once (and then captures and saves it as part of the block).

How to initialize a class with many constructor arguments?

I have a class that takes many arguments to create. It’s a sort of an audio processor that needs a sample rate, sample resolution, number of channels etc. Most of the parameters have sane defaults. And most of them should be only settable in the initializer (constructor), because it makes no sense to change them afterwards. I do not want to create a gargantuan initializer with all the parameters because (1) it would be huge and essentially it would only copy the passed values, doing no real work, and (2) the user would have to specify values for all the parameters. What’s a good way to solve this?
I’ve tried writing getters and setters for the params. This means that I could not create the “real” audio processing unit in the constructor, since the parameter values are not known then. I had to introduce a new method (say prepareForWork) so that the users can do something like:
AudioProcessor *box = [[AudioProcessor alloc] init];
[box setSampleRate:…];
[box setNumberOfChannels:…];
[box prepareForWork];
[box doSomeProcessing];
This is nice because it does not require an unwieldy constructor. Also the defaults are set in the initializer which means that I can take a fresh AudioProcessor instance and it could still do some work. The flip side is that (1) there is an extra method that has to be called before the instance can do any real work and (2) the class should refuse to change any of the parameters after prepareForWork was called. Guarding both these invariants would take some boilerplate code that I don’t like.
I thought I could create a special “preset” class that would look like this:
#interface SoundConfig : NSObject {
NSUInteger numberOfChannels;
NSUInteger sampleResolution;
float sampleRate;
}
And then require an instance of this class in the AudioProcessor initializer:
#interface AudioProcessor : NSObject {…}
- (id) initWithConfig: (SoundConfig*) config;
Default values would be set in the SoundConfig initializer, the AudioProcessor constructor would be simple and there would be no invariants to keep watching by hand.
Another approach I thought of was a kind of AudioProcessorBuilder class. You would create an instance of that, set the audio params through accessors and then finally it would build an AudioProcessor instance for you, setting all the properties through a non-public setters so that you could not change them later (and break the invariant).
Now that I write this I favour the SoundConfig approach. How do you solve this, is there a better approach?
See how NSURLConnection is implemented and used. It uses an NSURLRequest object to parameterise it, similarly to the way your SoundConfig object parameterises the AudioProcessor object.
The usual way is indeed to create a gargantuan initializer together with several initializers for non default values or sets of values.
-initWithSampleRate:numberOfChannels:sampleResolution:
-initWithSampleRate:sampleResolution:
-initWithSampleRate:numberOfChannels:
-initWithNumberOfChannels:sampleResolution:
-initWithNumberOfChannels:
-initWithSampleResolution:
-initWithSampleRate:
-init
But the SoundConfig approach looks simpler.
Usually, when you have class with many constructor parameters, especially when some or most of them are optional, you want to use Builder Pattern. Funny thing, I cannot find examples for objective-c, so I am not sure if it could be easily applied here...

Avoiding #property-itis (i.e. overuse of properties, when are they appropriate)?

Objective-C 2.0 gave us #properties.
They allow for introspection.
They allow for declarative programming.
The #synthesize and #dynamic mechanisms relieve use from having to write repetitive, stock accessors.
Finally, there is the ‘dot’ property syntax, which some love, and some hate.
That isn't what I'm hear to ask. Like any new feature, there is an initially tendency to want to use #property everywhere. So where is property use appropriate?
Clearly in model objects, attributes and relationships are good fodder for properties.
#property(...) NSString *firstName;
#property(...) NSString *lastName;
#property(...) Person *parent;
Even synthesized/computed attributes seem like a good use case for properties.
#property(...) NSString *fullName;
Where else have you used properties? Where have you used them, then later decided it was an inappropriate use of the feature?
Do you use properties for your private object attributes?
Can you think of any examples of things which aren't properties in Cocoa, which at first look, seem like they might want to be properties, but after closer inspection, are actual an example of abuse or property-itis?
My recommendation to people is to use property's wherever possible. If you are working in a framework, the ability to use non-fragile instance variables in the modern runtime is a huge bonus and if you aren't, properties make it clear how your ivars are to be managed (assigned vs retained vs copied). There isn't an inherent performance loss from declaring a property other than the time it takes to write the line of code (I actually use a TextExpander snippet to do this for me) but the potential for preventing bugs is large enough that it becomes a fantastic best-practice. If you do plan to user properties for private ivars, you can do so inside your implementation file via an #interface block. For example
#interface MyObject()
#property(retain) NSArray *myArray;
#end
If I had to think of a reason to avoid them, I'd say don't use it for computed attributes where the computation involved is significant. Properties encourage code like:
if (foobar.weight > 100) {
goober.capacity = foobar.weight;
}
In this example, foobar.weight is called twice. If it's just returning a cached value, no problem. But if it needs to block the thread while it deploys a robot to manually weigh the foobar each time, the above snipped of code would waste two robot deployments when only one is needed.
In such cases, I'd recommend NOT using a property, and also naming the method differently, so that the code would look more like:
int w = [foobar computeWeight];
if (w > 100) {
goober.capacity = w;
}
With a name like computeWeight it is easier to remember that it is a long running operation.
I would avoid using properties if the accessor method does something non-obvious to the object, like setting an unrelated instance variable. Also if the property being returned doesn't really "belong" to the object. For instance, in one of my projects I have a stringValue method that I decided not to make a property for this reason. This is really more a matter of style though.

Performance difference between dot notation versus method call in Objective-C

You can use a standard dot notation or a method call in Objective-C to access a property of an object in Objective-C.
myObject.property = YES;
or
[myObject setProperty:YES];
Is there a difference in performance (in terms of accessing the property)? Is it just a matter of preference in terms of coding style?
Dot notation for property access in Objective-C is a message send, just as bracket notation. That is, given this:
#interface Foo : NSObject
#property BOOL bar;
#end
Foo *foo = [[Foo alloc] init];
foo.bar = YES;
[foo setBar:YES];
The last two lines will compile exactly the same. The only thing that changes this is if a property has a getter and/or setter attribute specified; however, all it does is change what message gets sent, not whether a message is sent:
#interface MyView : NSView
#property(getter=isEmpty) BOOL empty;
#end
if ([someView isEmpty]) { /* ... */ }
if (someView.empty) { /* ... */ }
Both of the last two lines will compile identically.
Check out article from Cocoa is My Girlfriend. The gist of it, is that there is no performance penalty of using one over the other.
However, the notation does make it more difficult to see what is happening with your variables and what your variables are.
The only time you'll see a performance difference is if you do not mark a property as "nonatomic". Then #synthesize will automatically add synchronization code around the setting of your property, keeping it thread safe - but slower to set and access.
Thus mostly you probably want to define a property like:
#property (nonatomic, retain) NSString *myProp;
Personally I find the dot notation generally useful from the standpoint of you not having to think about writing correct setter methods, which is not completely trivial even for nonatomic setters because you must also remember to release the old value properly. Using template code helps but you can always make mistakes and it's generally repetitious code that clutters up classes.
A pattern to be aware of: if you define the setter yourself (instead of letting #synthesize create it) and start having other side effects of setting a value you should probably make the setter a normal method instead of calling using the property notation.
Semantically using properties appears to be direct access to the actual value to the caller and anything that varies from that should thus be done via sending a message, not accessing a property (even though they are really both sending messages).
As far as I've seen, there isn't a significant performance difference between the two. I'm reasonably certain that in most cases it will be 'compiled' down to the same code.
If you're not sure, try writing a test application that does each method a million times or so, all the while timing how long it takes. That's the only way to be certain (although it may vary on different architecture.)
Also read this blog post on Cocoa with Love:
http://cocoawithlove.com/2008/06/speed-test-nsmanagedobject-objc-20.html
There the author compares the speed of custom accessor and dot notations for NSManagedObject, and finds no difference. However, KVC access (setValue:forKey:) appears to be about twice as slow.