There’s always a place for heroes.

Author: @ nixzhu


For the picture in app, we can obtain it by its name:

let image = UIImage(named: "test_image")Copy the code

But it’s not safe, we could misspell the name of the image, and the image itself could be deleted. If we use the same image in more than one place, we should always be careful.

We can address our concerns with a UIImage extension:

extension UIImage {
    static var xxx_testImage: UIImage {
        return UIImage(named: "test_image")!}}Copy the code

When we use it later, just:

let image = UIImage.xxx_testImageCopy the code

This way, in addition to the editor providing auto-completion, the compiler also ensures that we don’t enter a non-existent image name.

However, we cannot guarantee that images will not be deleted from our app project, so we should add a test to ensure that every time the test runs, all the images required by the app are accessible.

None of this is a problem, but the problem is that we probably didn’t think about this in the first place, so the app already has so many images that it’s no fun to manually generate this extension. (I know some people recommend R.swift, but it does too many things, doesn’t generate localized strings very well, and relies on CocoaPod, so I don’t like it very much.)

We open the terminal and go to the images.xcassets directory of the app: ls -l, with output similar to:

total 8
drwxr-xr-x  22 nix  staff  748 12 16  2015 AppIcon.appiconset
-rw-r--r--   1 nix  staff   62  5  5 17:06 Contents.json
drwxr-xr-x   4 nix  staff  136  4  3  2015 bubble_body.imageset
drwxr-xr-x   4 nix  staff  136  4  3  2015 bubble_left_tail.imageset
drwxr-xr-x   4 nix  staff  136  4  3  2015 bubble_right_tail.imageset
...
Copy the code

Visible, only the imageset suffix is normal images, so we grep filters: ls -l | grep imageset, output similar to:

drwxr-xr-x   4 nix  staff  136  4  3  2015 bubble_body.imageset
drwxr-xr-x   4 nix  staff  136  4  3  2015 bubble_left_tail.imageset
drwxr-xr-x   4 nix  staff  136  4  3  2015 bubble_right_tail.imageset
...
Copy the code

Pay attention to in the above command | for pipeline, and its role is to the output of the command on the left it as the right of the command input.

Then comes the awk: ls -l | grep imageset | awk ‘} {print $9, will be cut out: 9

bubble_body.imageset
bubble_left_tail.imageset
bubble_right_tail.imageset
...
Copy the code

Note that AWK uses whitespace as a separator by default, and $9 represents the ninth column.

We are a step closer to get pictures name list, continue to awk: ls -l | grep imageset | awk ‘{print $9}’ | awk -f. “” ‘{print $1}’.

Awk -f “.” ‘{print $1}’ awk uses whitespace by default. Do the separator and print the first column:

bubble_body
bubble_left_tail
bubble_right_tail
...
Copy the code

So we have a list of image names. Next we want to change the image name to ️ to comply with the Swift naming convention, such as changing bubble_body to bubbleBody.

Therefore, to add an awk command: ls -l | grep imageset | awk ‘{print $9}’ | awk -f. “” ‘{print $1}’ | awk -f” _ “‘ {out =” “; for(i=1; i<=NF; I++) {if (I = = 1) {out = $I} else {out = out “” toupper (substr ($I, 1, 1)) substr ($I, 2)}}; print out}’

This time it’s a bit more complicated. First, specify _ as the separator. Then we define a variable out=””, which looks like an empty string; And then it goes into the loop, and I is the variable; NF is the built-in variable of awK, which represents the “number of columns” of the current row. Here we use _ as the separator, so the first row has two columns, NF is 2, the second row has three columns, NF is 3. Awk processes the input line by line, so NF can be different for each row. In the body of the for loop (note the curly braces), we first determine if I is 1, then we assign it directly to out, otherwise we capitalize the first letter and append it to out. This code is ugly, Toupper (substr($I,1,1)); substr($I,2); out=out””… Indicates that out is appended with a whitespace character followed by an uppercase character and the rest of the string, thus implementing the uppercase function.

This is cumbersome, but I don’t know if there’s a more convenient function in AWk, but the code here works just fine, generating:

bubbleBody
bubbleLeftTail
bubbleRightTail
...
Copy the code

For future code generation, we need to keep the previous name unchanged, so modify the above command again: ls -l | grep imageset | awk ‘{print $9}’ | awk -F”.” ‘{print $1}’ | awk -F”_” ‘{out=$0″ “; for(i=1; i<=NF; I++) {if (I = = 1) {out = $I} else {out = out “” toupper (substr ($I, 1, 1)) substr ($I, 2)}}; print out}’

With only one change, we initialized out with $0 (current line) and a space, resulting in:

bubble_body bubbleBody
bubble_left_tail bubbleLeftTail
bubble_right_tail bubbleRightTail
...
Copy the code

Finally turn to code generation, still add a awk: ls -l | grep imageset | awk ‘{print $9}’ | awk -f. “” ‘{print $1}’ | awk -f” _ “‘ {out = $0” “; for(i=1; i<=NF; I++) {if (I = = 1) {out = $I} else {out = out “” toupper (substr ($I, 1, 1)) substr ($I, 2)}}; print out}’ | awk ‘{print “static var xxx_”$2″: UIImage {\n\treturn UIImage(named: \””$1″\”)! \n}\n”}’

Available:

static var xxx_bubbleBody: UIImage {
    return UIImage(named: "bubble_body")!
}

static var xxx_bubbleLeftTail: UIImage {
    return UIImage(named: "bubble_left_tail")!
}

static var xxx_bubbleRightTail: UIImage {
    return UIImage(named: "bubble_right_tail")!
}
.Copy the code

We’ve basically achieved what we wanted. We literally did it with “one line of code.”

Then search the project code that uses UIImage, replace it with a more secure use, and write a test that accesses all images. Of course, the test code can also be generated using a script like the one above.

I’m no awK expert, but I recommend that all programmers learn grep, AWk, and sed, which is not mentioned in this article. You don’t have to be familiar with them, just know how they work, consult the manual when you use them.

The final script looks something like this:

#!/bin/bash

# Generate UIImage extension for images assets

if [ $# -eq0]; then
    echo "Usage: ./ios_static_images.sh path_to_images_assets"
    exit
fi

if [ ! -d The $1 ]; then
    echo "Usage: ./ios_static_images.sh path_to_images_assets"
    exit
fi

echo "extension UIImage {"
echo ""

ls -l The $1 | \
grep imageset | \
awk '{ print $9; }' | \
awk -F"." '{ print $1; }' | \
awk -F"_" '{\
    out = $0" "; \
    for (i = 1; i <= NF; i++) { \
        if (i == 1) { \
            out = out $i; \
        } else { \
Out = out toupper(substr($I,1,1)); \
        } \
    }; \
    print out \
}' | \
awk '{\
print " static var xxx_" $2 ": UIImage {"; \
print " return UIImage(named: \"" $1 "\")!" ; \
print " }\n"; \
}'

echo "}"Copy the code


Welcome to reprint, but please be sure to indicate the source! Github.com/nixzhu/dev-…