Add ///@mockolo to certain file of the API repository

Method 1: Make mockable annotation to certain files

  1. make bash file
#!/bin/bash
sed -i '' '12i\
/// @mockable' File.swift

12 is line number

2. edit Makefile

all: mockable

mockable:
	./mockable.bash

3.

$PROJECT_DIR/third_party/mockolo -s Pods/Backend -d Neo/Generated/MockAPI.swift

Method 2: Make mockable annotations to all files and that mockolo to read certain files

  1. Edit api.mustache file
/// @mockable you need to include the file to ios/scripts/generate-mock.bash to make Mock.
public protocol {{apiPrefix}}{{classname}}Type {

2.

$PROJECT_DIR/third_party/mockolo -srcs Pods/Backend/social/Classes/Swaggers/APIs/CertainAPI.swift -d [project]/Generated/MockAPI.swift

Make swift enum cases snake_case

I have a special enum only for analytics. The analytics requirements are all in snake_case. I want to make enum cases by copy and paste the requirements preserving snake_case. But sometimes I habitually make cases camelCase when I forget to copy and paste. Therefore I made a script that makes cases snake_case.

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

#go to project directory
 cd $SCRIPT_DIR/.. 

 sed -i '' '/^ *case [^\.]*$/s/\([a-z0-9]\)\([A-Z]\)/\1_\2/g' [projet_name]/[path]/[filename].swift

“-i” is to edit the file

“^” starts with

” *” multiple blanks

[^\.]*$ does not contain .

s/A/B substitute A to B

/g is to use \1 and \2

” it’s needed for Mac

Bash script file

  • bash is a script file. improved version of sh. Runs on Linux and Unix
    • Linux belongs to Unix family. But Linux is open source and Unix is not. Linux is more customizable while Unix is more stable and often used in enterprises.
    • Mac is Unix but includes it’s own technology of Apple. So Mac is often called hybrid Unix.
  • #!/bin/bash means the script should be executed using the Bash shell. If you want to execute the script using a different shell, you can specify its path instead, such as #!/bin/sh or #!/bin/zsh.

When you want to use ‘continue’ in map

Answer by ChatGPT

In Swift, you cannot use continue statement inside the map function because map function traverses each element of an array and executes a closure for each element, and continue statement can only be used inside a loop. However, there is a way to skip a specific element and continue to the next iteration inside the map function. You can achieve this by using a conditional statement inside the closure to skip the element. For example, if you want to skip odd numbers and process only even numbers in an array, you can write the following code:

let numbers = [1, 2, 3, 4, 5, 6]
let evenNumbers = numbers.map { number in
    if number % 2 != 0 {
        return nil // skip the element by returning nil
    }
    return number * 2 // process even numbers by returning a value
}.compactMap { $0 } // remove nil values

print(evenNumbers) // [4, 8, 12]

In the code above, we return nil to skip odd numbers and return a value to process even numbers inside the map function. Then, we use the compactMap function to remove nil values and print the result.

Therefore, although you cannot use continue statement inside the map function, you can skip a specific element and continue to the next iteration by using a conditional statement inside the closure.

If you gets error “Generic parameter ‘ElementOfResult’ could not be inferred”, add return type to the map closure

from

let monthlyDividendViewModels = dividendResponse.monthlyDividends
                    .map { monthlySummary in
                        guard let month = monthlySummary.paymentMonth else {
                            return nil
                        }
                        return MonthlyDividendViewModel(sum: sum, stockDividends: stockDividends)
                    }
                    .compactMap { $0 }

to

let monthlyDividendViewModels = dividendResponse.monthlyDividends
                    .map { monthlySummary -> MonthlyDividendViewModel? in
                        guard let month = monthlySummary.paymentMonth else {
                            return nil
                        }
                        return MonthlyDividendViewModel(sum: sum, stockDividends: stockDividends)
                    }
                    .compactMap { $0 }

swift generate boilerplate code with automation using gyb

  1. gyb stands for Generate Your Boilerplate https://nshipster.co.kr/swift-gyb/
  2. its python
  3. python comment out: #
  4. Download gyb from https://github.com/apple/swift/blob/main/utils/gyb.py
  5. Add script to run gyb files into Build Phases or Add to shell script which runs gyb file to make Swift files.
find . -name '*.gyb' |                                               \
    while read file; do                                              \
        ${SCRIPT_DIR}/gyb.py --line-directive '' -o "${file%.gyb}" "$file"; \
    done
  1. Add “.gyb” to the name of Swift file you want to make
  2. Except for the swift code to put you need to prefix %, and you have to write “end” in the same depth of condition
enum AppEventComponent: String {
% for component in appEventComponents:
    % if component[0].isdigit():
        case _${component} = "${component}"
    % else:
        case ${component}
    % end
% end
}

4. set doesn’t have .sort() function. use sorted instead. Because Set does not have order, sorted() returns list.

appEventModules = sorted(appEventModules)

5. If you want to change cases in Swift to list for python, it’s convenient to use “replace regex” with “()”, “$1”.

6. To prevent duplication, use Enum. duplication in Enum makes compile error but Set doesn’t. If name is value, use “auto”

It’s a script which makes enum case if you put event name with format of “screen_button_action”

//
// This file is auto-generated.
// Run ./scripts/generate-gyb.bash
//
%{
    from enum import Enum, auto

    class Event(Enum):
        # Add new statistics events
        market_filter__main__enter = auto()

    class AppEventModule(Enum):
        add_buy = auto()

    class AppEventComponent(Enum):
        _1y = auto()

    class AppEventAction(Enum):
        enter = auto()

    appEventModules = set()
    appEventComponents = set()
    appEventActions = set()

    for event in Event:
        for (index, value) in enumerate(event.name.split('__')):
            if index == 0: appEventModules.add(value)
            elif index == 1: appEventComponents.add(value)
            elif index == 2: appEventActions.add(value)

    for module in AppEventModule:
        appEventModules.add(module.name)

    for component in AppEventComponent:
        if component.name.startswith('_'):
            appEventComponents.add(component.name[1:])
        else:
            appEventComponents.add(component.name)

    for action in AppEventAction:
        appEventActions.add(action.name)

    appEventModules = sorted(appEventModules)
    appEventComponents = sorted(appEventComponents)
    appEventActions = sorted(appEventActions)
}%
import Foundation

enum AppEventModule: String {
% for module in appEventModules:
    case ${module}
% end
}

enum AppEventComponent: String {
% for component in appEventComponents:
    % if component[0].isdigit():
        case _${component} = "${component}"
    % else:
        case ${component}
    % end
% end
}

enum AppEventAction: String {
% for action in appEventActions:
    case ${action}
% end
}