• Guest
HabraHabr
  • Main
  • Users

  • Development
    • Programming
    • Information Security
    • Website development
    • JavaScript
    • Game development
    • Open source
    • Developed for Android
    • Machine learning
    • Abnormal programming
    • Java
    • Python
    • Development of mobile applications
    • Analysis and design of systems
    • .NET
    • Mathematics
    • Algorithms
    • C#
    • System Programming
    • C++
    • C
    • Go
    • PHP
    • Reverse engineering
    • Assembler
    • Development under Linux
    • Big Data
    • Rust
    • Cryptography
    • Entertaining problems
    • Testing of IT systems
    • Testing Web Services
    • HTML
    • Programming microcontrollers
    • API
    • High performance
    • Developed for iOS
    • CSS
    • Industrial Programming
    • Development under Windows
    • Image processing
    • Compilers
    • FPGA
    • Professional literature
    • OpenStreetMap
    • Google Chrome
    • Data Mining
    • PostgreSQL
    • Development of robotics
    • Visualization of data
    • Angular
    • ReactJS
    • Search technologies
    • Debugging
    • Test mobile applications
    • Browsers
    • Designing and refactoring
    • IT Standards
    • Solidity
    • Node.JS
    • Git
    • LaTeX
    • SQL
    • Haskell
    • Unreal Engine
    • Unity3D
    • Development for the Internet of things
    • Functional Programming
    • Amazon Web Services
    • Google Cloud Platform
    • Development under AR and VR
    • Assembly systems
    • Version control systems
    • Kotlin
    • R
    • CAD/CAM
    • Customer Optimization
    • Development of communication systems
    • Microsoft Azure
    • Perfect code
    • Atlassian
    • Visual Studio
    • NoSQL
    • Yii
    • Mono и Moonlight
    • Parallel Programming
    • Asterisk
    • Yandex API
    • WordPress
    • Sports programming
    • Lua
    • Microsoft SQL Server
    • Payment systems
    • TypeScript
    • Scala
    • Google API
    • Development of data transmission systems
    • XML
    • Regular expressions
    • Development under Tizen
    • Swift
    • MySQL
    • Geoinformation services
    • Global Positioning Systems
    • Qt
    • Dart
    • Django
    • Development for Office 365
    • Erlang/OTP
    • GPGPU
    • Eclipse
    • Maps API
    • Testing games
    • Browser Extensions
    • 1C-Bitrix
    • Development under e-commerce
    • Xamarin
    • Xcode
    • Development under Windows Phone
    • Semantics
    • CMS
    • VueJS
    • GitHub
    • Open data
    • Sphinx
    • Ruby on Rails
    • Ruby
    • Symfony
    • Drupal
    • Messaging Systems
    • CTF
    • SaaS / S+S
    • SharePoint
    • jQuery
    • Puppet
    • Firefox
    • Elm
    • MODX
    • Billing systems
    • Graphical shells
    • Kodobred
    • MongoDB
    • SCADA
    • Hadoop
    • Gradle
    • Clojure
    • F#
    • CoffeeScript
    • Matlab
    • Phalcon
    • Development under Sailfish OS
    • Magento
    • Elixir/Phoenix
    • Microsoft Edge
    • Layout of letters
    • Development for OS X
    • Forth
    • Smalltalk
    • Julia
    • Laravel
    • WebGL
    • Meteor.JS
    • Firebird/Interbase
    • SQLite
    • D
    • Mesh-networks
    • I2P
    • Derby.js
    • Emacs
    • Development under Bada
    • Mercurial
    • UML Design
    • Objective C
    • Fortran
    • Cocoa
    • Cobol
    • Apache Flex
    • Action Script
    • Joomla
    • IIS
    • Twitter API
    • Vkontakte API
    • Facebook API
    • Microsoft Access
    • PDF
    • Prolog
    • GTK+
    • LabVIEW
    • Brainfuck
    • Cubrid
    • Canvas
    • Doctrine ORM
    • Google App Engine
    • Twisted
    • XSLT
    • TDD
    • Small Basic
    • Kohana
    • Development for Java ME
    • LiveStreet
    • MooTools
    • Adobe Flash
    • GreaseMonkey
    • INFOLUST
    • Groovy & Grails
    • Lisp
    • Delphi
    • Zend Framework
    • ExtJS / Sencha Library
    • Internet Explorer
    • CodeIgniter
    • Silverlight
    • Google Web Toolkit
    • CakePHP
    • Safari
    • Opera
    • Microformats
    • Ajax
    • VIM
  • Administration
    • System administration
    • IT Infrastructure
    • *nix
    • Network technologies
    • DevOps
    • Server Administration
    • Cloud computing
    • Configuring Linux
    • Wireless technologies
    • Virtualization
    • Hosting
    • Data storage
    • Decentralized networks
    • Database Administration
    • Data Warehousing
    • Communication standards
    • PowerShell
    • Backup
    • Cisco
    • Nginx
    • Antivirus protection
    • DNS
    • Server Optimization
    • Data recovery
    • Apache
    • Spam and antispam
    • Data Compression
    • SAN
    • IPv6
    • Fidonet
    • IPTV
    • Shells
    • Administering domain names
  • Design
    • Interfaces
    • Web design
    • Working with sound
    • Usability
    • Graphic design
    • Design Games
    • Mobile App Design
    • Working with 3D-graphics
    • Typography
    • Working with video
    • Work with vector graphics
    • Accessibility
    • Prototyping
    • CGI (graphics)
    • Computer Animation
    • Working with icons
  • Control
    • Careers in the IT industry
    • Project management
    • Development Management
    • Personnel Management
    • Product Management
    • Start-up development
    • Managing the community
    • Service Desk
    • GTD
    • IT Terminology
    • Agile
    • Business Models
    • Legislation and IT-business
    • Sales management
    • CRM-systems
    • Product localization
    • ECM / EDS
    • Freelance
    • Venture investments
    • ERP-systems
    • Help Desk Software
    • Media management
    • Patenting
    • E-commerce management
    • Creative Commons
  • Marketing
    • Conferences
    • Promotion of games
    • Internet Marketing
    • Search Engine Optimization
    • Web Analytics
    • Monetize Web services
    • Content marketing
    • Monetization of IT systems
    • Monetize mobile apps
    • Mobile App Analytics
    • Growth Hacking
    • Branding
    • Monetize Games
    • Display ads
    • Contextual advertising
    • Increase Conversion Rate
  • Sundry
    • Reading room
    • Educational process in IT
    • Research and forecasts in IT
    • Finance in IT
    • Hakatonas
    • IT emigration
    • Education abroad
    • Lumber room
    • I'm on my way

