Skip to content

Instantly share code, notes, and snippets.

@fabiorodella
Created February 22, 2016 18:10
Show Gist options
  • Save fabiorodella/96ce303ac29e6eed3291 to your computer and use it in GitHub Desktop.
Save fabiorodella/96ce303ac29e6eed3291 to your computer and use it in GitHub Desktop.
#import <UIKit/UIKit.h>
#import <Motif/Motif.h>
NS_ASSUME_NONNULL_BEGIN
/**
* Extension that allows defining a global theme applier, which will be used
* when a class is set via Storyboard/XIB and a theme name is ommited.
*/
@interface UIView (MotifDefaultTheme)
/**
* Sets the default theme applier.
*
* @param themeApplier the theme applier to be set, or nil to unset the current applier.
*/
+ (void)setDefaultMotifThemeApplier:(nullable id<MTFThemeApplier>)themeApplier;
/**
* Creates a theme applier from the theme name and sets it as default.
*
* @param themeFile the theme name to be used by the new default applier, or nil
* to unset the current applier.
*/
+ (void)setDefaultMotifThemeApplierWithFileNamed:(nullable NSString *)themeFile;
/**
* Creates a theme applier from an array of theme names and sets it as default.
*
* @param themeFiles the theme names to be used by the new default applier, or nil
* to unset the current applier.
*/
+ (void)setDefaultMotifThemeApplierWithFilesNamed:(nullable NSArray<NSString *> *)themeFiles;
/**
* The current default theme applier.
*
* @return current default theme applier, or nil if not set.
*/
+ (nullable id<MTFThemeApplier>)defaultMotifThemeApplier;
@end
/**
* Extension that allows setting a Motif theme name and Class for any UIView in a
* Storyboard or XIB file. If the theme name is ommited, the default theme applier
* will be used if set.
*/
@interface UIView (MotifStoryboard)
/**
* The theme name to be used. You should prefer to use a default theme applier instead,
* since setting this causes a new theme applier to be created every time the class is changed.
*/
@property (nonatomic, strong, nullable) IBInspectable NSString *motifTheme;
/**
* The class to be used by this element.
*/
@property (nonatomic, strong, nullable) IBInspectable NSString *motifClass;
@end
NS_ASSUME_NONNULL_END
#import "UIView+Motif.h"
#import <objc/runtime.h>
@implementation UIView (MotifDefaultTheme)
+ (void)setDefaultMotifThemeApplier:(id<MTFThemeApplier>)themeApplier {
objc_setAssociatedObject(self, @selector(defaultMotifThemeApplier), themeApplier, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
+ (void)setDefaultMotifThemeApplierWithFileNamed:(NSString *)themeFile {
[self setDefaultMotifThemeApplierWithFilesNamed:(themeFile != nil ? @[themeFile] : nil)];
}
+ (void)setDefaultMotifThemeApplierWithFilesNamed:(NSArray<NSString *> *)themeFiles
{
id<MTFThemeApplier> themeApplier = nil;
if (themeFiles != nil) {
NSError *error = nil;
themeApplier = [MTFTheme themeFromFilesNamed:themeFiles
error:&error];
if (error != nil) {
NSLog(@"<Motif/Error> Error creating theme applier: %@", error);
}
}
[self setDefaultMotifThemeApplier:themeApplier];
}
+ (id<MTFThemeApplier>)defaultMotifThemeApplier {
return objc_getAssociatedObject(self, @selector(defaultMotifThemeApplier));
}
@end
@implementation UIView (MotifStoryboard)
@dynamic motifTheme;
@dynamic motifClass;
- (NSString *)motifTheme {
return objc_getAssociatedObject(self, @selector(motifTheme));
}
- (void)setMotifTheme:(NSString *)motifTheme {
objc_setAssociatedObject(self, @selector(motifTheme), motifTheme, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)motifClass {
return objc_getAssociatedObject(self, @selector(motifClass));
}
- (void)setMotifClass:(NSString *)motifClass {
objc_setAssociatedObject(self, @selector(motifClass), motifClass, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
if (motifClass == nil) {
return;
}
id<MTFThemeApplier> themeApplier = [UIView defaultMotifThemeApplier];
if (self.motifTheme != nil) {
NSError *error = nil;
themeApplier = [MTFTheme themeFromFileNamed:self.motifTheme
error:&error];
if (error != nil) {
NSLog(@"<Motif/Error> Error creating theme applier: %@", error);
}
}
if (themeApplier != nil) {
NSError *error = nil;
[themeApplier applyClassWithName:self.motifClass
to:self
error:&error];
if (error != nil) {
NSLog(@"<Motif/Error> Error applying class: %@", error);
}
} else {
NSLog(@"<Motif/Error> No theme to use for class '%@' in %@. Either set a value for Motif Theme, or set the default theme applier in UIView", motifClass, self);
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment