我试图在我的应用中创建一个名为Theme
的类。理想情况下,我希望能够通过调用[[Theme current] background]
来调用当前主题的背景颜色。
现在,我写了一个名为Theme
的课程。
Theme.h
@interface Theme : NSObject
+ (Theme *)current;
@end
Theme.m
@implementation Theme
static Theme *current = nil;
+ (Theme *)current {
@synchronized(self) {
if (current == nil) {
current = ...This is the hard part...
}
}
return current;
}
@end
我还写了第一个主题,一个黑色主题。
Black.h
@interface Theme (Black)
+ (UIColor *)background;
@end
Black.m
@implementation Theme (Black)
+ (UIColor *)background {
return [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0];
}
@end
我遇到什么困难,我是如何指定Theme.current
成为Black
的。我该怎么做?
答案 0 :(得分:1)
对于初学者来说,这是Objective-C的单例模式(参考这是困难部分)。
@interface Theme : NSObject
+ (Theme *)current;
@end
@implementation Theme
+ (id)current {
static Theme *current = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
current = [[Theme alloc] init];
});
return current;
}
@end
由于您的应用程序将具有单例主题,因此设置背景颜色就像设置属性一样简单。但首先我们要添加属性。以下是执行此操作的更新代码:
@interface Theme : NSObject
@property (nonatomic, strong) UIColor *background;
+ (Theme *)current;
@end
@implementation Theme
+ (id)current {
static Theme *current = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
current = [[Theme alloc] init];
// You can set a default background color or leave it nil.
current.background = [UIColor cyanColor];
});
return current;
}
@end
现在要更改主题的背景,我们只需更改该属性:
[Theme current].background = [UIColor blackColor];
// ...
someView.backgroundColor = [Theme current].background;
答案 1 :(得分:1)
类别(例如,@implementation Theme (Black)
)不适合您的目的。
您应该使用属性(或至少是实例变量和getter / setter实例方法)。
所以你需要拥有你班级的财产:
@interface Theme : NSObject
@property (nonatomic, strong) UIColor *background;
@end
此属性将自动包含隐藏的getter / setter方法,因此您无需创建管理该值的方法(除非您要覆盖该行为,在这种情况下,您可以覆盖- (void)setBackground:(UIColor *)background;
和{{ 1}})。
现在您可以通过以下方式从其他代码访问该属性:
- (UIColor *)background;
如果您愿意,您还可以通过以下方式从其他代码中设置该属性:
myView.backgroundColor = [Theme currentTheme].background;
现在,如果由于任何原因你希望维护多个主题,你可以简单地将它们分配给多个实例变量或另一个类的属性,如:
[Theme currentTheme].background = [UIColor blackColor];
或者,您的主题类可以包含一些标准主题的类方法。要么像普通的类方法那样:
Theme *themeBlack = [Theme new];
Theme *themeWhite = [Theme new];
themeBlack.background = [UIColor blackColor];
themeWhite.bakcground = [UIColor whiteColor];
或者,如果它们可能被频繁调用,作为单例类方法:
+ (Theme *)blackTheme {
Theme *theme = [theme new];
theme.background = [UIColor blackColor];
return theme;
}
+ (Theme *)whiteTheme {
Theme *theme = [theme new];
theme.background = [UIColor whiteColor];
return theme;
}
无论哪种方式,现在您的其他类的其他代码现在可以是:
+ (Theme *)themeBlack {
static Theme *themeBlack = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
themeBlack = [[self alloc] init];
});
return themeBlack;
}
+ (Theme *)themeWhite {
static Theme *themeWhite = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
themeWhite = [[self alloc] init];
});
return themeWhite;
}
答案 2 :(得分:1)
@ user4992124
通过创建类别无法有效实现您想要实现的目标。您的以下声明是类别:
@interface Theme (Black)
+ (UIColor *)background;
@end
从您的问题看来,您似乎正在尝试在应用程序中创建多个主题,然后您可能会在运行时切换主题。 @keithbhunter提供的答案是一个完美的起点,但在这种情况下,每次要切换主题时都必须分配/更改多个属性。为了使它更容易一些,你可以在下面做一些事情:
typedef NS_ENUM(NSInteger, ThemeColors) {
ThemeColor_Default,
ThemeColor_Black,
ThemeColor_White
};
/* Theme.h */
@interface Theme : NSObject
@property (nonatomic, strong) UIColor *backgroundColor;
@property (nonatomic, strong) UIColor *textColor;
- (instancetype)initWithTheme:(ThemeColors)color;
@end
/* Theme.m */
@implementation Theme
- (instancetype)initWithTheme:(ThemeColors)color {
self = [super init];
if (self) {
[self populateTheme:color];
}
return self;
}
- (void)populateTheme:(ThemeColors)color {
switch (color) {
case ThemeColor_Black:
self.backgroundColor = [UIColor blackColor];
self.textColor = [UIColor whiteColor];
break;
case ThemeColor_White:
self.backgroundColor = [UIColor whiteColor];
self.textColor = [UIColor blackColor];
break;
default:
self.backgroundColor = [UIColor lightGrayColor];
self.textColor = [UIColor darkGrayColor];
break;
}
}
@end
/* ThemeManager.h */
@interface ThemeManager : NSObject
@property (nonatomic, strong) Theme *currentTheme;
+ (ThemeManager *)sharedManager;
@end
/* ThemeManager.m */
@implementation ThemeManager
+ (id)sharedManager {
static ThemeManager *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [[ThemeManager alloc] init];
sharedManager.currentTheme = [[Theme alloc] initWithTheme:ThemeColor_Default];
});
return sharedManager;
}
@end
/* Test.h */
@interface Test : UIViewController
@end
/* Test.m */
@implementation Test
- (void)viewDidLoad {
UIColor *firstBackgroundColor = [ThemeManager sharedManager].currentTheme.backgroundColor;
[ThemeManager sharedManager].currentTheme = [[Theme alloc] initWithTheme:ThemeColor_White];
UIColor *secondBackgroundColor = [ThemeManager sharedManager].currentTheme.backgroundColor;
}
同样,这只是其中一种方法。总是可以改进上述方法。这只是为了让你开始。我还没有执行这段代码。