如何为iphone应用程序创建多个主题/皮肤?

时间:2023-01-12 20:02:03

I have an iphone app ready and approved by the app store. Now I want to create different themes for my app. Can someone please help me out, with info/links/steps on how to create themes for my app?

我有一个iphone应用程序已经准备好并得到了应用商店的批准。现在我想为我的应用创建不同的主题。能否有人帮助我,提供关于如何为我的应用创建主题的信息/链接/步骤?

I want to create a Metal theme for the Boys and a Pink theme for the Girls. Again by theme I mean, the whole app(features and functionality) is gonna stay the same, but depending on who the user is(boy or girl), he/she can choose the theme they wish to see. And when the theme changes, only the images/Background/music will change according to the applied theme.

我想为男生创造一个金属主题,为女生创造一个粉色主题。我说的主题是,整个应用程序(功能和功能)将保持不变,但取决于用户是谁(男孩还是女孩),他/她可以选择他们希望看到的主题。当主题发生变化时,只有图像/背景/音乐会根据应用的主题发生变化。

Thanks a lot!

谢谢!

1 个解决方案

#1


123  

This is quite difficult as apps don't have the equivalent of a css stylesheet.

这很困难,因为应用程序没有css样式表。

First you need to work out what parts of the app you want to skin, and when you want to allow the user to swap skins.

首先,您需要计算出应用程序的哪些部分需要进行皮肤处理,以及何时允许用户交换皮肤。

I'm going to assume that you want to change images and font colours, and that it's okay if the user has to relaunch the app to change the skin (that will make things simpler for now).

我假设你想要改变图片和字体的颜色,如果用户需要重新启动应用程序来改变皮肤(这将使事情变得更简单)。

