如何将一个班级分配给另一个班级?

时间:2017-03-06 21:09:41

标签: ios objective-c nsobject

我试图在我的应用中创建一个名为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的。我该怎么做?

3 个答案:

答案 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;

}

同样,这只是其中一种方法。总是可以改进上述方法。这只是为了让你开始。我还没有执行这段代码。