Search code examples
iosios6ios7subclassuiswitch

Add behaviour to UISwitch


I am using UISwitch in many places of my IOS app. Some of them are stock UISwitch and some of them are subclassed. The thing is in iOS 6 VS iOS 7 the size changes. So I wrote this method :

-(void)layoutSubviews{
    if ([[[UIDevice currentDevice]systemVersion]intValue]<7) {
        self.frame = CGRectMake(self.frame.origin.x-28, self.frame.origin.y, self.frame.size.width, self.frame.size.height);
    }
}

I can change every subclass and add this method but I don't think this is the wright approach. How can I set this class to effect the base UISwitch class?


Solution

  • You only want the frame property to change when setFrame: is called. Try writing a category of UISwitch that overrides setFrame: A category will be inherited by all subclasses, and because setFrame: is inherited from UIView, and is not declared in UISwitch, you can override the setter.

    something like this perhaps-

    // UISwitch+UISwitchAdditions.h
    #import <UIKit/UIKit.h>
    
    @interface UISwitch (UISwitchAdditions)
    
    - (void)setFrame:(CGRect)frame;
    
    @end
    

    and now the .m

    //  UISwitch+UISwitchAdditions.m
    
    #import "UISwitch+UISwitchAdditions.h"
    
    #define X_OFFSET -28.0 // tweak your offset here
    
    @implementation UISwitch (UISwitchAdditions)
    
    -(void)setFrame:(CGRect)frame {
        // get OS version
        float osVersion = [[UIDevice currentDevice].systemVersion floatValue];
        // now the conditional to determine offset
        if (osVersion < 7.0) {
            // offset frame before calling super
            frame = CGRectOffset(frame, X_OFFSET, 0.0);
            [super setFrame:frame];
        }
        else {
            // no offset so just call super
            [super setFrame:frame];
         }
    }
    
    @end
    

    I think @KudoCC has a valid point about layoutSubviews. Remember to import the header of your category (in this example UISwitch+UISwitchAdditions.h) into any class that will be calling setFrame: If you find yourself importing it into lots of classes then you could consider placing it in your pre compiled header instead. I used CGRectOffset in this example where you used CGRectMake.