Create a plist containing all your skinnable images and colours. The plist will be a dictionary with sensible, theme neutral key names for the images and colours (e.g. don't have a colour called "red", call it "primaryHeadingColor"). Images will be file names, and colours can be hex strings, e.g. FF0000 for red.

创建一个plist,其中包含所有可剥皮肤的图片和颜色。plist将会是一本字典,里面有对图像和颜色敏感的、主题中性的关键字(例如,没有一种叫做“红色”的颜色,叫“主色”)。图像将是文件名,颜色可以是十六进制字符串,例如FF0000表示红色。

You'll have one plist for each theme.

每个主题都有一个plist。

Create a new class called ThemeManager and make it a singleton by adding the following method:

创建一个名为ThemeManager的新类,通过添加以下方法使其成为单例:

+ (ThemeManager *)sharedManager
{
    static ThemeManager *sharedManager = nil;
    if (sharedManager == nil)
    {
        sharedManager = [[ThemeManager alloc] init];
    }
    return sharedManager;
}

The ThemeManager class will have an NSDictionary property called "styles", and in the init method you will load the theme into your styles dictionary like this:

ThemeManager类将有一个名为“styles”的NSDictionary属性,在init方法中,您将把主题加载到样式字典中,如下所示:

- (id)init
{
    if ((self = [super init]))
    {
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        NSString *themeName = [defaults objectForKey:@"theme"] ?: @"default";

        NSString *path = [[NSBundle mainBundle] pathForResource:themeName ofType:@"plist"];
        self.styles = [NSDictionary dictionaryWithContentsOfFile:path];
    }
    return self;
}

(Note: some people don't like doing a lot of work inside an init method. I've never found it to be an issue, but if you prefer, create a separate method to load the themes dictionary and call it from your app's setup code).

(注意:有些人不喜欢在init方法中做很多工作。我从来没有发现它是一个问题,但是如果您愿意,创建一个单独的方法来加载主题字典,并从应用程序的设置代码中调用它。

Notice how I'm getting the name for the theme plist from user defaults. That means the user can select a theme in your preferences and save it and the app will load that theme next time it is launched. I've put in a default theme name of "default" if no theme is selected, so make sure you have a default.plist theme file (or change the @"default" in the code to whatever your default theme plist is actually called).

注意我是如何从用户默认值中获取主题plist的名称的。这意味着用户可以在您的首选项中选择一个主题并保存它,应用程序将在下次启动时加载该主题。如果没有选择主题,我输入默认的主题名“default”,所以请确保您有一个默认的主题。plist主题文件(或将代码中的@“default”更改为您的默认主题plist的实际调用)。

Now that you've loaded your theme you need to use it; I'm assuming your app has various images and text labels. If you're loading and laying those out in code then this part is easy. If you are doing it in nibs then it's a bit trickier but I'll explain how to handle that later.

现在你已经加载了你的主题,你需要使用它;假设你的应用有各种图片和文字标签。如果您正在加载并在代码中列出这些内容,那么这部分很容易。如果你是在nibs中做的,那就有点麻烦了,但是我稍后会解释如何处理这个问题。

Now normally you would load an image by saying:

通常情况下,加载图像时你会说:

UIImage *image = [UIImage imageNamed:@"myImage.png"];

But if you want that image to be themable, you'll now need to load it by saying

但是如果你想要那个图像是可主题的,你现在需要通过说加载它

NSDictionary *styles = [ThemeManager sharedManager].styles;
NSString *imageName = [styles objectForKey:@"myImageKey"];
UIImage *image = [UIImage imageNamed:imageName];

That will look in your theme file for the themed image that matches the key "myImageKey" and will load it. Depending on which theme file you've loaded you'll get a different style.

它将在您的主题文件中查找与键“myImageKey”匹配的主题图像,并将加载它。根据您加载的主题文件,您将获得不同的样式。

You'll be using those three lines a lot so you may want to wrap them up in a function. A great idea would be to create a category on UIImage that declares a method called something like:

您将经常使用这三行代码,因此您可能想要将它们封装在一个函数中。一个很好的想法是在UIImage上创建一个类别,它声明一个叫做

+ (UIImage *)themeImageNamed:(NSString *)key;

Then to use it you can just replace any calls to [UIImage imageNamed:@"foo.png"]; with [UIImage themeImageNamed:@"foo"]; where foo is now the theme key instead of the actual image name.

然后使用它,你可以替换任何对[UIImage imageNamed:@"foo.png"的调用;与用户界面图像themeImageNamed:@“foo”);其中foo现在是主题键,而不是实际的图像名称。

Okay, so that's it for theming your images. To theme your label colours, suppose you're currently setting your label colours by saying:

这就是图像的主题化。你的标签颜色的主题,假设你正在设定你的标签颜色:

 someLabel.color = [UIColor redColor];

You would now replace that with:

你现在可以将其替换为:

NSDictionary *styles = [ThemeManager sharedManager].styles;
NSString *labelColor = [styles objectForKey:@"myLabelColor"];
someLabel.color = [UIColor colorWithHexString:labelColor];

Now you may have noticed that UIColor doesn't have a method "colorWithHexString:" - you'll have to add that using a category. You can Google for "UIColor with hex string" solutions to find code to do that, or I've written a handy category that does that and a bit more here: https://github.com/nicklockwood/ColorUtils

现在您可能已经注意到UIColor没有“colorWithHexString:”方法——您必须使用一个类别来添加它。您可以为“使用十六进制字符串的UIColor”解决方案谷歌找到实现这一点的代码,或者我已经编写了一个方便的类别来实现这一点,这里还有更多:https://github.com/nicklockwood/ColorUtils

If you've been paying attention you'll also be thinking that instead of writing those three lines over and over, why not add a method to UIColor called:

如果你一直在关注,你也会想,为什么不把这三行写一遍又一遍,给UIColor添加一个方法呢?

+ (UIColor *)themeColorNamed:(NSString *)key;

Just like we did with UIImage? Great idea!

就像我们用UIImage一样?好主意!

So that's it. Now you can theme any image or label in your app. You could use the same trick to set the font name, or any number of other potentially themable visual properties.

这就是它。现在,你可以在你的应用中设置任何图像或标签的主题。你可以使用同样的技巧来设置字体名称,或者设置任意数量的其他潜在可主题的视觉属性。

There's just one tiny thing we've forgotten...

我们忘记了一件小事……

If you've built most of your views as nibs (and I see no reason why you wouldn't) then these techniques aren't going to work because your image names and font colours are buried inside impenetrable nib data and aren't being set in your source code.

如果您已经将大部分视图构建为nib(我看没有理由不这样做),那么这些技术将无法工作,因为您的图像名称和字体颜色隐藏在不可穿透的nib数据中,并且没有在源代码中设置。

There are a few approaches to solve this:

有一些方法可以解决这个问题:

1) You could make duplicate themed copies of your nibs and then put the nib names in your theme plist and load them from your theme manager. That's not too bad, just implement the nibName method of your view controllers like this:

1)您可以复制您的nib主题副本,然后将nib名称放在主题列表中,并从主题管理器中加载它们。这还不算太坏,只需实现您的视图控制器的nibName方法,如下所示:

