Author: Shaohua

The introduction

Daily work, involving the development requirements of the UI layer, can not avoid interacting with color. If night mode is supported and two sets of colors are involved in one page, the situation becomes more complicated, requiring the developer to code the two sets of colors.

The ease of using color affects development efficiency to a certain extent. How to get through the channel between engineers and designers so that engineers can efficiently use the color code of design documents has also become the focus of the team. Snowball iOS team explored a set of tools and methods in practice, and shared them in this article, hoping to provide some ideas for teams who also want to improve the efficiency of color use.

Plan to introduce

Unify color sources

Create a unified color source: color palette. The palette is the source of all colors in the design output, and there are nearly 50 sets of colors that are maintained by the design team.

Function of color palette:

  1. Maintain strictly corresponding day and night colors, most of the design output does not need to output the night mode separately, improve efficiency;

  2. In the process of design and development, if there is a problem with wrong color, we can use the color code to quickly locate and modify, and improve communication efficiency;

  3. Ensure color uniformity and accuracy in design output.

The engineer abstracted the color palette into the json format available to the project and saved it in the project. The content named and numbered the colors and the corresponding day and night color coding. Color swatch JSON example:

{  
  "T010": {  
    "default": "#333333",
    "night": "#C2C2C2"
  },
  "T020": {
    "default": "#666666",
    "night": "#888888"
  },
  "T030": {
    "default": "#AAAAAA",
    "night": "#666666"
  }
}

Copy the code

Open the color synchronization channel

When color pairing is added to the color palette, the design side and the engineering side need to synchronize operation. In past practice, the following problems will occur:

  1. Manual synchronization to modify the color palette file caused by various errors;

  2. Designers don’t know the rules or add color pairs randomly according to their personal preferences, breaking the unified output color rules of the color palette;

  3. After the occurrence of situation 2, the development of new colors that are not used in the palette needs to modify the development palette JSON by itself, and add the color constant declaration, resulting in differences between the design and development of the palette;

  4. Develop color codes using hexadecimal code directly;

To solve the above problem, we maintain the palette to the remote configuration center, adopt an automatic synchronization strategy. The design side updates the palette with specific managers (to ensure uniform output rules for the palette). The engineer automatically pulls the synchronization into the project file through the script (manual changes will be overwritten by automatic synchronization to avoid discrepancies).

The timing synchronization

Color-related resources and code logic are maintained in a separate POD component, and changes to the palette file are committed to this POD repository separately. To synchronize the palette, you need to modify the POD dependency, integrate it using path, and then execute Pod Install to make it exist as a Development Pod. Therefore, after pod Install is implemented, it is a good time to synchronize the changes directly in the POD if the swatch changes.

post_integrate Hook

CocoaPods provides hooks during the pod installation lifecycle that allow developers to customize the installation process and make changes to the project. Post_integrate Hook CocoaPods 1.10 provides a new Post_Integrate hook that is executed after the CocoaPods integration step. This hook fits our needs exactly. In Podfile:

Post_integrate do | installer swatches end | # download and synchronizationCopy the code

Locating synchronization Files

There are several problems to solve for synchronous palette operation:

  1. How to determine whether the pod where the palettes are located is integrated in path mode? Palettes synchronization will only be attempted in the Development Pods directory.

  2. How to locate the color palette JSON resource and other code file paths in pod.

We use Ruby’s Xcodeproj library to operate the project and find the relevant file paths to solve the above problems. Xcodeproj is installed as a core component when Cocoapods is installed. Key code examples:

Require 'xcodeProj' # initialize pod project project = xcodeProj :: project. open(pod_project_path) # Targets = project.targets # corresponds to all.h. m files in the target file. The swift file is contained in source_file. Headers_files = target.headers_build_phase.files source_files = target.source_build_phase.files Resources_files = resource_target.resources_build_phase.files # Get the file you want, Output path path = file.file_ref.real_path.to_sCopy the code

With the above method, we get the files and resource paths we need, and then we can proceed with the following operations.

