xcode 推荐的 iOS 应用样式的方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7151608/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 21:47:22  来源:igfitidea点击:

What is the recommended method of styling an iOS app?

objective-ciosxcode

提问by Yogesh Agarwal

What is the recommended method of styling an iOS app? For example, if there are multiple labels or text views how can updating font style/color at one place update the style/color at all other places?

推荐的 iOS 应用样式的方法是什么?例如,如果有多个标签或文本视图,如何在一个地方更新字体样式/颜色来更新所有其他地方的样式/颜色?

I know sub classing could be one way... is there any other way?

我知道子分类可能是一种方式......还有其他方式吗?

采纳答案by Alex Coplan

You could import a standard header file into all your controllers with several constants set for styling... example:

您可以将标准头文件导入到所有控制器中,并为样式设置几个常量...例如:

Styles.h

样式文件

#define kFontSize 14
#define kFontFamily @"Helevetica"

Controller

控制器

#import "Styles.h" // at the top

myLabel.font = [UIFont fontWithName:kFontFamily size:kFontSize];

I personally think Interface Builder is the best way to style, however this answers your question directly.

我个人认为 Interface Builder 是设计样式的最佳方式,但这直接回答了您的问题。

回答by justin

Update:I would recommend starting by understanding UIAppearanceAPIs, and seeing how well they suit your needs. UIAppearanceis a convenient way to provide custom default stylization of specific controls' attributes at multiple levels (e.g. globally or contextually).

更新:我建议从了解UIAppearanceAPI开始,看看它们如何满足您的需求。UIAppearance是一种在多个级别(例如全局或上下文)提供特定控件属性的自定义默认样式的便捷方式。



My original answer, which predated UIAppearance's availability:

我的原始答案早于UIAppearance的可用性:



since we're working with an object based language...

因为我们正在使用基于对象的语言......

for the implementation, it depends on how you want it to behave/execute. when the implementation becomes nontrivial, i will often create a protocol. you could use class methods or instance methods and significantly optimize these types for your usage because you create fewer intermediate colors, fonts, images, etc.

对于实现,这取决于您希望它的行为/执行方式。当实现变得重要时,我会经常创建一个协议。您可以使用类方法或实例方法,并为您的使用显着优化这些类型,因为您创建的中间颜色、字体、图像等更少。

a basic interface could take the form:

基本界面可以采用以下形式:

@protocol MONLabelThemeProtocol

- (UIFont *)labelFont;
- (UIColor *)labelTextColor;
- (UITextAlignment)labelTextAlignment;
// ...
@end

@protocol MONTableViewCellThemeProtocol

- (UIFont *)tableViewCellFont;
- (UIColor *)tableViewCellTextColor;
- (UIImage *)tableViewCellImage;
- (NSInteger)tableViewCellIndentationLevel;
- (CGFloat)tableViewCellIndentationWidth;
// ...
@end

then a simple amalgamate theme could be declared like this:

然后可以像这样声明一个简单的合并主题:

@interface MONAmalgamateThemeBase : NSObject
   < MONLabelThemeProtocol, MONTableViewCellThemeProtocol >
{
@protected
    /* labels */
    UIFont * labelFont;
    UIColor * labelTextColor;
    UITextAlignment labelTextAlignment;
    // ...
    /* table view cells */
    UIFont * tableViewCellFont;
    UIColor * tableViewCellTextColor;
    UIImage * tableViewCellImage;
    NSInteger tableViewCellIndentationLevel;
    CGWidth tableViewCellIndentationWidth;
    // ...
}

@end

in this example, the amalgamate defines the getters and dealloc and expects the subclasses to initialize the instance variables. you could also support lazy initialization if initialization times are high (e.g. uses many images).

在这个例子中,合并定义了 getter 和 dealloc 并期望子类初始化实例变量。如果初始化时间很长(例如使用许多图像),您还可以支持延迟初始化。

then a specialization could take the form:

那么专业化可以采用以下形式:

@interface MONDarkTheme : MONAmalgamateThemeBase
@end

@implementation MONDarkTheme

- (id)init
{
    self = [super init];
    if (nil != self) {
        labelFont = [[UIFont boldSystemFontOfSize:15] retain];
        labelTextColor = [[UIColor redColor] retain];
        // and so on...
    }
    return self;
}

// ...

@end

/* declare another theme and set it up appropriately */
@interface MONLightTheme : MONAmalgamateThemeBase
@end

then just reuse the theme instances (e.g. MONDarkTheme) throughout the app to stylize the views. if you have a lot of themes or they are not trivial to construct, then you may want to create a collection for themes (theme manager). the amalgamate could also take a parameter, such as init with theme if your needs are simple. you can even configure objects to register for changes to themes, if you need support for dynamic changes.

然后在整个应用程序中重用主题实例(例如 MONDarkTheme)来风格化视图。如果您有很多主题或者它们不是很容易构建,那么您可能需要为主题创建一个集合(主题管理器)。如果您的需求很简单,合并也可以采用一个参数,例如带有主题的 init。如果您需要支持动态更改,您甚至可以配置对象以注册主题更改。

finally, you can create a simple theme applier to make life easier - like so:

最后,您可以创建一个简单的主题应用器,让生活更轻松 - 像这样:

@interface UILabel (MONThemeAdditions)

- (void)mon_applyMONLabelTheme:(id<MONLabelTheme>)theme;

@end

@implementation UILabel (MONThemeAdditions)