- (NSString *)nibName
{
    NSDictionary *styles = [ThemeManager sharedManager].styles;
    return [styles objectForKey:NSStringFromClass([self class])];
}

Notice my neat trick of using the class name of the view controller as the key - that will save you some typing because you can just make a base ThemeViewController with that method and have all your themable view controllers inherit from it.

注意我使用视图控制器的类名作为键的巧妙技巧——这将为您节省一些输入,因为您可以使用该方法创建一个基本的ThemeViewController并让所有可主题视图控制器继承它。

This approach does mean maintaining multiple copies of each nib though, which is a maintenance nightmare if you need to change any screens later.

这种方法确实意味着维护每个nib的多个副本,如果以后需要更改任何屏幕,这将是一个维护噩梦。

2) You could make IBOutlets for all of the imageViews and labels in your nibs, then set their images and colors in code in your viewDidLoad method. That's probably the most cumbersome approach, but at least you don't have duplicate nibs to maintain (this is essentially the same problem as localising nibs btw, and pretty much the same solution options).

2)您可以为nibs中的所有imageViews和label创建iboutlet,然后在viewDidLoad方法中以代码设置它们的图像和颜色。这可能是最麻烦的方法,但至少您没有要维护的重复nib(这本质上与本地化nibs是相同的问题,而且几乎是相同的解决方案选项)。

3) You could create a custom subclass of UILabel called ThemeLabel that automatically sets the font color using the code above when the label is instantiated, then use those ThemeLabels in your nib files instead of regular UILabels by setting the class of the label to ThemeLabel in Interface Builder. Unfortunately if you have more than one font or font colour, you'll need to create a different UILabel subclass for each different style.

3)您可以创建一个UILabel的自定义子类,名为ThemeLabel,当标签实例化时使用上面的代码自动设置字体颜色,然后在nib文件中使用这些ThemeLabels,而不是常规的UILabels,方法是将标签的类设置为Interface Builder中的ThemeLabel。不幸的是,如果您有多个字体或字体颜色,您将需要为每个不同的样式创建一个不同的UILabel子类。

Or you could be devious and use something like the view tag or accessibilityLabel property as the style dictionary key so that you can have a single ThemeLabel class and set the accessibility label in Interface Builder to select the style.

或者您可以使用类似于视图标记或accessibilityLabel属性的东西作为样式字典键,这样您就可以拥有一个ThemeLabel类,并在Interface Builder中设置可访问性标签来选择样式。

The same trick could work for ImageViews - create a UIImageView subclass called ThemeImageView that, in the awakeFromNib method replaces the image with a theme image based on the tag or accessibilityLabel property.

同样的技巧也适用于ImageViews——创建一个名为ThemeImageView的UIImageView子类,在awakeFromNib方法中使用基于标签或可访问性标签属性的主题图像替换图像。

Personally I like option 3 best because it saves on coding. Another advantage of option 3 is that if you wanted to be able to swap themes at runtime, you could implement a mechanism where your theme manager reloads the theme dictionary, then broadcasts an NSNotification to all the ThemeLabels and ThemeImageViews telling them to redraw themselves. That would probably only take about an extra 15 lines of code.

我个人最喜欢选项3,因为它节省了编码。选项3的另一个优点是,如果希望能够在运行时交换主题,可以实现这样一种机制:主题管理器重新加载主题字典,然后向所有ThemeLabels和ThemeImageViews广播一个NSNotification,告诉它们重新绘制自己。这可能只需要多写15行代码。

Anyway, there you have a complete iOS app theming solution. You're welcome!

总之,你有一个完整的iOS应用主题解决方案。欢迎你!

UPDATE:

更新:

As of iOS 5, it's now possible to set custom attributes by keyPath in Interface Builder, meaning that it's no longer necessary to create a view subclass for each themable property, or abuse the tag or accessibilityLabel for selecting styles. Just give your UILabel or UIImageView subclass a string property to indicate which theme key it should use from the plist, and then set that value in IB.

从ios5开始,现在可以在Interface Builder中通过keyPath设置自定义属性,这意味着不再需要为每个可主题属性创建视图子类,或者滥用标记或accessibilityLabel来选择样式。只需给你的UILabel或UIImageView子类一个字符串属性来指示它应该从plist中使用哪个主题键,然后在IB中设置该值。

UPDATE 2:

更新2:

As of iOS 6, there is now a limited skinning system built into iOS that allows you to use a property called the UIAppearance proxy to skin all instances of a given control class at once (there's a good tutorial about the UIAppearance APIs here). It's worth checking if this is sufficient for your skinning needs, but if not, the solution I outlined above still works well, and can be used instead, or in combination with UIAppearance.

在iOS 6中,现在有一个内置在iOS中的有限的皮肤系统,允许您使用一个名为UIAppearance代理的属性来一次皮肤一个给定控件类的所有实例(这里有一个关于UIAppearance api的很好的教程)。值得检查的是,这是否足以满足您的剥皮需求,但如果不能,我上面列出的解决方案仍然可以很好地工作,并且可以使用,或者与UIAppearance结合使用。

#1


123  

This is quite difficult as apps don't have the equivalent of a css stylesheet.

这很困难,因为应用程序没有css样式表。

First you need to work out what parts of the app you want to skin, and when you want to allow the user to swap skins.

首先,您需要计算出应用程序的哪些部分需要进行皮肤处理,以及何时允许用户交换皮肤。

I'm going to assume that you want to change images and font colours, and that it's okay if the user has to relaunch the app to change the skin (that will make things simpler for now).

我假设你想要改变图片和字体的颜色,如果用户需要重新启动应用程序来改变皮肤(这将使事情变得更简单)。

Create a plist containing all your skinnable images and colours. The plist will be a dictionary with sensible, theme neutral key names for the images and colours (e.g. don't have a colour called "red", call it "primaryHeadingColor"). Images will be file names, and colours can be hex strings, e.g. FF0000 for red.

创建一个plist,其中包含所有可剥皮肤的图片和颜色。plist将会是一本字典,里面有对图像和颜色敏感的、主题中性的关键字(例如,没有一种叫做“红色”的颜色,叫“主色”)。图像将是文件名,颜色可以是十六进制字符串,例如FF0000表示红色。

You'll have one plist for each theme.

每个主题都有一个plist。

Create a new class called ThemeManager and make it a singleton by adding the following method:

创建一个名为ThemeManager的新类,通过添加以下方法使其成为单例:

+ (ThemeManager *)sharedManager
{
    static ThemeManager *sharedManager = nil;
    if (sharedManager == nil)
    {
        sharedManager = [[ThemeManager alloc] init];
    }
    return sharedManager;
}

The ThemeManager class will have an NSDictionary property called "styles", and in the init method you will load the theme into your styles dictionary like this:

ThemeManager类将有一个名为“styles”的NSDictionary属性,在init方法中,您将把主题加载到样式字典中,如下所示:

- (id)init
{
    if ((self = [super init]))
    {
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        NSString *themeName = [defaults objectForKey:@"theme"] ?: @"default";

        NSString *path = [[NSBundle mainBundle] pathForResource:themeName ofType:@"plist"];
        self.styles = [NSDictionary dictionaryWithContentsOfFile:path];
    }
    return self;
}

(Note: some people don't like doing a lot of work inside an init method. I've never found it to be an issue, but if you prefer, create a separate method to load the themes dictionary and call it from your app's setup code).

(注意:有些人不喜欢在init方法中做很多工作。我从来没有发现它是一个问题,但是如果您愿意,创建一个单独的方法来加载主题字典,并从应用程序的设置代码中调用它。

Notice how I'm getting the name for the theme plist from user defaults. That means the user can select a theme in your preferences and save it and the app will load that theme next time it is launched. I've put in a default theme name of "default" if no theme is selected, so make sure you have a default.plist theme file (or change the @"default" in the code to whatever your default theme plist is actually called).

注意我是如何从用户默认值中获取主题plist的名称的。这意味着用户可以在您的首选项中选择一个主题并保存它,应用程序将在下次启动时加载该主题。如果没有选择主题,我输入默认的主题名“default”,所以请确保您有一个默认的主题。plist主题文件(或将代码中的@“default”更改为您的默认主题plist的实际调用)。

Now that you've loaded your theme you need to use it; I'm assuming your app has various images and text labels. If you're loading and laying those out in code then this part is easy. If you are doing it in nibs then it's a bit trickier but I'll explain how to handle that later.

现在你已经加载了你的主题,你需要使用它;假设你的应用有各种图片和文字标签。如果您正在加载并在代码中列出这些内容,那么这部分很容易。如果你是在nibs中做的,那就有点麻烦了,但是我稍后会解释如何处理这个问题。

Now normally you would load an image by saying:

通常情况下,加载图像时你会说:

UIImage *image = [UIImage imageNamed:@"myImage.png"];

But if you want that image to be themable, you'll now need to load it by saying

但是如果你想要那个图像是可主题的,你现在需要通过说加载它

NSDictionary *styles = [ThemeManager sharedManager].styles;
NSString *imageName = [styles objectForKey:@"myImageKey"];
UIImage *image = [UIImage imageNamed:imageName];

That will look in your theme file for the themed image that matches the key "myImageKey" and will load it. Depending on which theme file you've loaded you'll get a different style.

它将在您的主题文件中查找与键“myImageKey”匹配的主题图像,并将加载它。根据您加载的主题文件,您将获得不同的样式。

You'll be using those three lines a lot so you may want to wrap them up in a function. A great idea would be to create a category on UIImage that declares a method called something like:

您将经常使用这三行代码,因此您可能想要将它们封装在一个函数中。一个很好的想法是在UIImage上创建一个类别,它声明一个叫做

+ (UIImage *)themeImageNamed:(NSString *)key;

Then to use it you can just replace any calls to [UIImage imageNamed:@"foo.png"]; with [UIImage themeImageNamed:@"foo"]; where foo is now the theme key instead of the actual image name.

然后使用它,你可以替换任何对[UIImage imageNamed:@"foo.png"的调用;与用户界面图像themeImageNamed:@“foo”);其中foo现在是主题键,而不是实际的图像名称。

Okay, so that's it for theming your images. To theme your label colours, suppose you're currently setting your label colours by saying:

这就是图像的主题化。你的标签颜色的主题,假设你正在设定你的标签颜色:

 someLabel.color = [UIColor redColor];

You would now replace that with:

你现在可以将其替换为:

NSDictionary *styles = [ThemeManager sharedManager].styles;
NSString *labelColor = [styles objectForKey:@"myLabelColor"];
someLabel.color = [UIColor colorWithHexString:labelColor];

Now you may have noticed that UIColor doesn't have a method "colorWithHexString:" - you'll have to add that using a category. You can Google for "UIColor with hex string" solutions to find code to do that, or I've written a handy category that does that and a bit more here: https://github.com/nicklockwood/ColorUtils

现在您可能已经注意到UIColor没有“colorWithHexString:”方法——您必须使用一个类别来添加它。您可以为“使用十六进制字符串的UIColor”解决方案谷歌找到实现这一点的代码,或者我已经编写了一个方便的类别来实现这一点,这里还有更多:https://github.com/nicklockwood/ColorUtils

If you've been paying attention you'll also be thinking that instead of writing those three lines over and over, why not add a method to UIColor called:

如果你一直在关注,你也会想,为什么不把这三行写一遍又一遍,给UIColor添加一个方法呢?

+ (UIColor *)themeColorNamed:(NSString *)key;

Just like we did with UIImage? Great idea!

就像我们用UIImage一样?好主意!

So that's it. Now you can theme any image or label in your app. You could use the same trick to set the font name, or any number of other potentially themable visual properties.

这就是它。现在,你可以在你的应用中设置任何图像或标签的主题。你可以使用同样的技巧来设置字体名称,或者设置任意数量的其他潜在可主题的视觉属性。

There's just one tiny thing we've forgotten...

我们忘记了一件小事……

If you've built most of your views as nibs (and I see no reason why you wouldn't) then these techniques aren't going to work because your image names and font colours are buried inside impenetrable nib data and aren't being set in your source code.

如果您已经将大部分视图构建为nib(我看没有理由不这样做),那么这些技术将无法工作,因为您的图像名称和字体颜色隐藏在不可穿透的nib数据中,并且没有在源代码中设置。

There are a few approaches to solve this:

有一些方法可以解决这个问题:

1) You could make duplicate themed copies of your nibs and then put the nib names in your theme plist and load them from your theme manager. That's not too bad, just implement the nibName method of your view controllers like this:

1)您可以复制您的nib主题副本,然后将nib名称放在主题列表中,并从主题管理器中加载它们。这还不算太坏,只需实现您的视图控制器的nibName方法,如下所示:

- (NSString *)nibName
{
    NSDictionary *styles = [ThemeManager sharedManager].styles;
    return [styles objectForKey:NSStringFromClass([self class])];
}

Notice my neat trick of using the class name of the view controller as the key - that will save you some typing because you can just make a base ThemeViewController with that method and have all your themable view controllers inherit from it.

注意我使用视图控制器的类名作为键的巧妙技巧——这将为您节省一些输入,因为您可以使用该方法创建一个基本的ThemeViewController并让所有可主题视图控制器继承它。

This approach does mean maintaining multiple copies of each nib though, which is a maintenance nightmare if you need to change any screens later.

这种方法确实意味着维护每个nib的多个副本,如果以后需要更改任何屏幕,这将是一个维护噩梦。

2) You could make IBOutlets for all of the imageViews and labels in your nibs, then set their images and colors in code in your viewDidLoad method. That's probably the most cumbersome approach, but at least you don't have duplicate nibs to maintain (this is essentially the same problem as localising nibs btw, and pretty much the same solution options).

