Skip to content

illescasDaniel/Swift-Resources

Repository files navigation

Swift-Resources

Generates a simply structure from your assets (images and colors) and strings dynamically each time you build the project:

Output example:

import UIKit

enum R {

    enum Image {
        static var `avatar`: UIImage { UIImage(named: "avatar")! }
        static var `someImages_kickstarter2`: UIImage { UIImage(named: "some images/kickstarter-2")! }
        static var all: [UIImage] {[
            `avatar`,
            `someImages_kickstarter2`,
        ]}
    }

    enum Color {
        static var `accentColor`: UIColor { UIColor(named: "AccentColor")! }
        static var `eightSomething`: UIColor { UIColor(named: "8something")! }
        // ...
    }
    
    enum String {
        /// Add to favorites action
        static var `resourcesTest_addToFavorites`: Swift.String {
            NSLocalizedString(
                // also works for "resourcesTest_addToFavorites", "resources_test_add_to_favorites", etc
                "ResourcesTest.addToFavorites", 
                tableName: "Localizable",
                bundle: .main,
                value: "Add to favorites",
                comment: "Add to favorites action"
            )
        }
        // ...
    }

    static var all: [Any] {
        R.Image.all + R.Color.all + R.String.all
    }

    static func checkResources(shouldPrint: Bool = true) {
        // ...
    }
}

Instructions

Please follow all the following steps to know how it works and have all the necessary files set up.

1/3 What's needed:

  1. You need python 3 installed and you should have an alias/symbolic link to the binary with the name "python3".
  2. You will also need the gyb.py program made by Apple developers.

2/3 Tutorial using the example project

  1. Put gyb.py inside the gyb_resources_all folder of the project, the structure should be:
├── LICENSE
├── README.md
├── gyb_resources_all            # (folder) all files necessary for what we want
│  ├── __init__.py               # necessay file to easily use gyb_resources.py
│  ├── generate_resources.sh     # script to use in Xcode
│  ├── gyb.py                    # apple's gyb
│  ├── gyb_resources.py          # python script to generate code
│  ├── gyb_resources_assets.py   # python script to generate code
│  ├── gyb_resources_common.py   # python script to generate code
│  ├── gyb_resources_strings.py  # python script to generate code
│  └── gyb_script.py             # look for each gyb file to run it with gyb.py
├── resourcesTest        # project folder name
  1. Build and run the project.

Notes: The file that will generate the structure for your assets is R.swift.gyb, you can customize it if you like. The R.swift file should not be manually modified since it is automatically generated by R.swift.gyb.

  1. You can use the R structure in your code like this:
imageView1.image = R.Image.avatar
view1.backgroundColor = R.Color.accentColor

3/3 Tutorial for your project

  1. You need to copy the gyb_resources_all folder to the root folder of your project:
├── gyb_resources_all
│  ├── __init__.py 
│  ├── generate_resources.sh
│  ├── gyb.py
│  ├── gyb_resources.py
│  ├── gyb_resources_assets.py
│  ├── gyb_resources_common.py
│  ├── gyb_resources_strings.py
│  └── gyb_script.py
  1. Change the variable project_name inside gyb_script.py to your project folder name.
  2. Copy R.swift.gyb where you want R.swift to be generated. R.swift.gyb should NOT be added to your current target, so it should not be compiled (Compile sources) or copied to the app bundle resources (Copy bundle resources).
  3. You must create a new Run Script Phase in the Build Phases tab and these are its settings: Shell: /bin/sh Script content:
cd $PROJECT_DIR/gyb_resources_all
./generate_resources.sh

Run script: uncheck "for install builds only" and "based on dependendy analysis"

  1. IMPORTANT drag up this script build phase so that it appears BEFORE Compile Sources. Example:
- Dependencies
- GYB # your script created in step 4, you can rename it
- Compile Sources
- ...
  1. Make sure that the .strings file encoding matches the encoding specified in gyb_resources_all/gyb_resources_strings.py. To be sure convert your localizable strings file to UTF-8 with iconv -f UTF-16LE -t UTF-8 Localizable.strings > Localizable2.strings then delete Localizable.strings and rename Localizable2.strings to Localizable.strings. Then make sure the encoding is set to UTF-8 inside Xcode too.

Note: If you need to have UTF-16 strings just make sure the strings file is on that encoding and also change this line in gyb_resources_strings.py: with open(strings_path, encoding='utf-8') as f: replacing utf-8 for the desired encoding.

  1. You should be able to compile your project. After this a new file named R.swift should be generated alongside R.swift.gyb, drag R.swift to the project adding it to the proper target/s. R.swift should be treated as any other swift file (it should be compiled) BUT you should not modify it manually, since that file will change depending on your assets.

Notes

  • The file that will generate the structure for your assets is R.swift.gyb, you can customize it if you like.
  • The R.swift file should not be manually modified since it is automatically generated by R.swift.gyb.
  • Try not to use weird asset names (this is handled properly but just in case).
  • Nested folders work BUT only if all nested folders use the same setting for "provides namespace".
  • .strings files should have UTF-8 encoding, convert your Localizable.strings with iconv -f UTF-16LE -t UTF-8 Localizable.strings > Localizable2.strings. If you need to use UTF-16 change the encoder parameter in the file gyb_resources_strings.py in with open(strings_path, encoding='utf-8') as f: from utf-8 to utf-16 or other.
  • The script respects the "provides namespace" option and works fine when you mark a folder with that option.
  • If your Assets.xcassets is named differently or located in other folder different than the root folder, just modify R.swift.gyb adding the folder path in the function calls image_resources("myAssets.xcassets") and color_resources("myAssets.xcassets"). You can do the same with the strings resources function.
  • You can use R.checkResources() to verify all your assets at runtime. This is recommended to call when running your app in debug mode. IF YOU ENCOUNTER AN ERROR RUNNING IT, create an issue because maybe some assets weren't added properly.

TODO (maybe)

  • Generate strings from Localizable.strings
  • Support multiline string (without \n) in strings file.
  • Localizable string dictionaries.
  • Support other file types, like maybe fonts or audio files located on a specific project folder.

About

Python scripts to dynamically generate variables referencing your resources. (Similar to R class in Android)

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published