├── .github └── workflows │ └── test_each_pull_request.yml ├── .gitignore ├── LICENSE ├── Makefile ├── Package.resolved ├── Package.swift ├── README.md ├── Sources ├── UserDefaultsGenerator │ └── main.swift └── UserDefaultsGeneratorCore │ ├── ConfigurationParser.swift │ ├── Generator.swift │ ├── Runner.swift │ ├── RunnerArgumentParser.swift │ ├── StdlibExtension.swift │ ├── SwiftType.swift │ └── Template.swift ├── Tests ├── LinuxMain.swift └── UserDefaultsGeneratorCoreTests │ ├── GeneratorTests.swift │ ├── StdlibExtensionTests.swift │ └── XCTestManifests.swift ├── UserDefaultsGenerator.generated.swift ├── UserDefaultsGeneratorDemo ├── UserDefaultsGeneratorDemo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── UserDefaultsGeneratorDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── ViewController.swift ├── UserDefaultsGeneratorDemoTests │ ├── Info.plist │ └── UserDefaultsGeneratorDemoTests.swift └── UserDefaultsGeneratorDemoUITests │ ├── Info.plist │ └── UserDefaultsGeneratorDemoUITests.swift ├── template.stencil └── udg.yml /.github/workflows/test_each_pull_request.yml: -------------------------------------------------------------------------------- 1 | name: test_each_pull_request 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: macOS-latest 8 | steps: 9 | - uses: actions/checkout@v1 10 | - name: Run xcodebuild test 11 | run: make test 12 | - name: Upload codecov 13 | run: | 14 | bash <(curl -s https://codecov.io/bash) -J '^UserDefaultsGeneratorCore$' \ 15 | -D .build/derivedData 16 | env: 17 | CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}} 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 bannzai 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROJECT?=UserDefaultsGenerator 2 | COMMANDNAME?=udg 3 | 4 | build: 5 | swift build 6 | xcodeproj: 7 | swift package generate-xcodeproj 8 | 9 | generate: build 10 | ./.build/x86_64-apple-macosx/debug/udg generate 11 | generate-output: build 12 | ./.build/x86_64-apple-macosx/debug/udg generate --output A.generated.swift 13 | generate-output-config: build 14 | ./.build/x86_64-apple-macosx/debug/udg generate --output B.generated.swift --config udg.yml 15 | generate-output-config-template: build 16 | ./.build/x86_64-apple-macosx/debug/udg generate --output C.generated.swift --config udg.yml --template ./template.stencil 17 | 18 | setup: build 19 | ./.build/x86_64-apple-macosx/debug/udg setup 20 | 21 | help: build 22 | ./.build/x86_64-apple-macosx/debug/udg help 23 | 24 | test: build xcodeproj 25 | xcodebuild clean build test -project UserDefaultsGenerator.xcodeproj \ 26 | -scheme UserDefaultsGenerator \ 27 | -destination platform="macOS" \ 28 | -enableCodeCoverage YES \ 29 | -derivedDataPath .build/derivedData \ 30 | CODE_SIGN_IDENTITY="" \ 31 | CODE_SIGNING_REQUIRED=NO \ 32 | ONLY_ACTIVE_ARCH=NO 33 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "PathKit", 6 | "repositoryURL": "https://github.com/kylef/PathKit.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "e2f5be30e4c8f531c9c1e8765aa7b71c0a45d7a0", 10 | "version": "0.9.2" 11 | } 12 | }, 13 | { 14 | "package": "Spectre", 15 | "repositoryURL": "https://github.com/kylef/Spectre.git", 16 | "state": { 17 | "branch": null, 18 | "revision": "f14ff47f45642aa5703900980b014c2e9394b6e5", 19 | "version": "0.9.0" 20 | } 21 | }, 22 | { 23 | "package": "Stencil", 24 | "repositoryURL": "https://github.com/stencilproject/Stencil.git", 25 | "state": { 26 | "branch": null, 27 | "revision": "0e9a78d6584e3812cd9c09494d5c7b483e8f533c", 28 | "version": "0.13.1" 29 | } 30 | }, 31 | { 32 | "package": "StencilSwiftKit", 33 | "repositoryURL": "https://github.com/SwiftGen/StencilSwiftKit.git", 34 | "state": { 35 | "branch": null, 36 | "revision": "dbf02bd6afe71b65ead2bd250aaf974abc688094", 37 | "version": "2.7.2" 38 | } 39 | }, 40 | { 41 | "package": "Yams", 42 | "repositoryURL": "https://github.com/jpsim/Yams.git", 43 | "state": { 44 | "branch": null, 45 | "revision": "c947a306d2e80ecb2c0859047b35c73b8e1ca27f", 46 | "version": "2.0.0" 47 | } 48 | } 49 | ] 50 | }, 51 | "version": 1 52 | } 53 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "UserDefaultsGenerator", 8 | products: [ 9 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 10 | .executable(name: "udg", targets: ["UserDefaultsGenerator"]), 11 | .library( 12 | name: "UserDefaultsGeneratorCore", 13 | targets: ["UserDefaultsGeneratorCore"]), 14 | ], 15 | dependencies: [ 16 | // Dependencies declare other packages that this package depends on. 17 | // .package(url: /* package url */, from: "1.0.0"), 18 | .package(url: "https://github.com/jpsim/Yams.git", from: Version(2, 0, 0)), 19 | .package(url: "https://github.com/SwiftGen/StencilSwiftKit.git", from: Version(2, 7, 2)), 20 | ], 21 | targets: [ 22 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 23 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 24 | .target( 25 | name: "UserDefaultsGenerator", 26 | dependencies: ["UserDefaultsGeneratorCore"]), 27 | .target( 28 | name: "UserDefaultsGeneratorCore", 29 | dependencies: ["Yams", "StencilSwiftKit"]), 30 | .testTarget( 31 | name: "UserDefaultsGeneratorCoreTests", 32 | dependencies: ["UserDefaultsGeneratorCore"]), 33 | ] 34 | ) 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## UserDefaultsGenerator 2 | UserDefaultsGenerator generate swift code for easily management for (NS)UserDefaults key and value type. 3 | 4 | ## Usage 5 | First, you should prepare `udg.yml` file of below structure. 6 | 7 | ```yml 8 | - name: numberOfIndent 9 | type: Int 10 | 11 | - name: UserSelectedDarkMode 12 | type: Bool 13 | key: DarkMode 14 | 15 | - name: XYZ 16 | type: Array 17 | ``` 18 | 19 | Next, and exec below command. 20 | ``` 21 | $ udg generate 22 | ``` 23 | 24 | Last, you can confirm result of udg command about generated swift code for managiment UserDefaults. 25 | ```swift 26 | public enum UDGArrayKey: String { 27 | case XYZ 28 | } 29 | public enum UDGBoolKey: String { 30 | case UserSelectedDarkMode = "DarkMode" 31 | } 32 | public enum UDGIntKey: String { 33 | case numberOfIndent 34 | } 35 | 36 | // MARK: - UserDefaults Array Extension 37 | extension UserDefaults { 38 | public func array(forKey key: UDGArrayKey) -> [Any]? { 39 | return array(forKey: key.rawValue) 40 | } 41 | public func set(_ value: [Any]?, forKey key: UDGArrayKey) { 42 | set(value, forKey: key.rawValue) 43 | synchronize() 44 | } 45 | } 46 | // MARK: - Bool Extension 47 | extension UserDefaults { 48 | public func bool(forKey key: UDGBoolKey) -> Bool { 49 | return bool(forKey: key.rawValue) 50 | } 51 | public func set(_ value: Bool, forKey key: UDGBoolKey) { 52 | set(value, forKey: key.rawValue) 53 | synchronize() 54 | } 55 | } 56 | // MARK: - Int Extension 57 | extension UserDefaults { 58 | public func integer(forKey key: UDGIntKey) -> Int { 59 | return integer(forKey: key.rawValue) 60 | } 61 | public func set(_ value: Int, forKey key: UDGIntKey) { 62 | set(value, forKey: key.rawValue) 63 | synchronize() 64 | } 65 | } 66 | 67 | ``` 68 | 69 | ### udg command option 70 | ```shell 71 | $ udg --help 72 | Usage: 73 | udg [command] 74 | 75 | Available Commands: 76 | generate generate [--output $OUTPUT_PATH] [--config $CONFIG_PATH] [--template $TEMPLATE_PATH] 77 | setup setup can be generated example config file 78 | help Help about any command 79 | ``` 80 | 81 | #### udg generate command option description 82 | | Option | Description | 83 | | ---- | ---- | 84 | | --output | Output path for generated swift code. Default is UserDefaultsGenerator.generated.swift | 85 | | --config | Input configuration path of yml file. Default is ./udg.yml | 86 | | --template | Using template path about swift code. Template format is stencil. | 87 | 88 | 89 | 90 | 91 | ## Yaml Configuration 92 | | Key | Description | Required/Optional | 93 | | ---- | ---- | ---- | 94 | | name | Name of UserDefaults type key | Required | 95 | | type | Type of UserDefaults stored value | Required | 96 | | key | Custom key name if you want to use different name | Optional | 97 | 98 | 99 | ### Supported Swift Type 100 | Everything supported by Apple's UserDefaults is supported in a similar format. 101 | Document: https://developer.apple.com/documentation/foundation/userdefaults 102 | 103 | | SwiftType | Yaml configuration `type` name | 104 | | ---- | ---- | 105 | | Any | Any | 106 | | URL | URL | 107 | | [Any] | Array | 108 | | [String: Any] | Dictionary | 109 | | String | String | 110 | | [String] | StringArray | 111 | | Data | Data | 112 | | Bool | Bool | 113 | | Int | Int | 114 | | Float | Float | 115 | | Double | Double | 116 | 117 | [See also, SwiftType.swift](./Sources/UserDefaultsGeneratorCore/SwiftType.swift) 118 | 119 | ## Install 120 | It is recommended to use `mint` 121 | 122 | ```shell 123 | $ mint install bannzai/UserDefaultsGenerator 124 | ``` 125 | 126 | ## LICENSE 127 | UserDefaultsGenerator is available under the MIT license. See the LICENSE file for more info. 128 | 129 | -------------------------------------------------------------------------------- /Sources/UserDefaultsGenerator/main.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import UserDefaultsGeneratorCore 3 | 4 | let runners: [Runner.Type] = [ 5 | GenerateRunner.self, 6 | SetupRunner.self, 7 | HelpRunner.self 8 | ] 9 | 10 | let arguments = ProcessInfo.processInfo.arguments 11 | if arguments.count <= 1 || !runners.contains { $0.commandName == arguments[1] } { 12 | print(""" 13 | Missing argument. 14 | See below 15 | \(HelpRunner.help()) 16 | """) 17 | exit(1) 18 | } 19 | 20 | let subCommand = ProcessInfo.processInfo.arguments[1] 21 | guard let command = runners.first(where: { $0.commandName == subCommand }) else { 22 | print(""" 23 | Unexpected sub command \(subCommand) 24 | See below 25 | \(HelpRunner.help()) 26 | """) 27 | exit(1) 28 | } 29 | 30 | try command.init().run() 31 | -------------------------------------------------------------------------------- /Sources/UserDefaultsGeneratorCore/ConfigurationParser.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Yams 3 | 4 | public struct Configuration: Decodable { 5 | public let name: String 6 | public let type: SwiftType 7 | public let key: String? 8 | } 9 | 10 | public protocol ConfigurationParser { 11 | func parse(yamlFilePath: URL) throws -> [Configuration] 12 | } 13 | 14 | public struct YAMLParser: ConfigurationParser { 15 | public init() { } 16 | func read(yamlFilePath: URL) throws -> String { 17 | return try String(contentsOf: yamlFilePath) 18 | } 19 | public func parse(yamlFilePath: URL) throws -> [Configuration] { 20 | let decoder = YAMLDecoder() 21 | let decoded = try decoder.decode([Configuration].self, from: try read(yamlFilePath: yamlFilePath)) 22 | return decoded 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Sources/UserDefaultsGeneratorCore/Generator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generator.swift 3 | // CYaml 4 | // 5 | // Created by Yudai Hirose on 2019/09/18. 6 | // 7 | 8 | import Foundation 9 | import StencilSwiftKit 10 | 11 | let tab = "\t" 12 | public protocol Generator { 13 | func generate(outputPath: URL, templatePath: URL?, configurations: [Configuration]) throws 14 | } 15 | 16 | public struct GeneratorImpl: Generator { 17 | public init(){ } 18 | public func generate(outputPath: URL, templatePath: URL?, configurations: [Configuration]) throws { 19 | let content: String 20 | switch templatePath { 21 | case nil: 22 | content = """ 23 | import Foundation 24 | \(enumDefinition(configurations: configurations)) 25 | \(userDefaultsExtensions(configurations: configurations)) 26 | """ 27 | case let templatePath?: 28 | let template = try String(contentsOf: templatePath) 29 | content = try StencilSwiftTemplate( 30 | templateString: template, 31 | environment: stencilSwiftEnvironment(), 32 | name: "udg.user_defined.swift.stencil" 33 | ) 34 | .render(buildArguments(configurations)) 35 | } 36 | try content.write(to: outputPath, atomically: true, encoding: .utf8) 37 | } 38 | 39 | } 40 | 41 | private func buildArguments(_ configurations: [Configuration]) -> [String: Any] { 42 | let groupedConfigurations = configurations.grouped { $0.type }.ordered() 43 | return [ 44 | "groupedConfigurations": groupedConfigurations 45 | .map { (swiftType, configurations) -> [String: Any] in 46 | return [ 47 | "key": swiftType, 48 | "typeName": swiftType.typeName, 49 | "aliasName": swiftType.aliasName, 50 | "isOptionalType": swiftType.isOptional, 51 | "getterMethodName": swiftType.getterMethodName, 52 | "configurations": configurations 53 | .map { configuration -> [String: Any] in 54 | return [ 55 | "name": configuration.name, 56 | "key": configuration.key ?? "" 57 | ] 58 | 59 | } 60 | ] 61 | 62 | } 63 | 64 | ] 65 | } 66 | 67 | func enumDefinition(configurations: [Configuration]) -> String { 68 | return try! StencilSwiftTemplate( 69 | templateString: TemplateType.enum.template, 70 | environment: stencilSwiftEnvironment(), 71 | name: "enum.swift.stencil" 72 | ) 73 | .render(buildArguments(configurations)) 74 | } 75 | 76 | func userDefaultsExtensions(configurations: [Configuration]) -> String { 77 | return try! StencilSwiftTemplate( 78 | templateString: TemplateType.extension.template, 79 | environment: stencilSwiftEnvironment(), 80 | name: "extension.swift.stencil" 81 | ) 82 | .render(buildArguments(configurations)) 83 | } 84 | -------------------------------------------------------------------------------- /Sources/UserDefaultsGeneratorCore/Runner.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Runner.swift 3 | // CYaml 4 | // 5 | // Created by Yudai Hirose on 2019/09/21. 6 | // 7 | 8 | import Foundation 9 | 10 | public protocol Runner { 11 | static var commandName: String { get } 12 | init() 13 | func run() throws 14 | } 15 | 16 | public struct GenerateRunner: Runner { 17 | public static let commandName: String = "generate" 18 | 19 | // TODO: Use Opaque Result Type 20 | private let argumentParser: GenerateRunnerArgumentParser 21 | private let configurationParser: ConfigurationParser 22 | private let generator: Generator 23 | public init( 24 | argumentParser: GenerateRunnerArgumentParser, 25 | configurationParser: ConfigurationParser, 26 | generator: Generator 27 | ) { 28 | self.argumentParser = argumentParser 29 | self.configurationParser = configurationParser 30 | self.generator = generator 31 | } 32 | 33 | public init() { 34 | self.init(argumentParser: GenerateRunnerArgumentParser(), configurationParser: YAMLParser(), generator: GeneratorImpl()) 35 | } 36 | 37 | public func run() throws { 38 | let options = argumentParser.parse() 39 | let configurations = try configurationParser.parse(yamlFilePath: options.configPath) 40 | try generator.generate(outputPath: options.outputURL, templatePath: options.templatePath, configurations: configurations) 41 | } 42 | } 43 | 44 | public struct SetupRunner: Runner { 45 | public static let commandName: String = "setup" 46 | 47 | public init() { } 48 | public func run() throws { 49 | let content = """ 50 | - name: numberOfIndent 51 | type: Int 52 | 53 | - name: UserSelectedDarkMode 54 | type: Bool 55 | key: DarkMode 56 | 57 | 58 | """ 59 | try content.write(to: URL(fileURLWithPath: currentWorkingDirectory()).appendingPathComponent("udg.yml"), atomically: true, encoding: .utf8) 60 | } 61 | } 62 | 63 | public struct HelpRunner: Runner { 64 | public static let commandName: String = "help" 65 | 66 | public static func help() -> String { 67 | return """ 68 | Usage: 69 | udg [command] 70 | 71 | Available Commands: 72 | generate generate [--output $OUTPUT_PATH] [--config $CONFIG_PATH] [--template $TEMPLATE_PATH] 73 | setup setup can be generated example config file 74 | help Help about any command 75 | """ 76 | } 77 | 78 | public init() { } 79 | public func run() throws { 80 | print(HelpRunner.help()) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Sources/UserDefaultsGeneratorCore/RunnerArgumentParser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RunnerArgumentParser.swift 3 | // CYaml 4 | // 5 | // Created by Yudai Hirose on 2019/09/21. 6 | // 7 | 8 | import Foundation 9 | 10 | public typealias RunnerArguments = [String] 11 | 12 | public protocol RunnerArgumentParser { 13 | associatedtype Argument 14 | func parse() -> Argument 15 | } 16 | 17 | 18 | func currentWorkingDirectory() -> String { 19 | switch ProcessInfo.processInfo.environment["YMD_DEBUG_CWD"] { 20 | case nil: 21 | return FileManager.default.currentDirectoryPath 22 | case let cwd?: 23 | return cwd 24 | } 25 | } 26 | 27 | public struct GenerateRunnerArgumentParser: RunnerArgumentParser { 28 | enum Option: String, CaseIterable { 29 | case output 30 | case config 31 | case template 32 | 33 | var option: String { 34 | return "--\(rawValue)" 35 | } 36 | 37 | init?(option: String) { 38 | switch Option.allCases.first(where: { $0.option == option }) { 39 | case nil: 40 | return nil 41 | case let option?: 42 | self = option 43 | } 44 | } 45 | } 46 | 47 | public init() { } 48 | 49 | public func parse() -> (outputURL: URL, configPath: URL, templatePath: URL?) { 50 | let arguments = ProcessInfo.processInfo.arguments 51 | let options = arguments 52 | .enumerated() 53 | .filter { Option.allCases.map { $0.option }.contains($1) } 54 | .map { (offset: $0, option: Option(option: $1)!) } 55 | .map { (offset: $0, option: $1, value: arguments[$0 + 1]) } 56 | 57 | let cwd = URL(fileURLWithPath: currentWorkingDirectory()) 58 | 59 | let outputURL: URL 60 | if let option = options.first (where: { $0.option == .output }) { 61 | outputURL = cwd.appendingPathComponent(option.value) 62 | } else { 63 | let swiftFileName = "UserDefaultsGenerator.generated.swift" 64 | outputURL = cwd.appendingPathComponent(swiftFileName) 65 | } 66 | 67 | let configPath: URL 68 | if let option = options.first(where: { $0.option == .config }) { 69 | configPath = cwd.appendingPathComponent(option.value) 70 | } else { 71 | let yamlFileName = "udg.yml" 72 | configPath = cwd.appendingPathComponent(yamlFileName) 73 | } 74 | 75 | var templatePath: URL? = nil 76 | if let option = options.first(where: { $0.option == .template }) { 77 | templatePath = cwd.appendingPathComponent(option.value) 78 | } 79 | 80 | return (outputURL: outputURL, configPath: configPath, templatePath: templatePath) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Sources/UserDefaultsGeneratorCore/StdlibExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StdlibExtension.swift 3 | // UserDefaultsGeneratorCore 4 | // 5 | // Created by Yudai Hirose on 2019/09/21. 6 | // 7 | 8 | import Foundation 9 | 10 | extension Collection { 11 | func grouped(_ closure: (Element) -> (T)) -> [T: [Element]] { 12 | return reduce(into: [T: [Element]]()){ result, element in 13 | let key = closure(element) 14 | switch result[key] { 15 | case nil: 16 | result[key] = [element] 17 | case let a?: 18 | result[key] = a + [element] 19 | } 20 | } 21 | } 22 | } 23 | 24 | extension Dictionary where Key: Comparable { 25 | func ordered() -> [(key: Key, value: Value)] { 26 | return map { $0 }.sorted { $0.key < $1.key } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Sources/UserDefaultsGeneratorCore/SwiftType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftType.swift 3 | // CYaml 4 | // 5 | // Created by Yudai Hirose on 2019/09/20. 6 | // 7 | 8 | import Foundation 9 | 10 | public enum SwiftType: String, Decodable { 11 | case any = "Any" 12 | case url = "URL" 13 | case array = "Array" 14 | case dictionary = "Dictionary" 15 | case string = "String" 16 | case stringArray = "StringArray" 17 | case data = "Data" 18 | case bool = "Bool" 19 | case int = "Int" 20 | case float = "Float" 21 | case double = "Double" 22 | 23 | var typeName: String { 24 | switch self { 25 | case .array: 26 | return "[Any]" 27 | case .dictionary: 28 | return "[String: Any]" 29 | case .stringArray: 30 | return "[String]" 31 | case .any, .url, .string, .data, .bool, .int, .float, .double: 32 | return aliasName 33 | } 34 | } 35 | 36 | var aliasName: String { 37 | return rawValue 38 | } 39 | 40 | var isOptional: Bool { 41 | switch self { 42 | case .any, .url, .array, .dictionary, .string, .stringArray, .data: 43 | return true 44 | case .bool, .int, .float, .double: 45 | return false 46 | } 47 | } 48 | 49 | var getterMethodName: String { 50 | switch self { 51 | case .int: 52 | return "integer" 53 | case .any: 54 | return "object" 55 | case _: 56 | return "\(self)" 57 | } 58 | } 59 | } 60 | 61 | 62 | extension SwiftType: Comparable { 63 | public static func < (lhs: SwiftType, rhs: SwiftType) -> Bool { 64 | return lhs.rawValue < rhs.rawValue 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Sources/UserDefaultsGeneratorCore/Template.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Template.swift 3 | // CYaml 4 | // 5 | // Created by Yudai Hirose on 2019/09/21. 6 | // 7 | 8 | import Foundation 9 | 10 | enum TemplateType { 11 | case `enum` 12 | case `extension` 13 | 14 | var template: String { 15 | switch self { 16 | case .enum: 17 | return """ 18 | {% for groupuedConfiguration in groupedConfigurations where not groupedConfigurations.count == 0 %} 19 | public enum UDG{{ groupuedConfiguration.aliasName }}Key: String { 20 | {% for configuration in groupuedConfiguration.configurations where not groupedConfiguration.configurations.count == 0 %} 21 | \(tab)case {% if configuration.key == "" %}{{ configuration.name }}{% else %}{{ configuration.name }} = "{{ configuration.key }}"{% endif %} 22 | {% endfor %} 23 | } 24 | {% endfor %} 25 | """ 26 | case .extension: 27 | return """ 28 | {% for groupedConfiguration in groupedConfigurations where not groupedConfigurations.count == 0 %} 29 | {% set gc groupedConfiguration %} 30 | // MARK: - UserDefaults {{ gc.aliasName }} Extension 31 | extension UserDefaults { 32 | \(tab)public func {{ gc.getterMethodName }}(forKey key: UDG{{ gc.aliasName }}Key) -> {{ gc.typeName }}{% if gc.isOptionalType %}?{% endif %} { 33 | \(tab)\(tab)return {{ gc.getterMethodName }}(forKey: key.rawValue) 34 | \(tab)} 35 | \(tab)public func set(_ value: {{ gc.typeName }}{% if gc.isOptionalType %}?{% endif %}, forKey key: UDG{{ gc.aliasName }}Key) { 36 | \(tab)\(tab)set(value, forKey: key.rawValue) 37 | \(tab)\(tab)synchronize() 38 | \(tab)} 39 | } 40 | {% endfor %} 41 | """ 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import UserDefaultsGeneratorTests 4 | 5 | var tests = [XCTestCaseEntry]() 6 | tests += UserDefaultsGeneratorTests.allTests() 7 | XCTMain(tests) 8 | -------------------------------------------------------------------------------- /Tests/UserDefaultsGeneratorCoreTests/GeneratorTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GeneratorTests.swift 3 | // UserDefaultsGeneratorTests 4 | // 5 | // Created by Yudai Hirose on 2019/09/19. 6 | // 7 | 8 | import XCTest 9 | @testable import UserDefaultsGeneratorCore 10 | 11 | class GeneratorTests: XCTestCase { 12 | 13 | 14 | func testEnumDefinition() { 15 | XCTContext.runActivity(named: "When key is nil") { (_) in 16 | let configurations: [Configuration] = [ 17 | Configuration(name: "enumKey", type: .int, key: nil), 18 | ] 19 | let got = enumDefinition(configurations: configurations) 20 | let expected = """ 21 | 22 | public enum UDGIntKey: String { 23 | \(tab)case enumKey 24 | } 25 | 26 | """ 27 | XCTAssertEqual(got, expected) 28 | } 29 | XCTContext.runActivity(named: "When configuration for custom key") { (_) in 30 | let configurations: [Configuration] = [ 31 | Configuration(name: "enumKey", type: .bool, key: "Custom"), 32 | ] 33 | let got = enumDefinition(configurations: configurations) 34 | let expected = """ 35 | 36 | public enum UDGBoolKey: String { 37 | \(tab)case enumKey = "Custom" 38 | } 39 | 40 | """ 41 | XCTAssertEqual(got, expected) 42 | } 43 | XCTContext.runActivity(named: "When configuration for aliasName != typeName") { (_) in 44 | 45 | let type = SwiftType.array 46 | XCTAssert(type.aliasName != type.typeName) 47 | 48 | let configurations: [Configuration] = [ 49 | Configuration(name: "enumKey", type: type, key: nil), 50 | ] 51 | let got = enumDefinition(configurations: configurations) 52 | let expected = """ 53 | 54 | public enum UDGArrayKey: String { 55 | \(tab)case enumKey 56 | } 57 | 58 | """ 59 | XCTAssertEqual(got, expected) 60 | } 61 | } 62 | 63 | func testUserDefaultsExtensions() { 64 | XCTContext.runActivity(named: "When swift type is Int") { (_) in 65 | let configurations: [Configuration] = [ 66 | Configuration(name: "enumKey", type: .int, key: nil), 67 | ] 68 | let got = userDefaultsExtensions(configurations: configurations) 69 | let expected = """ 70 | 71 | // MARK: - UserDefaults Int Extension 72 | extension UserDefaults { 73 | \(tab)public func integer(forKey key: UDGIntKey) -> Int { 74 | \(tab)\(tab)return integer(forKey: key.rawValue) 75 | \(tab)} 76 | \(tab)public func set(_ value: Int, forKey key: UDGIntKey) { 77 | \(tab)\(tab)set(value, forKey: key.rawValue) 78 | \(tab)\(tab)synchronize() 79 | \(tab)} 80 | } 81 | 82 | """ 83 | XCTAssertEqual(got, expected) 84 | } 85 | XCTContext.runActivity(named: "When swift type is Bool. And add custom enum key name") { (_) in 86 | let configurations: [Configuration] = [ 87 | Configuration(name: "enumKey", type: .bool, key: "Custom"), 88 | ] 89 | let got = userDefaultsExtensions(configurations: configurations) 90 | let expected = """ 91 | 92 | // MARK: - UserDefaults Bool Extension 93 | extension UserDefaults { 94 | \(tab)public func bool(forKey key: UDGBoolKey) -> Bool { 95 | \(tab)\(tab)return bool(forKey: key.rawValue) 96 | \(tab)} 97 | \(tab)public func set(_ value: Bool, forKey key: UDGBoolKey) { 98 | \(tab)\(tab)set(value, forKey: key.rawValue) 99 | \(tab)\(tab)synchronize() 100 | \(tab)} 101 | } 102 | 103 | """ 104 | XCTAssertEqual(got, expected) 105 | } 106 | XCTContext.runActivity(named: "When swift type is Any. Any is optional type") { (_) in 107 | let configurations: [Configuration] = [ 108 | Configuration(name: "enumKey", type: .any, key: nil), 109 | ] 110 | let got = userDefaultsExtensions(configurations: configurations) 111 | let expected = """ 112 | 113 | // MARK: - UserDefaults Any Extension 114 | extension UserDefaults { 115 | \(tab)public func object(forKey key: UDGAnyKey) -> Any? { 116 | \(tab)\(tab)return object(forKey: key.rawValue) 117 | \(tab)} 118 | \(tab)public func set(_ value: Any?, forKey key: UDGAnyKey) { 119 | \(tab)\(tab)set(value, forKey: key.rawValue) 120 | \(tab)\(tab)synchronize() 121 | \(tab)} 122 | } 123 | 124 | """ 125 | XCTAssertEqual(got, expected) 126 | } 127 | XCTContext.runActivity(named: "When swift type is Array. Array return type name is [Any]") { (_) in 128 | let configurations: [Configuration] = [ 129 | Configuration(name: "enumKey", type: .array, key: nil), 130 | ] 131 | let got = userDefaultsExtensions(configurations: configurations) 132 | let expected = """ 133 | 134 | // MARK: - UserDefaults Array Extension 135 | extension UserDefaults { 136 | \(tab)public func array(forKey key: UDGArrayKey) -> [Any]? { 137 | \(tab)\(tab)return array(forKey: key.rawValue) 138 | \(tab)} 139 | \(tab)public func set(_ value: [Any]?, forKey key: UDGArrayKey) { 140 | \(tab)\(tab)set(value, forKey: key.rawValue) 141 | \(tab)\(tab)synchronize() 142 | \(tab)} 143 | } 144 | 145 | """ 146 | XCTAssertEqual(got, expected) 147 | } 148 | } 149 | 150 | func testPerformanceExample() { 151 | // This is an example of a performance test case. 152 | self.measure { 153 | // Put the code you want to measure the time of here. 154 | } 155 | } 156 | 157 | } 158 | -------------------------------------------------------------------------------- /Tests/UserDefaultsGeneratorCoreTests/StdlibExtensionTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StdlibExtensionTests.swift 3 | // UserDefaultsGeneratorCoreTests 4 | // 5 | // Created by Yudai Hirose on 2019/09/21. 6 | // 7 | 8 | import XCTest 9 | @testable import UserDefaultsGeneratorCore 10 | 11 | class StdlibExtensionTests: XCTestCase { 12 | 13 | func testCollectionGrouped() { 14 | let configurations = [SwiftType.any, .bool, .bool].map { Configuration(name: $0.rawValue, type: $0, key: nil) } 15 | let result = configurations.grouped { $0.type } 16 | 17 | XCTAssertEqual(result[.any]?.count, 1) 18 | XCTAssertEqual(result[.bool]?.count, 2) 19 | } 20 | 21 | func testDictionaryOrdered() { 22 | let result = ["a": 1, "c": 2, "b": 3].ordered() 23 | XCTAssertEqual(result[0].key, "a") 24 | XCTAssertEqual(result[1].key, "b") 25 | XCTAssertEqual(result[2].key, "c") 26 | } 27 | 28 | func testPerformanceExample() { 29 | // This is an example of a performance test case. 30 | self.measure { 31 | // Put the code you want to measure the time of here. 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /Tests/UserDefaultsGeneratorCoreTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | #if !canImport(ObjectiveC) 4 | public func allTests() -> [XCTestCaseEntry] { 5 | return [ 6 | testCase(UserDefaultsGeneratorTests.allTests), 7 | ] 8 | } 9 | #endif 10 | -------------------------------------------------------------------------------- /UserDefaultsGenerator.generated.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum UDGAnyKey: String { 4 | case ABC 5 | case DEF 6 | } 7 | public enum UDGArrayKey: String { 8 | case XYZ 9 | } 10 | public enum UDGBoolKey: String { 11 | case UserSelectedDarkMode = "DarkMode" 12 | } 13 | public enum UDGIntKey: String { 14 | case numberOfIndent 15 | } 16 | public enum UDGStringArrayKey: String { 17 | case StringArray 18 | } 19 | 20 | 21 | // MARK: - UserDefaults Any Extension 22 | extension UserDefaults { 23 | public func object(forKey key: UDGAnyKey) -> Any? { 24 | return object(forKey: key.rawValue) 25 | } 26 | public func set(_ value: Any?, forKey key: UDGAnyKey) { 27 | set(value, forKey: key.rawValue) 28 | synchronize() 29 | } 30 | } 31 | // MARK: - UserDefaults Array Extension 32 | extension UserDefaults { 33 | public func array(forKey key: UDGArrayKey) -> [Any]? { 34 | return array(forKey: key.rawValue) 35 | } 36 | public func set(_ value: [Any]?, forKey key: UDGArrayKey) { 37 | set(value, forKey: key.rawValue) 38 | synchronize() 39 | } 40 | } 41 | // MARK: - UserDefaults Bool Extension 42 | extension UserDefaults { 43 | public func bool(forKey key: UDGBoolKey) -> Bool { 44 | return bool(forKey: key.rawValue) 45 | } 46 | public func set(_ value: Bool, forKey key: UDGBoolKey) { 47 | set(value, forKey: key.rawValue) 48 | synchronize() 49 | } 50 | } 51 | // MARK: - UserDefaults Int Extension 52 | extension UserDefaults { 53 | public func integer(forKey key: UDGIntKey) -> Int { 54 | return integer(forKey: key.rawValue) 55 | } 56 | public func set(_ value: Int, forKey key: UDGIntKey) { 57 | set(value, forKey: key.rawValue) 58 | synchronize() 59 | } 60 | } 61 | // MARK: - UserDefaults StringArray Extension 62 | extension UserDefaults { 63 | public func stringArray(forKey key: UDGStringArrayKey) -> [String]? { 64 | return stringArray(forKey: key.rawValue) 65 | } 66 | public func set(_ value: [String]?, forKey key: UDGStringArrayKey) { 67 | set(value, forKey: key.rawValue) 68 | synchronize() 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /UserDefaultsGeneratorDemo/UserDefaultsGeneratorDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3348D20F2331E80700A1933E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3348D20E2331E80700A1933E /* AppDelegate.swift */; }; 11 | 3348D2112331E80700A1933E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3348D2102331E80700A1933E /* ViewController.swift */; }; 12 | 3348D2142331E80700A1933E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3348D2122331E80700A1933E /* Main.storyboard */; }; 13 | 3348D2162331E80800A1933E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3348D2152331E80800A1933E /* Assets.xcassets */; }; 14 | 3348D2192331E80800A1933E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3348D2172331E80800A1933E /* LaunchScreen.storyboard */; }; 15 | 3348D2242331E80800A1933E /* UserDefaultsGeneratorDemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3348D2232331E80800A1933E /* UserDefaultsGeneratorDemoTests.swift */; }; 16 | 3348D22F2331E80800A1933E /* UserDefaultsGeneratorDemoUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3348D22E2331E80800A1933E /* UserDefaultsGeneratorDemoUITests.swift */; }; 17 | 33AC9446233251D400A6E4AA /* UserDefaultsGenerator.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33AC9445233251D400A6E4AA /* UserDefaultsGenerator.generated.swift */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXContainerItemProxy section */ 21 | 3348D2202331E80800A1933E /* PBXContainerItemProxy */ = { 22 | isa = PBXContainerItemProxy; 23 | containerPortal = 3348D2032331E80700A1933E /* Project object */; 24 | proxyType = 1; 25 | remoteGlobalIDString = 3348D20A2331E80700A1933E; 26 | remoteInfo = UserDefaultsGeneratorDemo; 27 | }; 28 | 3348D22B2331E80800A1933E /* PBXContainerItemProxy */ = { 29 | isa = PBXContainerItemProxy; 30 | containerPortal = 3348D2032331E80700A1933E /* Project object */; 31 | proxyType = 1; 32 | remoteGlobalIDString = 3348D20A2331E80700A1933E; 33 | remoteInfo = UserDefaultsGeneratorDemo; 34 | }; 35 | /* End PBXContainerItemProxy section */ 36 | 37 | /* Begin PBXFileReference section */ 38 | 3348D20B2331E80700A1933E /* UserDefaultsGeneratorDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UserDefaultsGeneratorDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | 3348D20E2331E80700A1933E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 40 | 3348D2102331E80700A1933E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 41 | 3348D2132331E80700A1933E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 3348D2152331E80800A1933E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 3348D2182331E80800A1933E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 44 | 3348D21A2331E80800A1933E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | 3348D21F2331E80800A1933E /* UserDefaultsGeneratorDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UserDefaultsGeneratorDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | 3348D2232331E80800A1933E /* UserDefaultsGeneratorDemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsGeneratorDemoTests.swift; sourceTree = ""; }; 47 | 3348D2252331E80800A1933E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 48 | 3348D22A2331E80800A1933E /* UserDefaultsGeneratorDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UserDefaultsGeneratorDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | 3348D22E2331E80800A1933E /* UserDefaultsGeneratorDemoUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsGeneratorDemoUITests.swift; sourceTree = ""; }; 50 | 3348D2302331E80800A1933E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 51 | 33AC9445233251D400A6E4AA /* UserDefaultsGenerator.generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UserDefaultsGenerator.generated.swift; path = ../../UserDefaultsGenerator.generated.swift; sourceTree = ""; }; 52 | /* End PBXFileReference section */ 53 | 54 | /* Begin PBXFrameworksBuildPhase section */ 55 | 3348D2082331E80700A1933E /* Frameworks */ = { 56 | isa = PBXFrameworksBuildPhase; 57 | buildActionMask = 2147483647; 58 | files = ( 59 | ); 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | 3348D21C2331E80800A1933E /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | ); 67 | runOnlyForDeploymentPostprocessing = 0; 68 | }; 69 | 3348D2272331E80800A1933E /* Frameworks */ = { 70 | isa = PBXFrameworksBuildPhase; 71 | buildActionMask = 2147483647; 72 | files = ( 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | /* End PBXFrameworksBuildPhase section */ 77 | 78 | /* Begin PBXGroup section */ 79 | 3348D2022331E80700A1933E = { 80 | isa = PBXGroup; 81 | children = ( 82 | 3348D20D2331E80700A1933E /* UserDefaultsGeneratorDemo */, 83 | 3348D2222331E80800A1933E /* UserDefaultsGeneratorDemoTests */, 84 | 3348D22D2331E80800A1933E /* UserDefaultsGeneratorDemoUITests */, 85 | 3348D20C2331E80700A1933E /* Products */, 86 | ); 87 | sourceTree = ""; 88 | }; 89 | 3348D20C2331E80700A1933E /* Products */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 3348D20B2331E80700A1933E /* UserDefaultsGeneratorDemo.app */, 93 | 3348D21F2331E80800A1933E /* UserDefaultsGeneratorDemoTests.xctest */, 94 | 3348D22A2331E80800A1933E /* UserDefaultsGeneratorDemoUITests.xctest */, 95 | ); 96 | name = Products; 97 | sourceTree = ""; 98 | }; 99 | 3348D20D2331E80700A1933E /* UserDefaultsGeneratorDemo */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 3348D20E2331E80700A1933E /* AppDelegate.swift */, 103 | 3348D2102331E80700A1933E /* ViewController.swift */, 104 | 33AC9445233251D400A6E4AA /* UserDefaultsGenerator.generated.swift */, 105 | 3348D2122331E80700A1933E /* Main.storyboard */, 106 | 3348D2152331E80800A1933E /* Assets.xcassets */, 107 | 3348D2172331E80800A1933E /* LaunchScreen.storyboard */, 108 | 3348D21A2331E80800A1933E /* Info.plist */, 109 | ); 110 | path = UserDefaultsGeneratorDemo; 111 | sourceTree = ""; 112 | }; 113 | 3348D2222331E80800A1933E /* UserDefaultsGeneratorDemoTests */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | 3348D2232331E80800A1933E /* UserDefaultsGeneratorDemoTests.swift */, 117 | 3348D2252331E80800A1933E /* Info.plist */, 118 | ); 119 | path = UserDefaultsGeneratorDemoTests; 120 | sourceTree = ""; 121 | }; 122 | 3348D22D2331E80800A1933E /* UserDefaultsGeneratorDemoUITests */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | 3348D22E2331E80800A1933E /* UserDefaultsGeneratorDemoUITests.swift */, 126 | 3348D2302331E80800A1933E /* Info.plist */, 127 | ); 128 | path = UserDefaultsGeneratorDemoUITests; 129 | sourceTree = ""; 130 | }; 131 | /* End PBXGroup section */ 132 | 133 | /* Begin PBXNativeTarget section */ 134 | 3348D20A2331E80700A1933E /* UserDefaultsGeneratorDemo */ = { 135 | isa = PBXNativeTarget; 136 | buildConfigurationList = 3348D2332331E80800A1933E /* Build configuration list for PBXNativeTarget "UserDefaultsGeneratorDemo" */; 137 | buildPhases = ( 138 | 3348D2072331E80700A1933E /* Sources */, 139 | 3348D2082331E80700A1933E /* Frameworks */, 140 | 3348D2092331E80700A1933E /* Resources */, 141 | ); 142 | buildRules = ( 143 | ); 144 | dependencies = ( 145 | ); 146 | name = UserDefaultsGeneratorDemo; 147 | productName = UserDefaultsGeneratorDemo; 148 | productReference = 3348D20B2331E80700A1933E /* UserDefaultsGeneratorDemo.app */; 149 | productType = "com.apple.product-type.application"; 150 | }; 151 | 3348D21E2331E80800A1933E /* UserDefaultsGeneratorDemoTests */ = { 152 | isa = PBXNativeTarget; 153 | buildConfigurationList = 3348D2362331E80800A1933E /* Build configuration list for PBXNativeTarget "UserDefaultsGeneratorDemoTests" */; 154 | buildPhases = ( 155 | 3348D21B2331E80800A1933E /* Sources */, 156 | 3348D21C2331E80800A1933E /* Frameworks */, 157 | 3348D21D2331E80800A1933E /* Resources */, 158 | ); 159 | buildRules = ( 160 | ); 161 | dependencies = ( 162 | 3348D2212331E80800A1933E /* PBXTargetDependency */, 163 | ); 164 | name = UserDefaultsGeneratorDemoTests; 165 | productName = UserDefaultsGeneratorDemoTests; 166 | productReference = 3348D21F2331E80800A1933E /* UserDefaultsGeneratorDemoTests.xctest */; 167 | productType = "com.apple.product-type.bundle.unit-test"; 168 | }; 169 | 3348D2292331E80800A1933E /* UserDefaultsGeneratorDemoUITests */ = { 170 | isa = PBXNativeTarget; 171 | buildConfigurationList = 3348D2392331E80800A1933E /* Build configuration list for PBXNativeTarget "UserDefaultsGeneratorDemoUITests" */; 172 | buildPhases = ( 173 | 3348D2262331E80800A1933E /* Sources */, 174 | 3348D2272331E80800A1933E /* Frameworks */, 175 | 3348D2282331E80800A1933E /* Resources */, 176 | ); 177 | buildRules = ( 178 | ); 179 | dependencies = ( 180 | 3348D22C2331E80800A1933E /* PBXTargetDependency */, 181 | ); 182 | name = UserDefaultsGeneratorDemoUITests; 183 | productName = UserDefaultsGeneratorDemoUITests; 184 | productReference = 3348D22A2331E80800A1933E /* UserDefaultsGeneratorDemoUITests.xctest */; 185 | productType = "com.apple.product-type.bundle.ui-testing"; 186 | }; 187 | /* End PBXNativeTarget section */ 188 | 189 | /* Begin PBXProject section */ 190 | 3348D2032331E80700A1933E /* Project object */ = { 191 | isa = PBXProject; 192 | attributes = { 193 | LastSwiftUpdateCheck = 1020; 194 | LastUpgradeCheck = 1020; 195 | ORGANIZATIONNAME = "Yudai Hirose"; 196 | TargetAttributes = { 197 | 3348D20A2331E80700A1933E = { 198 | CreatedOnToolsVersion = 10.2.1; 199 | }; 200 | 3348D21E2331E80800A1933E = { 201 | CreatedOnToolsVersion = 10.2.1; 202 | TestTargetID = 3348D20A2331E80700A1933E; 203 | }; 204 | 3348D2292331E80800A1933E = { 205 | CreatedOnToolsVersion = 10.2.1; 206 | TestTargetID = 3348D20A2331E80700A1933E; 207 | }; 208 | }; 209 | }; 210 | buildConfigurationList = 3348D2062331E80700A1933E /* Build configuration list for PBXProject "UserDefaultsGeneratorDemo" */; 211 | compatibilityVersion = "Xcode 9.3"; 212 | developmentRegion = en; 213 | hasScannedForEncodings = 0; 214 | knownRegions = ( 215 | en, 216 | Base, 217 | ); 218 | mainGroup = 3348D2022331E80700A1933E; 219 | productRefGroup = 3348D20C2331E80700A1933E /* Products */; 220 | projectDirPath = ""; 221 | projectRoot = ""; 222 | targets = ( 223 | 3348D20A2331E80700A1933E /* UserDefaultsGeneratorDemo */, 224 | 3348D21E2331E80800A1933E /* UserDefaultsGeneratorDemoTests */, 225 | 3348D2292331E80800A1933E /* UserDefaultsGeneratorDemoUITests */, 226 | ); 227 | }; 228 | /* End PBXProject section */ 229 | 230 | /* Begin PBXResourcesBuildPhase section */ 231 | 3348D2092331E80700A1933E /* Resources */ = { 232 | isa = PBXResourcesBuildPhase; 233 | buildActionMask = 2147483647; 234 | files = ( 235 | 3348D2192331E80800A1933E /* LaunchScreen.storyboard in Resources */, 236 | 3348D2162331E80800A1933E /* Assets.xcassets in Resources */, 237 | 3348D2142331E80700A1933E /* Main.storyboard in Resources */, 238 | ); 239 | runOnlyForDeploymentPostprocessing = 0; 240 | }; 241 | 3348D21D2331E80800A1933E /* Resources */ = { 242 | isa = PBXResourcesBuildPhase; 243 | buildActionMask = 2147483647; 244 | files = ( 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | }; 248 | 3348D2282331E80800A1933E /* Resources */ = { 249 | isa = PBXResourcesBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | ); 253 | runOnlyForDeploymentPostprocessing = 0; 254 | }; 255 | /* End PBXResourcesBuildPhase section */ 256 | 257 | /* Begin PBXSourcesBuildPhase section */ 258 | 3348D2072331E80700A1933E /* Sources */ = { 259 | isa = PBXSourcesBuildPhase; 260 | buildActionMask = 2147483647; 261 | files = ( 262 | 3348D2112331E80700A1933E /* ViewController.swift in Sources */, 263 | 3348D20F2331E80700A1933E /* AppDelegate.swift in Sources */, 264 | 33AC9446233251D400A6E4AA /* UserDefaultsGenerator.generated.swift in Sources */, 265 | ); 266 | runOnlyForDeploymentPostprocessing = 0; 267 | }; 268 | 3348D21B2331E80800A1933E /* Sources */ = { 269 | isa = PBXSourcesBuildPhase; 270 | buildActionMask = 2147483647; 271 | files = ( 272 | 3348D2242331E80800A1933E /* UserDefaultsGeneratorDemoTests.swift in Sources */, 273 | ); 274 | runOnlyForDeploymentPostprocessing = 0; 275 | }; 276 | 3348D2262331E80800A1933E /* Sources */ = { 277 | isa = PBXSourcesBuildPhase; 278 | buildActionMask = 2147483647; 279 | files = ( 280 | 3348D22F2331E80800A1933E /* UserDefaultsGeneratorDemoUITests.swift in Sources */, 281 | ); 282 | runOnlyForDeploymentPostprocessing = 0; 283 | }; 284 | /* End PBXSourcesBuildPhase section */ 285 | 286 | /* Begin PBXTargetDependency section */ 287 | 3348D2212331E80800A1933E /* PBXTargetDependency */ = { 288 | isa = PBXTargetDependency; 289 | target = 3348D20A2331E80700A1933E /* UserDefaultsGeneratorDemo */; 290 | targetProxy = 3348D2202331E80800A1933E /* PBXContainerItemProxy */; 291 | }; 292 | 3348D22C2331E80800A1933E /* PBXTargetDependency */ = { 293 | isa = PBXTargetDependency; 294 | target = 3348D20A2331E80700A1933E /* UserDefaultsGeneratorDemo */; 295 | targetProxy = 3348D22B2331E80800A1933E /* PBXContainerItemProxy */; 296 | }; 297 | /* End PBXTargetDependency section */ 298 | 299 | /* Begin PBXVariantGroup section */ 300 | 3348D2122331E80700A1933E /* Main.storyboard */ = { 301 | isa = PBXVariantGroup; 302 | children = ( 303 | 3348D2132331E80700A1933E /* Base */, 304 | ); 305 | name = Main.storyboard; 306 | sourceTree = ""; 307 | }; 308 | 3348D2172331E80800A1933E /* LaunchScreen.storyboard */ = { 309 | isa = PBXVariantGroup; 310 | children = ( 311 | 3348D2182331E80800A1933E /* Base */, 312 | ); 313 | name = LaunchScreen.storyboard; 314 | sourceTree = ""; 315 | }; 316 | /* End PBXVariantGroup section */ 317 | 318 | /* Begin XCBuildConfiguration section */ 319 | 3348D2312331E80800A1933E /* Debug */ = { 320 | isa = XCBuildConfiguration; 321 | buildSettings = { 322 | ALWAYS_SEARCH_USER_PATHS = NO; 323 | CLANG_ANALYZER_NONNULL = YES; 324 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 325 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 326 | CLANG_CXX_LIBRARY = "libc++"; 327 | CLANG_ENABLE_MODULES = YES; 328 | CLANG_ENABLE_OBJC_ARC = YES; 329 | CLANG_ENABLE_OBJC_WEAK = YES; 330 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 331 | CLANG_WARN_BOOL_CONVERSION = YES; 332 | CLANG_WARN_COMMA = YES; 333 | CLANG_WARN_CONSTANT_CONVERSION = YES; 334 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 335 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 336 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 337 | CLANG_WARN_EMPTY_BODY = YES; 338 | CLANG_WARN_ENUM_CONVERSION = YES; 339 | CLANG_WARN_INFINITE_RECURSION = YES; 340 | CLANG_WARN_INT_CONVERSION = YES; 341 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 342 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 343 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 344 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 345 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 346 | CLANG_WARN_STRICT_PROTOTYPES = YES; 347 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 348 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 349 | CLANG_WARN_UNREACHABLE_CODE = YES; 350 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 351 | CODE_SIGN_IDENTITY = "iPhone Developer"; 352 | COPY_PHASE_STRIP = NO; 353 | DEBUG_INFORMATION_FORMAT = dwarf; 354 | ENABLE_STRICT_OBJC_MSGSEND = YES; 355 | ENABLE_TESTABILITY = YES; 356 | GCC_C_LANGUAGE_STANDARD = gnu11; 357 | GCC_DYNAMIC_NO_PIC = NO; 358 | GCC_NO_COMMON_BLOCKS = YES; 359 | GCC_OPTIMIZATION_LEVEL = 0; 360 | GCC_PREPROCESSOR_DEFINITIONS = ( 361 | "DEBUG=1", 362 | "$(inherited)", 363 | ); 364 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 365 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 366 | GCC_WARN_UNDECLARED_SELECTOR = YES; 367 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 368 | GCC_WARN_UNUSED_FUNCTION = YES; 369 | GCC_WARN_UNUSED_VARIABLE = YES; 370 | IPHONEOS_DEPLOYMENT_TARGET = 12.2; 371 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 372 | MTL_FAST_MATH = YES; 373 | ONLY_ACTIVE_ARCH = YES; 374 | SDKROOT = iphoneos; 375 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 376 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 377 | }; 378 | name = Debug; 379 | }; 380 | 3348D2322331E80800A1933E /* Release */ = { 381 | isa = XCBuildConfiguration; 382 | buildSettings = { 383 | ALWAYS_SEARCH_USER_PATHS = NO; 384 | CLANG_ANALYZER_NONNULL = YES; 385 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 386 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 387 | CLANG_CXX_LIBRARY = "libc++"; 388 | CLANG_ENABLE_MODULES = YES; 389 | CLANG_ENABLE_OBJC_ARC = YES; 390 | CLANG_ENABLE_OBJC_WEAK = YES; 391 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 392 | CLANG_WARN_BOOL_CONVERSION = YES; 393 | CLANG_WARN_COMMA = YES; 394 | CLANG_WARN_CONSTANT_CONVERSION = YES; 395 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 396 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 397 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 398 | CLANG_WARN_EMPTY_BODY = YES; 399 | CLANG_WARN_ENUM_CONVERSION = YES; 400 | CLANG_WARN_INFINITE_RECURSION = YES; 401 | CLANG_WARN_INT_CONVERSION = YES; 402 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 403 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 404 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 405 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 406 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 407 | CLANG_WARN_STRICT_PROTOTYPES = YES; 408 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 409 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 410 | CLANG_WARN_UNREACHABLE_CODE = YES; 411 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 412 | CODE_SIGN_IDENTITY = "iPhone Developer"; 413 | COPY_PHASE_STRIP = NO; 414 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 415 | ENABLE_NS_ASSERTIONS = NO; 416 | ENABLE_STRICT_OBJC_MSGSEND = YES; 417 | GCC_C_LANGUAGE_STANDARD = gnu11; 418 | GCC_NO_COMMON_BLOCKS = YES; 419 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 420 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 421 | GCC_WARN_UNDECLARED_SELECTOR = YES; 422 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 423 | GCC_WARN_UNUSED_FUNCTION = YES; 424 | GCC_WARN_UNUSED_VARIABLE = YES; 425 | IPHONEOS_DEPLOYMENT_TARGET = 12.2; 426 | MTL_ENABLE_DEBUG_INFO = NO; 427 | MTL_FAST_MATH = YES; 428 | SDKROOT = iphoneos; 429 | SWIFT_COMPILATION_MODE = wholemodule; 430 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 431 | VALIDATE_PRODUCT = YES; 432 | }; 433 | name = Release; 434 | }; 435 | 3348D2342331E80800A1933E /* Debug */ = { 436 | isa = XCBuildConfiguration; 437 | buildSettings = { 438 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 439 | CODE_SIGN_STYLE = Automatic; 440 | INFOPLIST_FILE = UserDefaultsGeneratorDemo/Info.plist; 441 | LD_RUNPATH_SEARCH_PATHS = ( 442 | "$(inherited)", 443 | "@executable_path/Frameworks", 444 | ); 445 | PRODUCT_BUNDLE_IDENTIFIER = com.bannzai.UserDefaultsGeneratorDemo; 446 | PRODUCT_NAME = "$(TARGET_NAME)"; 447 | SWIFT_VERSION = 5.0; 448 | TARGETED_DEVICE_FAMILY = "1,2"; 449 | }; 450 | name = Debug; 451 | }; 452 | 3348D2352331E80800A1933E /* Release */ = { 453 | isa = XCBuildConfiguration; 454 | buildSettings = { 455 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 456 | CODE_SIGN_STYLE = Automatic; 457 | INFOPLIST_FILE = UserDefaultsGeneratorDemo/Info.plist; 458 | LD_RUNPATH_SEARCH_PATHS = ( 459 | "$(inherited)", 460 | "@executable_path/Frameworks", 461 | ); 462 | PRODUCT_BUNDLE_IDENTIFIER = com.bannzai.UserDefaultsGeneratorDemo; 463 | PRODUCT_NAME = "$(TARGET_NAME)"; 464 | SWIFT_VERSION = 5.0; 465 | TARGETED_DEVICE_FAMILY = "1,2"; 466 | }; 467 | name = Release; 468 | }; 469 | 3348D2372331E80800A1933E /* Debug */ = { 470 | isa = XCBuildConfiguration; 471 | buildSettings = { 472 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 473 | BUNDLE_LOADER = "$(TEST_HOST)"; 474 | CODE_SIGN_STYLE = Automatic; 475 | INFOPLIST_FILE = UserDefaultsGeneratorDemoTests/Info.plist; 476 | LD_RUNPATH_SEARCH_PATHS = ( 477 | "$(inherited)", 478 | "@executable_path/Frameworks", 479 | "@loader_path/Frameworks", 480 | ); 481 | PRODUCT_BUNDLE_IDENTIFIER = com.bannzai.UserDefaultsGeneratorDemoTests; 482 | PRODUCT_NAME = "$(TARGET_NAME)"; 483 | SWIFT_VERSION = 5.0; 484 | TARGETED_DEVICE_FAMILY = "1,2"; 485 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UserDefaultsGeneratorDemo.app/UserDefaultsGeneratorDemo"; 486 | }; 487 | name = Debug; 488 | }; 489 | 3348D2382331E80800A1933E /* Release */ = { 490 | isa = XCBuildConfiguration; 491 | buildSettings = { 492 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 493 | BUNDLE_LOADER = "$(TEST_HOST)"; 494 | CODE_SIGN_STYLE = Automatic; 495 | INFOPLIST_FILE = UserDefaultsGeneratorDemoTests/Info.plist; 496 | LD_RUNPATH_SEARCH_PATHS = ( 497 | "$(inherited)", 498 | "@executable_path/Frameworks", 499 | "@loader_path/Frameworks", 500 | ); 501 | PRODUCT_BUNDLE_IDENTIFIER = com.bannzai.UserDefaultsGeneratorDemoTests; 502 | PRODUCT_NAME = "$(TARGET_NAME)"; 503 | SWIFT_VERSION = 5.0; 504 | TARGETED_DEVICE_FAMILY = "1,2"; 505 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UserDefaultsGeneratorDemo.app/UserDefaultsGeneratorDemo"; 506 | }; 507 | name = Release; 508 | }; 509 | 3348D23A2331E80800A1933E /* Debug */ = { 510 | isa = XCBuildConfiguration; 511 | buildSettings = { 512 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 513 | CODE_SIGN_STYLE = Automatic; 514 | INFOPLIST_FILE = UserDefaultsGeneratorDemoUITests/Info.plist; 515 | LD_RUNPATH_SEARCH_PATHS = ( 516 | "$(inherited)", 517 | "@executable_path/Frameworks", 518 | "@loader_path/Frameworks", 519 | ); 520 | PRODUCT_BUNDLE_IDENTIFIER = com.bannzai.UserDefaultsGeneratorDemoUITests; 521 | PRODUCT_NAME = "$(TARGET_NAME)"; 522 | SWIFT_VERSION = 5.0; 523 | TARGETED_DEVICE_FAMILY = "1,2"; 524 | TEST_TARGET_NAME = UserDefaultsGeneratorDemo; 525 | }; 526 | name = Debug; 527 | }; 528 | 3348D23B2331E80800A1933E /* Release */ = { 529 | isa = XCBuildConfiguration; 530 | buildSettings = { 531 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 532 | CODE_SIGN_STYLE = Automatic; 533 | INFOPLIST_FILE = UserDefaultsGeneratorDemoUITests/Info.plist; 534 | LD_RUNPATH_SEARCH_PATHS = ( 535 | "$(inherited)", 536 | "@executable_path/Frameworks", 537 | "@loader_path/Frameworks", 538 | ); 539 | PRODUCT_BUNDLE_IDENTIFIER = com.bannzai.UserDefaultsGeneratorDemoUITests; 540 | PRODUCT_NAME = "$(TARGET_NAME)"; 541 | SWIFT_VERSION = 5.0; 542 | TARGETED_DEVICE_FAMILY = "1,2"; 543 | TEST_TARGET_NAME = UserDefaultsGeneratorDemo; 544 | }; 545 | name = Release; 546 | }; 547 | /* End XCBuildConfiguration section */ 548 | 549 | /* Begin XCConfigurationList section */ 550 | 3348D2062331E80700A1933E /* Build configuration list for PBXProject "UserDefaultsGeneratorDemo" */ = { 551 | isa = XCConfigurationList; 552 | buildConfigurations = ( 553 | 3348D2312331E80800A1933E /* Debug */, 554 | 3348D2322331E80800A1933E /* Release */, 555 | ); 556 | defaultConfigurationIsVisible = 0; 557 | defaultConfigurationName = Release; 558 | }; 559 | 3348D2332331E80800A1933E /* Build configuration list for PBXNativeTarget "UserDefaultsGeneratorDemo" */ = { 560 | isa = XCConfigurationList; 561 | buildConfigurations = ( 562 | 3348D2342331E80800A1933E /* Debug */, 563 | 3348D2352331E80800A1933E /* Release */, 564 | ); 565 | defaultConfigurationIsVisible = 0; 566 | defaultConfigurationName = Release; 567 | }; 568 | 3348D2362331E80800A1933E /* Build configuration list for PBXNativeTarget "UserDefaultsGeneratorDemoTests" */ = { 569 | isa = XCConfigurationList; 570 | buildConfigurations = ( 571 | 3348D2372331E80800A1933E /* Debug */, 572 | 3348D2382331E80800A1933E /* Release */, 573 | ); 574 | defaultConfigurationIsVisible = 0; 575 | defaultConfigurationName = Release; 576 | }; 577 | 3348D2392331E80800A1933E /* Build configuration list for PBXNativeTarget "UserDefaultsGeneratorDemoUITests" */ = { 578 | isa = XCConfigurationList; 579 | buildConfigurations = ( 580 | 3348D23A2331E80800A1933E /* Debug */, 581 | 3348D23B2331E80800A1933E /* Release */, 582 | ); 583 | defaultConfigurationIsVisible = 0; 584 | defaultConfigurationName = Release; 585 | }; 586 | /* End XCConfigurationList section */ 587 | }; 588 | rootObject = 3348D2032331E80700A1933E /* Project object */; 589 | } 590 | -------------------------------------------------------------------------------- /UserDefaultsGeneratorDemo/UserDefaultsGeneratorDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /UserDefaultsGeneratorDemo/UserDefaultsGeneratorDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /UserDefaultsGeneratorDemo/UserDefaultsGeneratorDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // UserDefaultsGeneratorDemo 4 | // 5 | // Created by Yudai Hirose on 2019/09/18. 6 | // Copyright © 2019 Yudai Hirose. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /UserDefaultsGeneratorDemo/UserDefaultsGeneratorDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /UserDefaultsGeneratorDemo/UserDefaultsGeneratorDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /UserDefaultsGeneratorDemo/UserDefaultsGeneratorDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /UserDefaultsGeneratorDemo/UserDefaultsGeneratorDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /UserDefaultsGeneratorDemo/UserDefaultsGeneratorDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /UserDefaultsGeneratorDemo/UserDefaultsGeneratorDemo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // UserDefaultsGeneratorDemo 4 | // 5 | // Created by Yudai Hirose on 2019/09/18. 6 | // Copyright © 2019 Yudai Hirose. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view. 16 | } 17 | 18 | 19 | } 20 | 21 | -------------------------------------------------------------------------------- /UserDefaultsGeneratorDemo/UserDefaultsGeneratorDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /UserDefaultsGeneratorDemo/UserDefaultsGeneratorDemoTests/UserDefaultsGeneratorDemoTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserDefaultsGeneratorDemoTests.swift 3 | // UserDefaultsGeneratorDemoTests 4 | // 5 | // Created by Yudai Hirose on 2019/09/18. 6 | // Copyright © 2019 Yudai Hirose. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import UserDefaultsGeneratorDemo 11 | 12 | class UserDefaultsGeneratorDemoTests: XCTestCase { 13 | 14 | override func setUp() { 15 | // Put setup code here. This method is called before the invocation of each test method in the class. 16 | } 17 | 18 | override func tearDown() { 19 | // Put teardown code here. This method is called after the invocation of each test method in the class. 20 | } 21 | 22 | func testExample() { 23 | // This is an example of a functional test case. 24 | // Use XCTAssert and related functions to verify your tests produce the correct results. 25 | } 26 | 27 | func testPerformanceExample() { 28 | // This is an example of a performance test case. 29 | self.measure { 30 | // Put the code you want to measure the time of here. 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /UserDefaultsGeneratorDemo/UserDefaultsGeneratorDemoUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /UserDefaultsGeneratorDemo/UserDefaultsGeneratorDemoUITests/UserDefaultsGeneratorDemoUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserDefaultsGeneratorDemoUITests.swift 3 | // UserDefaultsGeneratorDemoUITests 4 | // 5 | // Created by Yudai Hirose on 2019/09/18. 6 | // Copyright © 2019 Yudai Hirose. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class UserDefaultsGeneratorDemoUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | // Put setup code here. This method is called before the invocation of each test method in the class. 15 | 16 | // In UI tests it is usually best to stop immediately when a failure occurs. 17 | continueAfterFailure = false 18 | 19 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 20 | XCUIApplication().launch() 21 | 22 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 23 | } 24 | 25 | override func tearDown() { 26 | // Put teardown code here. This method is called after the invocation of each test method in the class. 27 | } 28 | 29 | func testExample() { 30 | // Use recording to get started writing UI tests. 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /template.stencil: -------------------------------------------------------------------------------- 1 | {% for groupuedConfiguration in groupedConfigurations %} 2 | groupuedConfiguration.aliasName 3 | {% endfor %} 4 | -------------------------------------------------------------------------------- /udg.yml: -------------------------------------------------------------------------------- 1 | - name: numberOfIndent 2 | type: Int 3 | 4 | - name: UserSelectedDarkMode 5 | type: Bool 6 | key: DarkMode 7 | 8 | - name: XYZ 9 | type: Array 10 | 11 | - name: ABC 12 | type: Any 13 | - name: DEF 14 | type: Any 15 | 16 | - name: StringArray 17 | type: StringArray 18 | --------------------------------------------------------------------------------