Control over resources. Set up SwiftGen

Probably, in every big iOS-project - long-livers you can come across icons that are not used anywhere, or access localization keys that have not existed for a long time. Most often, such situations arise because of inattention, and the best cure for inattention is automation.
 
In the iOS-command HeadHunter we pay much attention to automation of routine tasks, which the developer can face. With this article, we want to start a series of stories about the tools and approaches that simplify our daily work.
 
Some time ago we managed to take the application resources under control with the help of the SwiftGen utility. About how to configure it, how to live with it and how this utility helps to shift the verification of the relevance of resources to the shoulders of the compiler, and will be discussed under the cut.
 
Control over resources. Set up SwiftGen documentation . In our case, all you need to do is add to Podfile. pod 'SwiftGen' , then add a new build phase ( Build Phase ), which will run SwiftGen before starting the project build.
 

    "$ PODS_ROOT" /SwiftGen /bin /swiftgen    

 

It is important to run SwiftGen before running phase Compile Sources to avoid errors when compiling the project.


 


 

Now you can start adapting SwiftGen to our project.


 

Setting up SwiftGen


 

The first step is to configure the templates, which will generate code for accessing resources. The utility already contains a set of templates for code generation, they can all be viewed at githabe and, in principle, they are ready for use. Templates are written in the language Stencil , you may be familiar with it if you used Sourcery or played with Kitura . If desired, each of the templates can be adapted to their guides.
 
