Replacing the content of UIImage(s) loaded from XIB at runtime
For a concept I'm developing, I need to load XIB files manually and by using class and instance method swizzling I have been able to intercept calls to imageCustomNamed, imageCustomWithContentsOfFile and imageCustomWithCGImage for the UIImage class and initCustomWithImage for UIImageView. What I want to to is detect the image name and replace it with some content rendered on the fly in place of the one set in IB at design time.
for example:
when XIB has an UIImageView object whose Image property is set to "About.png", I need to intercept the loading of that image and replace with another one depending on certain condition. It would be ok even to replace the image after the UIImageView object has loaded the image set at design time, but looks like the original name of the UIImage used to set the content of UIImageView is not stored anywhere.
I cannot use IBOutlets as I don't know the content of XIB file before hand; this is a class that should work on any XIB not just a particular one.
The custom methods are in fact being called in placed of the default ones, but looks like that when loading XIb the system uses imageCustomWithCGImage which accept a CGImageRe开发者_JAVA技巧f as argument; from it there is no way to know the origin (i.e: the image file name)
Any idea on how I can intercept the loading of images?
In OS 3, at least, you can override UIImageNibPlaceholder's initWithCoder:. Replace it with something like this:
-(id)hack_UIImageNibPlaceholder_initWithCoder:(NSCoder*)coder
{
NSString * name = [coder decodeObjectForKey:@"UIResourceName"];
[self release];
return [[UIImage imageNamed:name] retain];
}
I'm not sure what happens if you load nibs from other bundles (e.g. frameworks).
Perhaps you can set another property of UIImageView in xib file, and then reference that property? For example label, or tag...
It's not a good idea to swizzle a private class(UIImageNibPlaceholder)'s method.
But you can overload its superclass(UIImage)'s method. Seems like UIImageNibPlaceholder did't implement 'awakeAfterUsingCoder', so you can safely do this until Apple did it one day.
#import "UIImage+xib.h"
@implementation UIImage (xib)
- (id)awakeAfterUsingCoder:(NSCoder *)coder{
NSString* imageName = [coder decodeObjectForKey:@"UIResourceName"];
if(imageName){
return [UIImage imageNamed:imageName];
}
return self;
}
@end
精彩评论