- (void)mon_applyMONLabelTheme:(id<MONLabelTheme>)theme
{
    assert(theme);
    if (nil == theme) return;
    self.font = [theme labelFont];
    self.textColor = [theme labelTextColor];
    self.textAlignment = [theme labelTextAlignment];
}

@end

回答by DexterW

Frankly, the best way to go about this is to use Interface Builder. While it might seem nice to change a single constant somewhere in the code and have the entire app change styles, it never quite works out that way. Here are my reasonings:

坦率地说,最好的方法是使用 Interface Builder。虽然在代码的某处更改单个常量并让整个应用程序更改样式看起来不错,但它永远不会以这种方式奏效。以下是我的理由:

1) Developers don't write interface code as well as interface builder does.Interface builder is a tool that has been refined, tested, and intreated over years. It offers fonts, text alignment, shadow, etc. It is backwards compatible for as far back as you'd ever want. It provides a very simple way for any number of developers and designers to jump in and work on something very straightforward.

1) 开发人员不像接口构建器那样编写接口代码。接口生成器是被提炼,测试,并应允在工具多年。它提供字体、文本对齐、阴影等。它向后兼容,只要你想要。它为任何数量的开发人员和设计人员提供了一种非常简单的方法,可以让他们参与并处理非常简单的事情。

2) There are always edge cases that you'll have to account for.Sure, a simple constant will do what you want most the time, but you'll eventually have to hack something in here and sneak something in there. The "simple" interface code you wrote to start off will grow and grow and grow. Other developers will have to maintain that code. You will have to maintain that code. You will have to file and fix bugs, tweak this, except that, etc. It will inevitably become a steaming pile of mess.

2)总有一些边缘情况你必须考虑。当然,一个简单的常量在大多数情况下都可以满足您的需求,但您最终将不得不在这里破解一些东西并在那里偷偷摸摸。您开始编写的“简单”界面代码会越来越大。其他开发人员将不得不维护该代码。您将不得不维护该代码。你将不得不归档和修复错误,调整这个,除了那个,等等。它不可避免地会变成一堆乱七八糟的东西。

3) The more code you write, the more bugs you write.Interface builder is for building the 'look' of most iOS apps. Use it. Don't get too clever.

3)你写的代码越多,你写的错误就越多。界面构建器用于构建大多数 iOS 应用程序的“外观”。用它。不要太聪明。

NOTE: I understand that Interface builder cannot do everything for all apps. There are cases that coding an interface is the only solution. This answer is simply a general "best practice" I use in the bulk of my apps.

注意:我知道 Interface builder 不能为所有应用程序做所有事情。在某些情况下,对接口进行编码是唯一的解决方案。这个答案只是我在大部分应用程序中使用的一般“最佳实践”。

回答by Clifton Labrum

You can use a third-party abstraction of UIAppearance:

您可以使用 UIAppearance 的第三方抽象:

Using a Storyboard has a lot of benefits, but many style options aren't available, not the least of which is custom fonts. If you want a deeply-customized UI, you will need some style code to make it happen.

使用 Storyboard 有很多好处,但许多样式选项不可用,尤其是自定义字体。如果你想要一个深度定制的 UI,你需要一些样式代码来实现它。

回答by Carter

Similar to Alex's idea, you could create a static class called ThemeManager:

与 Alex 的想法类似,您可以创建一个名为 ThemeManager 的静态类:

typedef enum
{
    defaultStyle,
    redStyle,
} ThemeStyles;

@interface Level : NSObject
{
    ThemeStyles currentTheme;
}

All classes which can be themed will import ThemeManager. Then, you can create methods like:

所有可以主题化的类都将导入 ThemeManager。然后,您可以创建如下方法:

+ (UIColor*) fontColor;

Which other classes would call when they want a color for their font. Then, if you want to change themes, you could implement fontColoras:

当其他类想要为其字体设置颜色时会调用哪些类。然后,如果您想更改主题,您可以实现fontColor为:

+ (UIColor*) fontColor
{
    switch (currentTheme)
    {
        case defaultStyle:
        return [UIColor blackColor];
        case redStyle:
        return [UIColor redColor];
    }
}

When you want to change the theme, you could have ThemeManager implement a method like:

当你想改变主题时,你可以让 ThemeManager 实现一个方法,如:

+ (void) changeTheme:(ThemeStyles)newTheme
{
    currentTheme = newTheme;
}

回答by Jano

I use plists. Just as I localize strings, I use the same procedure to change themes. I coded a singleton that loads a current theme plist and a fallback plist. Then I replace the names of resources with keys and macro functions that pull the real resource name from the singleton.

我使用 plist。正如我本地化字符串一样,我使用相同的过程来更改主题。我编写了一个加载当前主题 plist 和后备 plist 的单例。然后我用键和宏函数替换资源的名称,这些键和宏函数从单例中提取真实的资源名称。

Cons: you have to set the resource for each element, not just set it in the NIB.
Pros: once you are done, most of the next theme involves photoshop and textmate, not IB or code.

缺点:您必须为每个元素设置资源,而不仅仅是在 NIB 中设置它。
优点:一旦你完成了,接下来的主题大部分涉及photoshop和textmate,而不是IB或代码。

回答by Charith Nidarsha

You may need to look at this library. It supports multiple themes/skins on the fly. Supports images and colors currently. Font support will be added in future.

您可能需要查看此库。它即时支持多个主题/皮肤。目前支持图像和颜色。字体支持将在未来添加。

https://github.com/charithnidarsha/MultiThemeManager

https://github.com/charithnidarsha/MultiThemeManager