2)您可以为nibs中的所有imageViews和label创建iboutlet,然后在viewDidLoad方法中以代码设置它们的图像和颜色。这可能是最麻烦的方法,但至少您没有要维护的重复nib(这本质上与本地化nibs是相同的问题,而且几乎是相同的解决方案选项)。

3) You could create a custom subclass of UILabel called ThemeLabel that automatically sets the font color using the code above when the label is instantiated, then use those ThemeLabels in your nib files instead of regular UILabels by setting the class of the label to ThemeLabel in Interface Builder. Unfortunately if you have more than one font or font colour, you'll need to create a different UILabel subclass for each different style.

3)您可以创建一个UILabel的自定义子类,名为ThemeLabel,当标签实例化时使用上面的代码自动设置字体颜色,然后在nib文件中使用这些ThemeLabels,而不是常规的UILabels,方法是将标签的类设置为Interface Builder中的ThemeLabel。不幸的是,如果您有多个字体或字体颜色,您将需要为每个不同的样式创建一个不同的UILabel子类。

Or you could be devious and use something like the view tag or accessibilityLabel property as the style dictionary key so that you can have a single ThemeLabel class and set the accessibility label in Interface Builder to select the style.

或者您可以使用类似于视图标记或accessibilityLabel属性的东西作为样式字典键,这样您就可以拥有一个ThemeLabel类,并在Interface Builder中设置可访问性标签来选择样式。

