conditional implementations of methods - iphone

ok.. think of objectA.. objectA has optional properties defined in its protocol. the delegate may or may not implement these, but if you do decide to implement them, you must provide a valid return.
now what if i have objectA.delegate set to objectB but object be needs to implement them all at compile time, and at runtime will decide which ones it may or may not support.
The problem in implementing them all as stubs means that the objectA will simply use 'respondsToSelector' to see if the delegate is trying to use optional properties, and if so it will assume they are valid and use them.
Since objectB(delegate) has to decide conditionally which ones to implement, the only solution i can see is to use 'class_addMethod'.
I was hoping there could be a more elegant and possibly more optimal solution, but not sure as what it may be.

Anytime you think you need to use class_addMethod() to implement something, you are almost always doing it wrong.
From what you describe-- which is rather vague-- an easy solution would be to create something that can both act as the delegate and can conditionally forward the methods, as needed.
Now, you say that if the delegate does implement a method it must return a valid value. If that is the case, class_addMethod() isn't really going to help. Most classes that implement delegates will check once if the delegate implements the method and then will assume it does forever unless the delegate changes. You could get into the business of switching delegates often, but down that path lies madness.
A better answer might be to ask a question; what are you trying to do?

Yeah, use NSObject's + (BOOL)resolveInstanceMethod:(SEL)aSEL in combination with class_AddMethod and hook up the implementation you want based on whatever criteria you want. Not sure if this is what you are looking for or not. Hope it helps.

Related

Obj-c runtime: find what class another class is a property of

Suppose I have this:
#interface ThingManager : NSObject
#property Thing *aThing;
#end
Is there a way for aThing to know at runtime that it is a property of ThingManager?
You start with the question:
Is there a way for aThing to know at runtime that it is a property of ThingManager?
Though not completely clear the answers so far have assumed you want aThing to be able to determine whether an instance of ThingManger is managing it.
So at this point we know that the ThingManger class knows about the Thing class, and you now appear to want the reverse - you ask can a Thing find its ThingManager?
However when someone answers that you comment
So Thing and ThingManager need to know about each other? Mmmm... Bad for loose coupling.
Hmmm... How can a Thing ask what its ThingManager is if you don't want it to know about ThingManagers?
Is everybody's interpretation of your question wrong?
Maybe you are concerned not about loose coupling but about strong reference cycles? If the two know about each other, and create a strong cycle in doing so, then there is a risk they will keep each other alive long after the need for either by your application - is that the concern?
But that is addressed by #DrummerB - you use a weak property on Thing which references its managing ThingManager. So it would appear that strong reference cycles are not your concern either...
Then you comment:
Isn't there a way to see who's referencing an object at runtime?
As stated generally that is a very different question. The short answer to this is no[*].
Are you asking whether it is possible to write a method which a Thing can call to find the ThingManager that is managing it without any references being maintained between Thing instances and ThingManager instances?
If so here is an outline algorithm:
Have the ThingManager class keep a collection of all create and alive instances of itself. The alive requirement requires this collection be some kind of weak collection (design your own or do a search for weak collections).
Add a class method to ThingManager which finds the manager for a Thing, e.g. something like + (ThingManager *) managerFor:(Thing *)thing.
Have your Thing instances call [ThingManager managerFor:self] when they need to know their manager.
That of course doesn't address your concern over loose coupling - the two classes must still know of each others existence...
Which brings you back to the direct solution of having Thing have a manager property. If you want to reduce the coupling you can type this property as id, so its any old object, or id<SomeMinimalManagerProtocol> so its any old object provide it implements some minimal set of management methods you've define in the protocol SomeMinimalManagerProtocol.
Take a look at NSWindow and NSWindowController - they know about each other.
HTH
[*] The long answer is that (Objective-)C(++) are not designed to ensure all references can be found. This is why you hear phrases such as "conservative garbage collection". There was a garbage collector for just Objective-C objects, which was supported by internal changes to the runtime, but that is now deprecated and its machinery wasn't easily accessible to applications to apply to other uses.
Not unless you tell it, that it is.
You could add a ThingManager weak property to Thing and implement the setter in ThingManager like this:
- (void)setAThing:(Thing *)thing {
if (_aThing != thing) {
_aThing = thing;
_aThing.manager = self; // this is the relevant line
}
}
Not unless you have a custom setter for your aThing property that sets something on the Thing object to tell it that it is. You could have the aThing setter method set a property that you add to Thing that tells it who its manager is.