Auto-generated code

After the palette JSON is synchronized to your project, you need to generate the corresponding Color constant declaration: color.h to match the existing theme manager in your project

#ifndef Color_h
#define Color_h
 
typedef NSString *SNBColor NS_EXTENSIBLE_STRING_ENUM;
/// default: #333333, night: #C2C2C2
FOUNDATION_EXTERN SNBColor const SNBColorT010;
/// default: #666666, night: #888888
FOUNDATION_EXTERN SNBColor const SNBColorT020;
/// default: #AAAAAA, night: #666666
FOUNDATION_EXTERN SNBColor const SNBColorT030;
 
#endif /* Color_h */

Copy the code

Color.m

#import "Color.h"
 
SNBColor const SNBColorT010 = @"T010";
SNBColor const SNBColorT020 = @"T020";
SNBColor const SNBColorT030 = @"T030";

Copy the code

NS_EXTENSIBLE_STRING_ENUM Enum string enumeration, which can be used to extend enumeration when bridging to Swift

As we saw in the example above, the color constant declaration code is highly associated with the color swatch JSON file and can be generated automatically using the tool. In Ruby, ERB is a good choice.

ERB

ERB (Embedded Ruby) is a Ruby templating engine. ERB provides Ruby with an easy-to-use and powerful templating system. With ERB, you can add Ruby code to any plain text document and customize the various outputs you need. A simple example:

require 'erb'
 
x = 42
template = ERB.new <<-EOF
  The value of x is: <%= x %>
EOF
puts template.result(binding)

Copy the code

Output: The value of x is: 42

Here’s a slightly more complicated example:

Class SNBColor attr_accessor :name, :default, :night def initialize(name, default, Night) @name = name@default = default@night = night end end # create template template = %{# ifNdef Color_h #define Color_h typedef NSString *SNBColor NS_EXTENSIBLE_STRING_ENUM; <% colors.each do |c| %> /// default: <%= c.default%>, night: <%= c.night%> FOUNDATION_EXTERN SNBColor const SNBColor<%= c.name%>; <% end %> #endif /* Color_h */} Color_h = erb. new(template) Color_h = [snbcolor. new("T010", "#333333", "#C2C2C2"), SNBColor.new("T020", "#666666", "#888888"), SNBColor.new("T030", "#AAAAAA", "#666666")] # puts color_h.result(binding)Copy the code

<% Ruby code — inline output %>, <%= Ruby expression — replace with result %>

After running, the output is as follows:

#ifndef Color_h
#define Color_h
 
typedef NSString *SNBColor NS_EXTENSIBLE_STRING_ENUM;
/// default: #333333, night: #C2C2C2
FOUNDATION_EXTERN SNBColor const SNBColorT010;
/// default: #666666, night: #888888
FOUNDATION_EXTERN SNBColor const SNBColorT020;
/// default: #AAAAAA, night: #666666
FOUNDATION_EXTERN SNBColor const SNBColorT030;
 
#endif /* Color_h */

Copy the code

The output of this example happens to be the contents of our color.h file.

Similar to the above example, the palette color constant declaration code is all automatically generated using ERB. Examples of pseudocode in practice:

# set template data to colors = get snbColor instance array from json parser # create template, Template = file.read (file.expand_path (' colorh.erb ', __dir__)) # construct ERB object message = erb.new (template) # get render result = message.result(binding) # write Color File. The open (' Color. H File path ', 'w') {| File | File. Write (result)}Copy the code

When a color is added to the json palette, the file is rewritten as an overwrite, and all you see in git diff is the color change.

So far, the color palette JSON and color constant declaration code files have been automatically synchronized to the color Pod.

Color Code Snippet

The design draft is output using tools such as Sketch and Blue Lake. All colors are marked in hexadecimal code. When we actually land the code, the topic manager wrapped in the project requires us to type a constant declaration for the color to use the actual color.