The same trick could work for ImageViews - create a UIImageView subclass called ThemeImageView that, in the awakeFromNib method replaces the image with a theme image based on the tag or accessibilityLabel property.

同样的技巧也适用于ImageViews——创建一个名为ThemeImageView的UIImageView子类,在awakeFromNib方法中使用基于标签或可访问性标签属性的主题图像替换图像。

Personally I like option 3 best because it saves on coding. Another advantage of option 3 is that if you wanted to be able to swap themes at runtime, you could implement a mechanism where your theme manager reloads the theme dictionary, then broadcasts an NSNotification to all the ThemeLabels and ThemeImageViews telling them to redraw themselves. That would probably only take about an extra 15 lines of code.

我个人最喜欢选项3,因为它节省了编码。选项3的另一个优点是,如果希望能够在运行时交换主题,可以实现这样一种机制:主题管理器重新加载主题字典,然后向所有ThemeLabels和ThemeImageViews广播一个NSNotification,告诉它们重新绘制自己。这可能只需要多写15行代码。

Anyway, there you have a complete iOS app theming solution. You're welcome!

总之,你有一个完整的iOS应用主题解决方案。欢迎你!

UPDATE:

更新:

As of iOS 5, it's now possible to set custom attributes by keyPath in Interface Builder, meaning that it's no longer necessary to create a view subclass for each themable property, or abuse the tag or accessibilityLabel for selecting styles. Just give your UILabel or UIImageView subclass a string property to indicate which theme key it should use from the plist, and then set that value in IB.

从ios5开始,现在可以在Interface Builder中通过keyPath设置自定义属性,这意味着不再需要为每个可主题属性创建视图子类,或者滥用标记或accessibilityLabel来选择样式。只需给你的UILabel或UIImageView子类一个字符串属性来指示它应该从plist中使用哪个主题键,然后在IB中设置该值。

UPDATE 2:

更新2:

As of iOS 6, there is now a limited skinning system built into iOS that allows you to use a property called the UIAppearance proxy to skin all instances of a given control class at once (there's a good tutorial about the UIAppearance APIs here). It's worth checking if this is sufficient for your skinning needs, but if not, the solution I outlined above still works well, and can be used instead, or in combination with UIAppearance.

在iOS 6中,现在有一个内置在iOS中的有限的皮肤系统,允许您使用一个名为UIAppearance代理的属性来一次皮肤一个给定控件类的所有实例(这里有一个关于UIAppearance api的很好的教程)。值得检查的是,这是否足以满足您的剥皮需求,但如果不能,我上面列出的解决方案仍然可以很好地工作,并且可以使用,或者与UIAppearance结合使用。