Best way to do init without repeating code?

Each view class has multiple init methods - ones already included as part of UIView, and then additional ones - and each of them set up the same elements in the same way. I therefore usually have them all running a [self initialSetup]; method, which includes the setting up of all of these elements.
The problem i've ran into is that if a subclass also has an initialSetup method, it would override the superclass initialSetup method, and thus the superclass would have to have the method be public in order to still function. This causes problems with organisation, as the method should never be called other than from init, so has no reason to be public.
You've hit upon a problem that there's no perfect fix for. What you'd ideally have is a method that can't be subclassed in the normal sense, that's accessible only to instances of that exact type of class.
Where this is a risk, the normal practice seems to be to incorporate the class name into the setup method. So instead of initialSetup you'd have something like myViewSubclassInitialSetup.
You can also add something like this at the top of your method:
NSAssert([self isMemberOfClass:[ThisClass class]],
#"IniitalSetup called by sub- or superclass")
Then your debug builds will raise an exception if a subclass or superclass ends up calling your init method. That'll give you a place for a breakpoint and a stacktrace that should allow you to find the problem very quickly.
It won't add any code to your release builds.
Change the name of initialSetup to something like initialSetupClassName - subclasses, even if they accidentally used the same pattern, would not use the same name as they had a different class name.
You can also use an "_" prefix for private methods you would rather not be called, but the subclasser may do that also.
It sounds like you are missing a designated initializer. Designate one initializer as the official one that actually performs the setup, and have all the others just call that with some degree of customization. Usually the designated initializer will be the one with the most detail — for example, if you have init, initWithName:, initWithName:age: and initAsFiveYearOldNamed:, the designated initializer will be initWithName:age: and the other initializers would just call that method with the arguments filled in appropriately.
Unfortunatly Objective C doesn't provide a way to achieve that in a "clean" way. The ideal solution would be a protected method. But that's not possible in Objective C
Apple had this problem, when they were creating the UIGestureRecognizer. There were some methods they really didn't want to get called by somebody, but which had to be overwritten by subclasses. The way they chose to deal with this, was to create a seperate header file (UIGestureRecognizerSubclass.h), that contains a category to the original UIGestureRecognizer with those "protected" methods. The additional header is only to be imported by subclasses (i.e. for subclassing purposes). See UIGestureRecognizer Class Reference for some details.
Of course that doesn't prevent anybody from misusing the additional header file, but at least it clearly states your intention and keeps your code well structured. Also you won't be "bothered" by autocompletion for the additional methods, when just using the class.
Personally I only use an additional header, if it is extremely important that nobody calls it directly. In most cases I think it's ok to use public methods and make a note for what it's inteded. The iOS Framework also has many of these cases. F.e. many methods of UIViewController's viewDidLoad etc.

Categories on NSObject -- keeping it safe

Apple has this to say:
Categories of the Root Class
A category can add methods to any class, including the root class. Methods added to NSObject become available to all classes that are linked to your code. Adding methods to the root class with a category can be useful at times, but it can also be quite dangerous. Although it may seem that the modifications the category makes are well understood and of limited impact, inheritance gives them a wide scope. You may be making unintended changes to unseen classes in your application; you may not know all the consequences of what you’re doing. Moreover, others working on your application, who are unaware of your changes, won’t understand what they’re doing.
My question is -- if I choose method names that are sufficiently weird that I am quite sure that no one else will use them (either at Apple or in my project), can I still get into trouble? Could there still be unexpected behavior? Performance implications?
If you're really quite certain that Apple would never add a method of that name, it's safe. If you want to enforce that certainty though, prefix the selector name. For example, Adium at one point added a -setObject:atIndex: method to NSMutableArray (yes, just a "cosmetic" wrapper over the existing API method -replaceObject:atIndex. Very pointless)... it turned out to have the same name as an internal method, and veeeeery slightly different semantics. This caused crashes, but only on certain OSs. If it had been named something like -AISetObject:atIndex:it would have been fine.
Performance implications for categories are minimal. I wouldn't worry about that aspect.
If your method names do not conflict with anything, and people who use them know what they do, you shouldn't run into any problems. Remember, a category adds extra methods, but not instance variables to a class. A subclass is more flexible, and is treated as an entire object, which responds to all superclass methods plus it's own. I would say make a subclass unless you can't or it's inconvenient to do so. Categories were made to be used, after all. I usually use categories when I have a framework and I need to add private methods to a publicly declared class.

Does it make a difference in performance if I use self.fooBar instead of fooBar?

Note: I know exactly what a property is. This question is about performance.
Using self.fooBar for READ access seems a waste of time for me. Unnecessary Objective-C messaging is going on. The getters typically simply pass along the ivar, so as long as it's pretty sure there will be no reasonable getter method written, I think it's perfectly fine to bypass this heavy guy.
Objective-C messaging is about 20 times slower than direct calls. So if there is some high-performance-high-frequency code with hundreds of properties in use, maybe it does help a lot to avoid unnessessary objective-c messaging?
Or am I wasting my time thinking about this?
This kind of premature optimization should really be postponed until you actually notice or measure (with Instruments.app) a real problem.
No offence, but you're probably wasting your time thinking about it. Unless you have code that accesses that property thousands of times a second, then you're not going to see any performance differences.
The two aren't really interchangeable (ok some of the times they are). Access the ivar directly when that is what you need and use the accessor methods when that is what you need. It will probably depend on the the class hierarchy, the implementation of the class, is the code thread safe etc, etc.
All things that are largely upto you if it's your code. Might someone want to subclass this class and write a custom implementation of -foobar that always returned #"BOO" but they find that the superClass method -printFooBar now prints #"hello darling" because it prints out the value of the variable foobar instead of the value returned from self.foobar ?
Calling the accessor method does have more overhead than using the variable directly, but there are more things to consider than performance. Personally i find the position "always use the accessor method" just as ridiculous as saying "never use the accessor methods" - which would clearly be ridiculous.
Yes using property getters are much slower than direct access. A property getter is useful outside of the self class (and categories) for encapsulation, but I see no benefits using a self.ivar getter, unless you have overridden the getter to something else.
(And why are you using self.ivar in the first place?)
The only cases where self.ivar will be different from self->ivar are:
The property is atomic, so self.ivar will be similar to
spin_lock(&ivar_lock);
id retval = [ivar retain];
spin_unlock(&ivar_lock);
return [retval autorelease];
for an id property, and
spin_lock(&ivar_lock);
spin_lock(&destination_lock);
memcpy(&destination, &ivar, sizeof(ivar));
spin_unlock(&ivar_lock);
spin_unlock(&destination_lock);
for a struct. There is no difference between the two when the property is nonatomic.
When the class is not final. A category of the class or a subclass can override the property getter to something else. But I think overriding a concrete property is not a good style.
Like what the others have said, unless you have tested that the getter is a hot spot, changing it back to direct ivar access won't help much.
Some may disagree, but I happen to like accessing the ivar directly and bypassing the whole messaging business where possible. I think it makes my intentions clearer, since if I ever need to message the getter (for memory management or the like), then I will.
It's a tiny bit less efficient, but you still should generally not make your object state public. Although public members are considered bad in most OO languages, there's actually a pragmatic reason why in Objective-C: The framework uses your "getter" and "setter" methods to make certain things automatic, such as memory management and KVO notifications. With ivars accessed from multiple places, every piece of client code needs to fully understand all the responsibilities that the accessor methods were taking on and perform those duties in the exact same way itself.
So it's no "absolutely don't access your own ivars," but just make sure you fully understand what it entails in a given situation.

Is an object in objective-c EVER created without going through alloc?

I know that there are functions in the objective-c runtime that allow you to create objects directly, such as class_createInstance. What I would like to know is if anything actually uses these functions other than the root classes' (NSObject) alloc method. I think things like KVC bindings might, but those aren't present on the iPhone OS (to my knowledge, correct me if I'm wrong), so is there anything that would do this?
In case you're wondering/it matters, I'm looking to allocate the size of an instance in a way that circumvents the objc runtime by declaring no ivars on a class, but overriding the +alloc method and calling class_createInstance(self, numberofbytesofmyivars).
Thanks
EDIT
I think I need to be more specific. I am adding classes to the runtime at runtime, and possibly unload and reload an altered version of the same class. I've worked around most of the issues so far, due to things like class_addMethod, but there's no equivalent for ivars after the class has been registered. The two solutions I can think of are having no actual ivars as far as the runtime is concerned, but overriding alloc to make sure I have enough room for them through extraBytes, or alternatively declaring an ivar which is a pointer to all of my actual ivars, which I can then obviously do whatever I want with. I would prefer to use the former strategy but there are a number of things that can go wrong, like if something allocates an instance of my object without going through my overloaded alloc method. Does anyone know of one of these things?
I'm not sure if you're trying to change the behavior of existing classes, which is not safe, or trying to do something for custom classes you own that are direct subclasses of NSObject, which probably is.
Almost all NSStrings you see in practice are instances of a private subclass, and that subclass allocates space for the string inline with the object. Like, instead of containing a pointer to a char*, the character data comes right after the ivars in the object. The extraBytes parameter in NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone) is there for purposes such as this.
So on the one hand, yes, you can pull tricks like that. On the other, you need to know you're doing it with your stuff. If you try to do something like that with the private subclass of NSString (which is private, so you're only going to interact with through runtime introspection), you're probably going to conflict.
There are a few public cocoa classes that also do stuff like this, so you're best off if your classes inherit directly from NSObject. NSLock is one. The layout in memory for a custom subclass of NSLock looks like { isa, <ivars of NSLock> <ivars of subclass of NSLock> <more NSLock stuff, space reserved using the extraBytes parameter> }.
Also, just for the heck of it, note that +alloc calls +allocWithZone:, and +allocWithZone: is the more common override point.
I'm not sure why you'd want to do what you're suggesting--I don't see any reason you couldn't do it, but according to this post, there's usually no reason to use class_createInstance directly (I don't know of anything that uses it specifically). class_createInstance also doesn't take into account memory zones or other possible optimizations used by alloc. If you're just trying to hide your ivars, there are better ways.
EDIT: I think you're looking for the class_addIvar function, which (as the name suggests) dynamically adds an ivar to a class. It only works with the new runtime, so it won't work on the simulator, but it will work on the iPhone.
EDIT 2: Just to be totally clear (in case it wasn't already), you can definitely rely on allocWithZone always being called. Fundamental Cocoa classes, such as NSString and NSArray, override allocWithZone. class_createInstance is almost never used except at the runtime level, so you don't have to worry about any parts of Cocoa using it on your classes. So the answer to the original question is "no" (or more specifically, objects are sometimes created without alloc, but not without allocWithZone, at least as far as I know).
Well there is nothing technically to stop you from overriding alloc. Just create a method in your class called +alloc. I just can't imagine any reason why you would need to.
Sounds like you are trying too hard to manage memory. Let the OS dynamically allocate memory when you create an object. If you are using too much, the OS will send a notification that you are getting close to the limit. At that point you can dealloc stuff you don't need anymore.
If you need so much memory that you have to use tricks, your implementation may need rethinking at the core level instead of trying to fit your square design into the round hole of the iPhone OS.
Just my opinion based on the info you provided.