There was a problem in the original development process that affected efficiency very much: the engineer saw that the design output color tag was #333333, and the night mode was #C2C2C2. In this case, the engineer needed to find the name T010 in the color palette JSON, and then write the actual code in Xcode. If you enter the hexadecimal code from the design directly into the code, the actual code on the right is generated directly, and the efficiency is greatly improved.

Currently, the design team uses Figma for design output, and can also directly note the color constants in the color position, instead of requiring the color palette JSON to find the corresponding name of the color match.

Code Snippet

Code Snippet Code templates are a quick way to generate Code that saves a lot of input and speeds up development. Xcode provides pre-configured Code snippets for development, which are often used in daily development.

In addition to the Code snippets that Xcode presets for us, we can customize our own Code snippets for quick Code generation. The following parameters need to be configured on the customized page:

  • Title Title – Name. (Appears in code completion and code block library list)

  • Summary – Briefly describe what the code block does. (Only appears in block library list)

  • Platform – The Platform that restricts access to this code block.

  • Language Language – Limits the Language in which this code block can be accessed.

  • Completion input code – Shortcut input code.

  • Availability Availability – Limits the scope of access to this code block.

Once we know what each field means, we can create Code snippets that automatically complete color codes using color hexadecimal codes as quick input codes.

Results achieved in actual development:

The Completion shortcut field starts with the character C because numeric input does not trigger Xcode’s auto-completion mechanism.

Automatically generate Code snippets

Code snippets solve the problem of converting from design to actual Code, but generating Code snippets for each pair of color pairs in the palette is a huge amount of work. When a color is added to the palette, engineers need to add a Snippet (two sets of Objective-C/Swift Code for each color palette).

Xcode all Code snippets in ~ / Library/Developer/Xcode/UserData/CodeSnippets/directory, in XML form. T010. Codesnippet example:

Much of the code is duplicate templates, and only some of the field content needs to be customized.

This is where ERB comes in again. We also use the ERB template engine for rendering to automatically generate Code snippets. (The IDECodeSnippetIdentifier field needs to be filled with UUID generated. Uuidtools of Ruby are introduced into the script, and relevant tool dependencies are stored in Gemfile)

Trigger time is also placed in post_integrate:

Post_integrate do | installer | synchronous swatches # # download and automatically generates synchronization Code Snippet endCopy the code

After make color Code Snippet, copy to the current user’s ~ / Library/Developer/Xcode/UserData/CodeSnippets/directory, synchronization Code Snippet task is completed.

Code snippets created with Xcode are named with UUID. Create directly from XML source form can specify any name, we use the color name + development language name, to prevent repeated generation.

conclusion

The entire process tool does not require special configuration by the development team members. When new colors need to be synchronized, the color palette JSON, color name declaration Code files, and accompanying Code snippets are synchronized and updated during pod install before requirements development. At development time, if the Code Snippet auto-completion cannot be triggered by typing a hexadecimal Code, the design color is not from the palette, and the designer is prevented from following the uniform output color rules of the palette.

Through the process comparison, we can see that in the new scheme:

  • Added color palette with day and night color matching;

  • Color plate automatic update synchronization, avoid the error of manual modification in the process of synchronization;

  • Automatically generate project available color constant declaration code file;

  • Automatically generate Code snippets to help develop fast landing Code;

It opens up the color conversion process from design to engineering, reduces the operation and learning costs of team members, increases the efficiency of the use of color in UI development, and makes UI development no longer have to worry about the color Settings supporting the night mode.

The resources

Post_integrate Hook DSL: www.rubydoc.info/github/Coco…

Xcodeproj: www.rubydoc.info/gems/xcodep…

ERB:

www.rubydoc.info/gems/erb

Xcode Snippet: nshipster.com/xcode-snipp…

One more thing

Snowball business is developing by leaps and bounds, and the engineer team is looking forward to joining us. If you are interested in “being the premier online wealth management platform for Chinese people”, we hope you can join us. Click “Read the article” to check out the hot jobs. Hot position: Android/iOS/FE technical expert, recommendation algorithm engineer, Java development engineer.