For example, take a template that generates enum to access the localization strings. It seemed to us that in the standard there is too much too much and it can be simplified. A simplified example with explanatory comments is under the spoiler.


 
Example of the template [/b]
    {# Processing one of the input parameters #}
{% set accessModifier%} {% if param.publicAccess%} public {% else%} internal {% endif%} {% endset%}
{# Declaring auxiliary macros #}
{% macro parametersBlock types%} {% filter removeNewlines: "leading"%}
{% for type in types%}
_ p {{forloop.counter}}: {{type}} {% if not forloop.last%}, {% endif%}
{% endfor%}
{% endfilter%} {% endmacro%}
{% macro argumentsBlock types%} {% filter removeNewlines: "leading"%}
{% for type in types%}
p {{forloop.counter}} {% if not forloop.last%}, {% endif%}
{% endfor%}
{% endfilter%} {% endmacro%}
{# Declare a macro that creates either a nested enum or a static constant to access the value #}
{% macro recursiveBlock table item sp%}
{{sp}} {% for string in item.strings%}
{{sp}} {% if not param.noComments%}
{{sp}} ///{{string.translation}}
{{sp}} {% endif%}
{{sp}} {% if string.types%}
{{sp}} {{accessModifier}} static func {{string.name | swiftIdentifier: "pretty" | lowerFirstWord | escapeReservedKeywords}} ({% call parametersBlock string.types%}) -> String {
{{sp}} return localize ("{{string.key}}", {% call argumentsBlock string.types%})
{{sp}}}
{{sp}} {% else%}
{{sp}} {{accessModifier}} static let {{string.name | swiftIdentifier: "pretty" | lowerFirstWord | escapeReservedKeywords}} = localize ("{{string.key}}")
{{sp}} {% endif%}
{{sp}} {% endfor%}
{{sp}} {% for child in item.children%}
{{sp}} {{accessModifier}} enum {{child.name | swiftIdentifier: "pretty" | escapeReservedKeywords}} {
{{sp}} {% set sp2%} {{sp}} {% endset%}
{{sp}} {% call recursiveBlock table child sp2%}
{{sp}}}
{{sp}} {% endfor%}
{% endmacro%}
import Foundation
{# Declare the root enum #}
{% set enumName%} {{param.enumName | default: "L10n"}} {% endset%}
{{accessModifier}} enum {{enumName}} {
{% if tables.count> 1%}
{% for table in tables%}
{{accessModifier}} enum {{table.name | swiftIdentifier: "pretty" | escapeReservedKeywords}} {
{% call recursiveBlock table.name table.levels ""%}
}
{% endfor%}
{% else%}
{% call recursiveBlock tables.first.name tables.first.levels ""%}
{% endif%}
}
{# Extend enum Localization for convenient conversion of the key to the required localization string #}
extension Localization {
fileprivate static func localize (_ key: String, _args: CVarArg ) -> String {
return String (
format: NSLocalizedString (key, comment: ""),
locale: Locale.current,
arguments: args
)
}
}

 

The template file itself is conveniently saved in the project root, for example, in the folder SwiftGen /Templates so that this template is available to everyone who works on the project.
 
The utility supports configuration via YAML-file swiftgen.yml , in which you can specify the path to the source files, templates and additional parameters. Create it in the project root in the folder Swiftgen , in the same folder later, we group the other files associated with the script.
 
For our project, this file might look like this:


 
    xcassets:
- paths: /SwiftGenExample/Assets.xcassets
templatePath: Templates /ImageAssets.stencil
output: /SwiftGenExample/Image.swift
params:
enumName: Image
publicAccess: 1
noAllValues: 1
strings:
- paths: /SwiftGenExample/en.lproj/Localizable.strings
templatePath: Templates /LocalizableStrings.stencil
output: /SwiftGenExample/Localization.swift
params:
enumName: Localization
publicAccess: 1
noComments: 0

 

In fact, there are specified paths to files and templates, as well as additional parameters that are passed to the context of the template.
 
Since the file does not lie in the root of the project, we need to specify the path to it when running Swiftgen. Let's change our startup script:


 
    "$ PODS_ROOT" /SwiftGen /bin /swiftgen config run --config SwiftGen /swiftgen.yml    

 

Now our project can be collected. After assembly in the project folder as specified in swiftgen.yml two files should appear in the paths. Localization.swift and Image.swift . They need to be added to the Xcode project. In our case, the generated files contain the following:


 
For strings: [/b]
    public enum Localization {
public enum Languages ​​{
public enum ObjectiveC {
///General-purpose, object-oriented programming language that adds Smalltalk-style messaging to the C programming language
public static let description = localize ("languages.objective-c.description")
///https://en.wikipedia.org/wiki/Objective-C
public static let link = localize ("languages.objective-. link")
///Objective-C
public static let name = localize ("languages.objective-c.name")
}
public enum Swift {
///General-purpose, multi-paradigm, compiled programming language developed by Apple Inc. for iOS, macOS, watchOS, tvOS, and Linux
public static let description = localize ("languages.swift.description")
///https://en.wikipedia.org/wiki/Swift_(programming_language)
public static let link = localize ("languages.swift.link")
///Swift
public static let name = localize ("languages.swift.name")
}
}
public enum MainScreen {
///Language
public static let title = localize ("main-screen.title")
public enum Button {
///View in Wikipedia
public static let title = localize ("main-screen.button.title")
}
}
}
extension Localization {
fileprivate static func localize (_ key: String, _args: CVarArg ) -> String {
return String (
format: NSLocalizedString (key, comment: ""),
locale: Locale.current,
arguments: args
)
}
}

 
For images: [/b]
    public enum Image {
public enum Logos {
public static var objectiveC: UIImage {
return image (named: "ObjectiveC")
}
public static var swift: UIImage {
return image (named: "Swift")
}
}
private static func image (named name: String) -> UIImage {
let bundle = Bundle (for: BundleToken.self)
guard let image = UIImage (named: name, in: bundle, compatibleWith: nil) else {
fatalError ("Unable to load image named (name).")
}
return image
}
}
private final class BundleToken {}

 

Now you can replace all the use of the localization and initialization lines of images of the form UIImage (named: "") on what we have generated. This will make it easier for us to track changes to or delete key locale rows. In either of these cases, the project simply will not meet until all the errors associated with the changes are corrected.
 
After the changes, our code looks like this:


 
    let logos = Image.Logos.self
let localization = Localization.self
private func setupWithLanguage (_ language: ProgrammingLanguage) {
switch language {
case .Swift:
logoImageView.image = logos.swift
nameLabel.text = localization.Languages.Swift.name
descriptionLabel.text = localization.Languages.Swift.description
wikiUrl = localization.Languages.Swift.link.toURL ()
case. ObjectiveC:
logoImageView.image = logos.objectiveC
nameLabel.text = localization.Languages.ObjectiveC.name
descriptionLabel.text = localization.Languages.ObjectiveC.description
wikiUrl = localization.Languages.ObjectiveC.link.toURL ()
}
}

 

Setting up the project in Xcode


 

There is one problem with the generated files: they can be changed manually by mistake, and since they are overwritten from scratch every compilation, these changes can be lost. To avoid this, you can lock the files to write after the execution of the script SwiftGen .
 
This can be achieved with the command chmod . We rewrite our Build Phase with the SwiftGen launch as follows:


 
    if[-f "$SRCROOT"/SwiftGenExample/Image.swift ]; then
chmod + w "$ SRCROOT" /SwiftGenExample/Image.swift
fi
if[-f "$SRCROOT"/SwiftGenExample/Localization.swift ]; then
chmod + w "$ SRCROOT" /SwiftGenExample/Localization.swift
fi
"$ PODS_ROOT" /SwiftGen /bin /swiftgen config run --config SwiftGen /swiftgen.yml
chmod -w "$ SRCROOT" /SwiftGenExample/Image.swift
chmod -w "$ SRCROOT" /SwiftGenExample/Localization.swift

 

The script is quite simple. Before starting the generation, if the files exist, we issue write permissions for them. After running the script, we block the ability to modify the files.
 
For convenience of editing and checking the script on the review it is convenient to put it in a separate file runswiftgen.sh . The final version of the script with some minor modifications can be found here. Now our Build Phase will look like this: enter the script to the path to the project's root folder and the path to the Pods folder:


 
    "$ SRCROOT" /SwiftGen/runswiftgen.sh "$ SRCROOT" "$ PODS_ROOT"    

 

We rebuild the project, and now when you try to change the generated file manually, a warning will appear:


 


 

So, the folder with Swiftgen now contains a configuration file, a script for blocking files and running Swiftgen and a folder with customized templates. It is convenient to add it to the project for further editing if necessary.


 


 

And since the files are Localization.swift and Image.swift are generated automatically, they can be added to .gitignore, so once again they do not solve conflicts after git merge .
 
Results of
 
SwiftGen is a good tool for protecting against our inattention when working with project resources. Using it, we managed to automatically generate code to access the resources of the application and to shift some of the work on checking the relevance of resources on the shoulders of the compiler, which means that we can simplify our work a little. In addition, we configured the Xcode project so that further work with the tool was more convenient.
 
Pros:
 
 
It is easier to control the resources of the project.
 
The probability of typos is reduced, it becomes possible to use auto-substitution.
 
Errors are checked at compile time.
 
 
Cons:
 
 
There is no support for Localizable.stringsdict.
 
Resources that are not used are not considered.
 
 
You can see the whole example at githabe

It may be interesting

  • Comments
  • About article
  • Similar news
Archie 13 April 2020 07:51
The blog is listing the most valuable mobile applications and their controls with the set up. The swiftgen rushessay reviews are now used to gain so many applications. So, we all been happy to use your mobile applications and resources.

weber

Author

16-09-2018, 21:11

Publication Date

Development of mobile applications / Swift

Category
  • Comments: 1
  • Views: 517
Serverless will kill DevOps?
Network administrator in the era of
Ideal requirements are returned
For what and how do backlog grooming in
Project Manager vs Product Manager: who
We will understand Nirvana, the
Write a comment
Name:*
E-Mail:


Comments
I genuinely believed you would probably have something useful to say. All I hear is a bunch of whining about something that you can fix if you were not too busy looking for attention. After all, I know it was my choice to read .. [url = https: //gamebnat.net] 먹튀 [/ url]

Today, 15:56

raymond weber

Lots of interesting comments, but it feels like users are really experts in their field, and it's very cool!
Today, 15:49

claudedufont

This is a good idea, thank you very much to the author!
Today, 15:47

claudedufont

I learned a lot of interesting things on this topic, and it really interested me! Good and smart comments from users!
Today, 15:47

claudedufont


We have years of experience in repairing fences and we can give you one that you will love! No matter what type of fence you have, we can fix it for you. Check Out:
All fences cape coral



Today, 15:03

noorseo

Adv
Website for web developers. New scripts, best ideas, programming tips. How to write a script for you here, we have a lot of information about various programming languages. You are a webmaster or a beginner programmer, it does not matter, useful articles will help to make your favorite business faster.

Login

Registration Forgot password