├── AppModel ├── AppModel.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── antongoncharov.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── AppModel │ ├── Sources │ ├── Actions.swift │ ├── Extensions.swift │ ├── FormState.swift │ └── Reducer.swift │ └── SupportingFiles │ ├── AppModel.h │ └── Info.plist ├── SwiftUIApp ├── SwiftUIApp.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── antongoncharov.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── SwiftUIApp │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── ContentView.swift │ ├── Info.plist │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ └── SceneDelegate.swift ├── UDF ├── UDF.xcodeproj │ ├── project.pbxproj │ └── xcuserdata │ │ └── antongoncharov.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── UDF │ ├── Sources │ ├── Action.swift │ ├── Store.swift │ └── SwiftUIStore.swift │ └── SupportingFiles │ ├── Info.plist │ └── UDF.h ├── UDFExample.xcworkspace ├── contents.xcworkspacedata ├── xcshareddata │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── antongoncharov.xcuserdatad │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist └── UIKitApp ├── UIKitApp.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── antongoncharov.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist └── UIKitApp ├── AppDelegate.swift ├── Assets.xcassets ├── AppIcon.appiconset │ └── Contents.json └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── Info.plist └── ViewController.swift /AppModel/AppModel.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7D7EDCA3258620DB00E17C13 /* AppModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D7EDCA1258620DB00E17C13 /* AppModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 7D7EDCAD2586213600E17C13 /* FormState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D7EDCAA2586213600E17C13 /* FormState.swift */; }; 12 | 7D7EDCAE2586213600E17C13 /* Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D7EDCAB2586213600E17C13 /* Actions.swift */; }; 13 | 7D7EDCAF2586213600E17C13 /* Reducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D7EDCAC2586213600E17C13 /* Reducer.swift */; }; 14 | 7D7EDCB32586215E00E17C13 /* UDF.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D7EDCB22586215E00E17C13 /* UDF.framework */; }; 15 | 7D7EDCB42586215E00E17C13 /* UDF.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7D7EDCB22586215E00E17C13 /* UDF.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 16 | 7D7EDCF9258670D300E17C13 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D7EDCF8258670D300E17C13 /* Extensions.swift */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXCopyFilesBuildPhase section */ 20 | 7D7EDCB52586215E00E17C13 /* Embed Frameworks */ = { 21 | isa = PBXCopyFilesBuildPhase; 22 | buildActionMask = 2147483647; 23 | dstPath = ""; 24 | dstSubfolderSpec = 10; 25 | files = ( 26 | 7D7EDCB42586215E00E17C13 /* UDF.framework in Embed Frameworks */, 27 | ); 28 | name = "Embed Frameworks"; 29 | runOnlyForDeploymentPostprocessing = 0; 30 | }; 31 | /* End PBXCopyFilesBuildPhase section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 7D7EDC9E258620DB00E17C13 /* AppModel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AppModel.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | 7D7EDCA1258620DB00E17C13 /* AppModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppModel.h; sourceTree = ""; }; 36 | 7D7EDCA2258620DB00E17C13 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 37 | 7D7EDCAA2586213600E17C13 /* FormState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormState.swift; sourceTree = ""; }; 38 | 7D7EDCAB2586213600E17C13 /* Actions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Actions.swift; sourceTree = ""; }; 39 | 7D7EDCAC2586213600E17C13 /* Reducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reducer.swift; sourceTree = ""; }; 40 | 7D7EDCB22586215E00E17C13 /* UDF.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = UDF.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 7D7EDCF8258670D300E17C13 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; }; 42 | /* End PBXFileReference section */ 43 | 44 | /* Begin PBXFrameworksBuildPhase section */ 45 | 7D7EDC9B258620DB00E17C13 /* Frameworks */ = { 46 | isa = PBXFrameworksBuildPhase; 47 | buildActionMask = 2147483647; 48 | files = ( 49 | 7D7EDCB32586215E00E17C13 /* UDF.framework in Frameworks */, 50 | ); 51 | runOnlyForDeploymentPostprocessing = 0; 52 | }; 53 | /* End PBXFrameworksBuildPhase section */ 54 | 55 | /* Begin PBXGroup section */ 56 | 7D7EDC94258620DB00E17C13 = { 57 | isa = PBXGroup; 58 | children = ( 59 | 7D7EDCA0258620DB00E17C13 /* AppModel */, 60 | 7D7EDC9F258620DB00E17C13 /* Products */, 61 | 7D7EDCB12586215E00E17C13 /* Frameworks */, 62 | ); 63 | sourceTree = ""; 64 | }; 65 | 7D7EDC9F258620DB00E17C13 /* Products */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | 7D7EDC9E258620DB00E17C13 /* AppModel.framework */, 69 | ); 70 | name = Products; 71 | sourceTree = ""; 72 | }; 73 | 7D7EDCA0258620DB00E17C13 /* AppModel */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 7D7EDCA92586212900E17C13 /* Sources */, 77 | 7D7EDCB02586213B00E17C13 /* SupportingFiles */, 78 | ); 79 | path = AppModel; 80 | sourceTree = ""; 81 | }; 82 | 7D7EDCA92586212900E17C13 /* Sources */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 7D7EDCAB2586213600E17C13 /* Actions.swift */, 86 | 7D7EDCAA2586213600E17C13 /* FormState.swift */, 87 | 7D7EDCAC2586213600E17C13 /* Reducer.swift */, 88 | 7D7EDCF8258670D300E17C13 /* Extensions.swift */, 89 | ); 90 | path = Sources; 91 | sourceTree = ""; 92 | }; 93 | 7D7EDCB02586213B00E17C13 /* SupportingFiles */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | 7D7EDCA1258620DB00E17C13 /* AppModel.h */, 97 | 7D7EDCA2258620DB00E17C13 /* Info.plist */, 98 | ); 99 | path = SupportingFiles; 100 | sourceTree = ""; 101 | }; 102 | 7D7EDCB12586215E00E17C13 /* Frameworks */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 7D7EDCB22586215E00E17C13 /* UDF.framework */, 106 | ); 107 | name = Frameworks; 108 | sourceTree = ""; 109 | }; 110 | /* End PBXGroup section */ 111 | 112 | /* Begin PBXHeadersBuildPhase section */ 113 | 7D7EDC99258620DB00E17C13 /* Headers */ = { 114 | isa = PBXHeadersBuildPhase; 115 | buildActionMask = 2147483647; 116 | files = ( 117 | 7D7EDCA3258620DB00E17C13 /* AppModel.h in Headers */, 118 | ); 119 | runOnlyForDeploymentPostprocessing = 0; 120 | }; 121 | /* End PBXHeadersBuildPhase section */ 122 | 123 | /* Begin PBXNativeTarget section */ 124 | 7D7EDC9D258620DB00E17C13 /* AppModel */ = { 125 | isa = PBXNativeTarget; 126 | buildConfigurationList = 7D7EDCA6258620DB00E17C13 /* Build configuration list for PBXNativeTarget "AppModel" */; 127 | buildPhases = ( 128 | 7D7EDC99258620DB00E17C13 /* Headers */, 129 | 7D7EDC9A258620DB00E17C13 /* Sources */, 130 | 7D7EDC9B258620DB00E17C13 /* Frameworks */, 131 | 7D7EDC9C258620DB00E17C13 /* Resources */, 132 | 7D7EDCB52586215E00E17C13 /* Embed Frameworks */, 133 | ); 134 | buildRules = ( 135 | ); 136 | dependencies = ( 137 | ); 138 | name = AppModel; 139 | productName = AppModel; 140 | productReference = 7D7EDC9E258620DB00E17C13 /* AppModel.framework */; 141 | productType = "com.apple.product-type.framework"; 142 | }; 143 | /* End PBXNativeTarget section */ 144 | 145 | /* Begin PBXProject section */ 146 | 7D7EDC95258620DB00E17C13 /* Project object */ = { 147 | isa = PBXProject; 148 | attributes = { 149 | LastUpgradeCheck = 1150; 150 | ORGANIZATIONNAME = "Anton Goncharov"; 151 | TargetAttributes = { 152 | 7D7EDC9D258620DB00E17C13 = { 153 | CreatedOnToolsVersion = 11.5; 154 | LastSwiftMigration = 1150; 155 | }; 156 | }; 157 | }; 158 | buildConfigurationList = 7D7EDC98258620DB00E17C13 /* Build configuration list for PBXProject "AppModel" */; 159 | compatibilityVersion = "Xcode 9.3"; 160 | developmentRegion = en; 161 | hasScannedForEncodings = 0; 162 | knownRegions = ( 163 | en, 164 | Base, 165 | ); 166 | mainGroup = 7D7EDC94258620DB00E17C13; 167 | productRefGroup = 7D7EDC9F258620DB00E17C13 /* Products */; 168 | projectDirPath = ""; 169 | projectRoot = ""; 170 | targets = ( 171 | 7D7EDC9D258620DB00E17C13 /* AppModel */, 172 | ); 173 | }; 174 | /* End PBXProject section */ 175 | 176 | /* Begin PBXResourcesBuildPhase section */ 177 | 7D7EDC9C258620DB00E17C13 /* Resources */ = { 178 | isa = PBXResourcesBuildPhase; 179 | buildActionMask = 2147483647; 180 | files = ( 181 | ); 182 | runOnlyForDeploymentPostprocessing = 0; 183 | }; 184 | /* End PBXResourcesBuildPhase section */ 185 | 186 | /* Begin PBXSourcesBuildPhase section */ 187 | 7D7EDC9A258620DB00E17C13 /* Sources */ = { 188 | isa = PBXSourcesBuildPhase; 189 | buildActionMask = 2147483647; 190 | files = ( 191 | 7D7EDCAD2586213600E17C13 /* FormState.swift in Sources */, 192 | 7D7EDCAE2586213600E17C13 /* Actions.swift in Sources */, 193 | 7D7EDCAF2586213600E17C13 /* Reducer.swift in Sources */, 194 | 7D7EDCF9258670D300E17C13 /* Extensions.swift in Sources */, 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | }; 198 | /* End PBXSourcesBuildPhase section */ 199 | 200 | /* Begin XCBuildConfiguration section */ 201 | 7D7EDCA4258620DB00E17C13 /* Debug */ = { 202 | isa = XCBuildConfiguration; 203 | buildSettings = { 204 | ALWAYS_SEARCH_USER_PATHS = NO; 205 | CLANG_ANALYZER_NONNULL = YES; 206 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 207 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 208 | CLANG_CXX_LIBRARY = "libc++"; 209 | CLANG_ENABLE_MODULES = YES; 210 | CLANG_ENABLE_OBJC_ARC = YES; 211 | CLANG_ENABLE_OBJC_WEAK = YES; 212 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 213 | CLANG_WARN_BOOL_CONVERSION = YES; 214 | CLANG_WARN_COMMA = YES; 215 | CLANG_WARN_CONSTANT_CONVERSION = YES; 216 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 217 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 218 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 219 | CLANG_WARN_EMPTY_BODY = YES; 220 | CLANG_WARN_ENUM_CONVERSION = YES; 221 | CLANG_WARN_INFINITE_RECURSION = YES; 222 | CLANG_WARN_INT_CONVERSION = YES; 223 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 224 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 225 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 226 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 227 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 228 | CLANG_WARN_STRICT_PROTOTYPES = YES; 229 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 230 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 231 | CLANG_WARN_UNREACHABLE_CODE = YES; 232 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 233 | COPY_PHASE_STRIP = NO; 234 | CURRENT_PROJECT_VERSION = 1; 235 | DEBUG_INFORMATION_FORMAT = dwarf; 236 | ENABLE_STRICT_OBJC_MSGSEND = YES; 237 | ENABLE_TESTABILITY = YES; 238 | GCC_C_LANGUAGE_STANDARD = gnu11; 239 | GCC_DYNAMIC_NO_PIC = NO; 240 | GCC_NO_COMMON_BLOCKS = YES; 241 | GCC_OPTIMIZATION_LEVEL = 0; 242 | GCC_PREPROCESSOR_DEFINITIONS = ( 243 | "DEBUG=1", 244 | "$(inherited)", 245 | ); 246 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 247 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 248 | GCC_WARN_UNDECLARED_SELECTOR = YES; 249 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 250 | GCC_WARN_UNUSED_FUNCTION = YES; 251 | GCC_WARN_UNUSED_VARIABLE = YES; 252 | IPHONEOS_DEPLOYMENT_TARGET = 13.5; 253 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 254 | MTL_FAST_MATH = YES; 255 | ONLY_ACTIVE_ARCH = YES; 256 | SDKROOT = iphoneos; 257 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 258 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 259 | VERSIONING_SYSTEM = "apple-generic"; 260 | VERSION_INFO_PREFIX = ""; 261 | }; 262 | name = Debug; 263 | }; 264 | 7D7EDCA5258620DB00E17C13 /* Release */ = { 265 | isa = XCBuildConfiguration; 266 | buildSettings = { 267 | ALWAYS_SEARCH_USER_PATHS = NO; 268 | CLANG_ANALYZER_NONNULL = YES; 269 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 270 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 271 | CLANG_CXX_LIBRARY = "libc++"; 272 | CLANG_ENABLE_MODULES = YES; 273 | CLANG_ENABLE_OBJC_ARC = YES; 274 | CLANG_ENABLE_OBJC_WEAK = YES; 275 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 276 | CLANG_WARN_BOOL_CONVERSION = YES; 277 | CLANG_WARN_COMMA = YES; 278 | CLANG_WARN_CONSTANT_CONVERSION = YES; 279 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 280 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 281 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 282 | CLANG_WARN_EMPTY_BODY = YES; 283 | CLANG_WARN_ENUM_CONVERSION = YES; 284 | CLANG_WARN_INFINITE_RECURSION = YES; 285 | CLANG_WARN_INT_CONVERSION = YES; 286 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 287 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 288 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 289 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 290 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 291 | CLANG_WARN_STRICT_PROTOTYPES = YES; 292 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 293 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 294 | CLANG_WARN_UNREACHABLE_CODE = YES; 295 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 296 | COPY_PHASE_STRIP = NO; 297 | CURRENT_PROJECT_VERSION = 1; 298 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 299 | ENABLE_NS_ASSERTIONS = NO; 300 | ENABLE_STRICT_OBJC_MSGSEND = YES; 301 | GCC_C_LANGUAGE_STANDARD = gnu11; 302 | GCC_NO_COMMON_BLOCKS = YES; 303 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 304 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 305 | GCC_WARN_UNDECLARED_SELECTOR = YES; 306 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 307 | GCC_WARN_UNUSED_FUNCTION = YES; 308 | GCC_WARN_UNUSED_VARIABLE = YES; 309 | IPHONEOS_DEPLOYMENT_TARGET = 13.5; 310 | MTL_ENABLE_DEBUG_INFO = NO; 311 | MTL_FAST_MATH = YES; 312 | SDKROOT = iphoneos; 313 | SWIFT_COMPILATION_MODE = wholemodule; 314 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 315 | VALIDATE_PRODUCT = YES; 316 | VERSIONING_SYSTEM = "apple-generic"; 317 | VERSION_INFO_PREFIX = ""; 318 | }; 319 | name = Release; 320 | }; 321 | 7D7EDCA7258620DB00E17C13 /* Debug */ = { 322 | isa = XCBuildConfiguration; 323 | buildSettings = { 324 | CLANG_ENABLE_MODULES = YES; 325 | CODE_SIGN_STYLE = Automatic; 326 | DEFINES_MODULE = YES; 327 | DYLIB_COMPATIBILITY_VERSION = 1; 328 | DYLIB_CURRENT_VERSION = 1; 329 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 330 | INFOPLIST_FILE = AppModel/SupportingFiles/Info.plist; 331 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 332 | LD_RUNPATH_SEARCH_PATHS = ( 333 | "$(inherited)", 334 | "@executable_path/Frameworks", 335 | "@loader_path/Frameworks", 336 | ); 337 | PRODUCT_BUNDLE_IDENTIFIER = com.MasterWatcher.AppModel; 338 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 339 | SKIP_INSTALL = YES; 340 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 341 | SWIFT_VERSION = 5.0; 342 | TARGETED_DEVICE_FAMILY = "1,2"; 343 | }; 344 | name = Debug; 345 | }; 346 | 7D7EDCA8258620DB00E17C13 /* Release */ = { 347 | isa = XCBuildConfiguration; 348 | buildSettings = { 349 | CLANG_ENABLE_MODULES = YES; 350 | CODE_SIGN_STYLE = Automatic; 351 | DEFINES_MODULE = YES; 352 | DYLIB_COMPATIBILITY_VERSION = 1; 353 | DYLIB_CURRENT_VERSION = 1; 354 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 355 | INFOPLIST_FILE = AppModel/SupportingFiles/Info.plist; 356 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 357 | LD_RUNPATH_SEARCH_PATHS = ( 358 | "$(inherited)", 359 | "@executable_path/Frameworks", 360 | "@loader_path/Frameworks", 361 | ); 362 | PRODUCT_BUNDLE_IDENTIFIER = com.MasterWatcher.AppModel; 363 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 364 | SKIP_INSTALL = YES; 365 | SWIFT_VERSION = 5.0; 366 | TARGETED_DEVICE_FAMILY = "1,2"; 367 | }; 368 | name = Release; 369 | }; 370 | /* End XCBuildConfiguration section */ 371 | 372 | /* Begin XCConfigurationList section */ 373 | 7D7EDC98258620DB00E17C13 /* Build configuration list for PBXProject "AppModel" */ = { 374 | isa = XCConfigurationList; 375 | buildConfigurations = ( 376 | 7D7EDCA4258620DB00E17C13 /* Debug */, 377 | 7D7EDCA5258620DB00E17C13 /* Release */, 378 | ); 379 | defaultConfigurationIsVisible = 0; 380 | defaultConfigurationName = Release; 381 | }; 382 | 7D7EDCA6258620DB00E17C13 /* Build configuration list for PBXNativeTarget "AppModel" */ = { 383 | isa = XCConfigurationList; 384 | buildConfigurations = ( 385 | 7D7EDCA7258620DB00E17C13 /* Debug */, 386 | 7D7EDCA8258620DB00E17C13 /* Release */, 387 | ); 388 | defaultConfigurationIsVisible = 0; 389 | defaultConfigurationName = Release; 390 | }; 391 | /* End XCConfigurationList section */ 392 | }; 393 | rootObject = 7D7EDC95258620DB00E17C13 /* Project object */; 394 | } 395 | -------------------------------------------------------------------------------- /AppModel/AppModel.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AppModel/AppModel.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /AppModel/AppModel.xcodeproj/xcuserdata/antongoncharov.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AppModel.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 2 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /AppModel/AppModel/Sources/Actions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Actions.swift 3 | // AppModel 4 | // 5 | // Created by Anton Goncharov on 06.12.2020. 6 | // 7 | 8 | import Foundation 9 | import UDF 10 | 11 | public enum Actions: Action { 12 | case nameDidChange(String?) 13 | case pincodeDidChange(String?) 14 | case dogNameDidChange(String?) 15 | } 16 | -------------------------------------------------------------------------------- /AppModel/AppModel/Sources/Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extensions.swift 3 | // AppModel 4 | // 5 | // Created by Anton Goncharov on 13.12.2020. 6 | // Copyright © 2020 Anton Goncharov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension String { 12 | var isNumberic: Bool { 13 | guard !isEmpty else { return false } 14 | return CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: self)) 15 | } 16 | } 17 | 18 | public extension Optional where Wrapped == String { 19 | var orEmpty: String { self ?? "" } 20 | } 21 | -------------------------------------------------------------------------------- /AppModel/AppModel/Sources/FormState.swift: -------------------------------------------------------------------------------- 1 | // 2 | // State.swift 3 | // AppModel 4 | // 5 | // Created by Anton Goncharov on 06.12.2020. 6 | // 7 | 8 | import Foundation 9 | 10 | public struct FormState { 11 | public var name: Field 12 | public var pincode: Field 13 | public var dogName: Field 14 | public var isValidForm: Bool 15 | 16 | public init() { 17 | name = .init() 18 | pincode = .init() 19 | dogName = .init() 20 | isValidForm = false 21 | } 22 | } 23 | 24 | public struct Field { 25 | public var value: String? 26 | public var status: FieldStatus = .default 27 | } 28 | 29 | public enum FieldStatus { 30 | case `default` 31 | case valid 32 | case tooShort(minLength: Int) 33 | case tooLong(maxLength: Int) 34 | case numbersOnly 35 | } 36 | public extension FieldStatus { 37 | var isValid: Bool { 38 | if case .valid = self { 39 | return true 40 | } else { 41 | return false 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /AppModel/AppModel/Sources/Reducer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Reducer.swift 3 | // AppModel 4 | // 5 | // Created by Anton Goncharov on 06.12.2020. 6 | // 7 | 8 | import Foundation 9 | import UDF 10 | 11 | public func reduce(state: inout FormState, action: Action) { 12 | if case let Actions.nameDidChange(name) = action { 13 | update(name: &state.name, with: name) 14 | update(isValidForm: &state) 15 | } 16 | 17 | if case let Actions.pincodeDidChange(pincode) = action { 18 | update(pincode: &state.pincode, with: pincode) 19 | update(isValidForm: &state) 20 | } 21 | 22 | if case let Actions.dogNameDidChange(dogName) = action { 23 | update(dogName: &state.dogName, with: dogName) 24 | update(isValidForm: &state) 25 | } 26 | } 27 | 28 | private func update(name: inout Field, with value: String?) { 29 | name.value = value 30 | 31 | let nameLength = value?.count ?? 0 32 | let minNameLength = 5 33 | name.status = nameLength >= minNameLength ? .valid : .tooShort(minLength: minNameLength) 34 | } 35 | 36 | private func update(pincode: inout Field, with value: String?) { 37 | pincode.value = value 38 | 39 | let value = value ?? "" 40 | pincode.status = value.isNumberic ? .valid : .numbersOnly 41 | } 42 | 43 | private func update(dogName: inout Field, with value: String?) { 44 | dogName.value = value 45 | 46 | let dogNameLength = value?.count ?? 0 47 | let maxDogNameLength = 3 48 | dogName.status = dogNameLength <= maxDogNameLength ? .valid : .tooLong(maxLength: maxDogNameLength) 49 | } 50 | 51 | private func update(isValidForm state: inout FormState) { 52 | state.isValidForm = checkValidStatus(of: [state.name, state.pincode, state.dogName]) 53 | } 54 | 55 | private func checkValidStatus(of fields: [Field]) -> Bool { 56 | fields.allSatisfy { $0.status.isValid } 57 | } 58 | -------------------------------------------------------------------------------- /AppModel/AppModel/SupportingFiles/AppModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppModel.h 3 | // AppModel 4 | // 5 | // Created by Anton Goncharov on 13.12.2020. 6 | // Copyright © 2020 Anton Goncharov. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for AppModel. 12 | FOUNDATION_EXPORT double AppModelVersionNumber; 13 | 14 | //! Project version string for AppModel. 15 | FOUNDATION_EXPORT const unsigned char AppModelVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /AppModel/AppModel/SupportingFiles/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /SwiftUIApp/SwiftUIApp.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7D7EDCC62586233600E17C13 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D7EDCC52586233600E17C13 /* AppDelegate.swift */; }; 11 | 7D7EDCC82586233600E17C13 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D7EDCC72586233600E17C13 /* SceneDelegate.swift */; }; 12 | 7D7EDCCA2586233600E17C13 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D7EDCC92586233600E17C13 /* ContentView.swift */; }; 13 | 7D7EDCCC2586233700E17C13 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7D7EDCCB2586233700E17C13 /* Assets.xcassets */; }; 14 | 7D7EDCCF2586233700E17C13 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7D7EDCCE2586233700E17C13 /* Preview Assets.xcassets */; }; 15 | 7D7EDCD22586233700E17C13 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7D7EDCD02586233700E17C13 /* LaunchScreen.storyboard */; }; 16 | 7D7EDCDC2586237B00E17C13 /* AppModel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D7EDCDA2586237B00E17C13 /* AppModel.framework */; }; 17 | 7D7EDCDD2586237B00E17C13 /* AppModel.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7D7EDCDA2586237B00E17C13 /* AppModel.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 18 | 7D7EDCDE2586237B00E17C13 /* UDF.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D7EDCDB2586237B00E17C13 /* UDF.framework */; }; 19 | 7D7EDCDF2586237B00E17C13 /* UDF.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7D7EDCDB2586237B00E17C13 /* UDF.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXCopyFilesBuildPhase section */ 23 | 7D7EDCE02586237B00E17C13 /* Embed Frameworks */ = { 24 | isa = PBXCopyFilesBuildPhase; 25 | buildActionMask = 2147483647; 26 | dstPath = ""; 27 | dstSubfolderSpec = 10; 28 | files = ( 29 | 7D7EDCDF2586237B00E17C13 /* UDF.framework in Embed Frameworks */, 30 | 7D7EDCDD2586237B00E17C13 /* AppModel.framework in Embed Frameworks */, 31 | ); 32 | name = "Embed Frameworks"; 33 | runOnlyForDeploymentPostprocessing = 0; 34 | }; 35 | /* End PBXCopyFilesBuildPhase section */ 36 | 37 | /* Begin PBXFileReference section */ 38 | 7D7EDCC22586233600E17C13 /* SwiftUIApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftUIApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | 7D7EDCC52586233600E17C13 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 40 | 7D7EDCC72586233600E17C13 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 41 | 7D7EDCC92586233600E17C13 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 42 | 7D7EDCCB2586233700E17C13 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 7D7EDCCE2586233700E17C13 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 44 | 7D7EDCD12586233700E17C13 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 45 | 7D7EDCD32586233700E17C13 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 46 | 7D7EDCDA2586237B00E17C13 /* AppModel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = AppModel.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | 7D7EDCDB2586237B00E17C13 /* UDF.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = UDF.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | 7D7EDCBF2586233600E17C13 /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | 7D7EDCDE2586237B00E17C13 /* UDF.framework in Frameworks */, 56 | 7D7EDCDC2586237B00E17C13 /* AppModel.framework in Frameworks */, 57 | ); 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | /* End PBXFrameworksBuildPhase section */ 61 | 62 | /* Begin PBXGroup section */ 63 | 7D7EDCB92586233600E17C13 = { 64 | isa = PBXGroup; 65 | children = ( 66 | 7D7EDCC42586233600E17C13 /* SwiftUIApp */, 67 | 7D7EDCC32586233600E17C13 /* Products */, 68 | 7D7EDCD92586237B00E17C13 /* Frameworks */, 69 | ); 70 | sourceTree = ""; 71 | }; 72 | 7D7EDCC32586233600E17C13 /* Products */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | 7D7EDCC22586233600E17C13 /* SwiftUIApp.app */, 76 | ); 77 | name = Products; 78 | sourceTree = ""; 79 | }; 80 | 7D7EDCC42586233600E17C13 /* SwiftUIApp */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 7D7EDCC52586233600E17C13 /* AppDelegate.swift */, 84 | 7D7EDCC72586233600E17C13 /* SceneDelegate.swift */, 85 | 7D7EDCC92586233600E17C13 /* ContentView.swift */, 86 | 7D7EDCCB2586233700E17C13 /* Assets.xcassets */, 87 | 7D7EDCD02586233700E17C13 /* LaunchScreen.storyboard */, 88 | 7D7EDCD32586233700E17C13 /* Info.plist */, 89 | 7D7EDCCD2586233700E17C13 /* Preview Content */, 90 | ); 91 | path = SwiftUIApp; 92 | sourceTree = ""; 93 | }; 94 | 7D7EDCCD2586233700E17C13 /* Preview Content */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 7D7EDCCE2586233700E17C13 /* Preview Assets.xcassets */, 98 | ); 99 | path = "Preview Content"; 100 | sourceTree = ""; 101 | }; 102 | 7D7EDCD92586237B00E17C13 /* Frameworks */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 7D7EDCDA2586237B00E17C13 /* AppModel.framework */, 106 | 7D7EDCDB2586237B00E17C13 /* UDF.framework */, 107 | ); 108 | name = Frameworks; 109 | sourceTree = ""; 110 | }; 111 | /* End PBXGroup section */ 112 | 113 | /* Begin PBXNativeTarget section */ 114 | 7D7EDCC12586233600E17C13 /* SwiftUIApp */ = { 115 | isa = PBXNativeTarget; 116 | buildConfigurationList = 7D7EDCD62586233700E17C13 /* Build configuration list for PBXNativeTarget "SwiftUIApp" */; 117 | buildPhases = ( 118 | 7D7EDCBE2586233600E17C13 /* Sources */, 119 | 7D7EDCBF2586233600E17C13 /* Frameworks */, 120 | 7D7EDCC02586233600E17C13 /* Resources */, 121 | 7D7EDCE02586237B00E17C13 /* Embed Frameworks */, 122 | ); 123 | buildRules = ( 124 | ); 125 | dependencies = ( 126 | ); 127 | name = SwiftUIApp; 128 | productName = SwiftUIApp; 129 | productReference = 7D7EDCC22586233600E17C13 /* SwiftUIApp.app */; 130 | productType = "com.apple.product-type.application"; 131 | }; 132 | /* End PBXNativeTarget section */ 133 | 134 | /* Begin PBXProject section */ 135 | 7D7EDCBA2586233600E17C13 /* Project object */ = { 136 | isa = PBXProject; 137 | attributes = { 138 | LastSwiftUpdateCheck = 1150; 139 | LastUpgradeCheck = 1150; 140 | ORGANIZATIONNAME = "Anton Goncharov"; 141 | TargetAttributes = { 142 | 7D7EDCC12586233600E17C13 = { 143 | CreatedOnToolsVersion = 11.5; 144 | }; 145 | }; 146 | }; 147 | buildConfigurationList = 7D7EDCBD2586233600E17C13 /* Build configuration list for PBXProject "SwiftUIApp" */; 148 | compatibilityVersion = "Xcode 9.3"; 149 | developmentRegion = en; 150 | hasScannedForEncodings = 0; 151 | knownRegions = ( 152 | en, 153 | Base, 154 | ); 155 | mainGroup = 7D7EDCB92586233600E17C13; 156 | productRefGroup = 7D7EDCC32586233600E17C13 /* Products */; 157 | projectDirPath = ""; 158 | projectRoot = ""; 159 | targets = ( 160 | 7D7EDCC12586233600E17C13 /* SwiftUIApp */, 161 | ); 162 | }; 163 | /* End PBXProject section */ 164 | 165 | /* Begin PBXResourcesBuildPhase section */ 166 | 7D7EDCC02586233600E17C13 /* Resources */ = { 167 | isa = PBXResourcesBuildPhase; 168 | buildActionMask = 2147483647; 169 | files = ( 170 | 7D7EDCD22586233700E17C13 /* LaunchScreen.storyboard in Resources */, 171 | 7D7EDCCF2586233700E17C13 /* Preview Assets.xcassets in Resources */, 172 | 7D7EDCCC2586233700E17C13 /* Assets.xcassets in Resources */, 173 | ); 174 | runOnlyForDeploymentPostprocessing = 0; 175 | }; 176 | /* End PBXResourcesBuildPhase section */ 177 | 178 | /* Begin PBXSourcesBuildPhase section */ 179 | 7D7EDCBE2586233600E17C13 /* Sources */ = { 180 | isa = PBXSourcesBuildPhase; 181 | buildActionMask = 2147483647; 182 | files = ( 183 | 7D7EDCC62586233600E17C13 /* AppDelegate.swift in Sources */, 184 | 7D7EDCC82586233600E17C13 /* SceneDelegate.swift in Sources */, 185 | 7D7EDCCA2586233600E17C13 /* ContentView.swift in Sources */, 186 | ); 187 | runOnlyForDeploymentPostprocessing = 0; 188 | }; 189 | /* End PBXSourcesBuildPhase section */ 190 | 191 | /* Begin PBXVariantGroup section */ 192 | 7D7EDCD02586233700E17C13 /* LaunchScreen.storyboard */ = { 193 | isa = PBXVariantGroup; 194 | children = ( 195 | 7D7EDCD12586233700E17C13 /* Base */, 196 | ); 197 | name = LaunchScreen.storyboard; 198 | sourceTree = ""; 199 | }; 200 | /* End PBXVariantGroup section */ 201 | 202 | /* Begin XCBuildConfiguration section */ 203 | 7D7EDCD42586233700E17C13 /* Debug */ = { 204 | isa = XCBuildConfiguration; 205 | buildSettings = { 206 | ALWAYS_SEARCH_USER_PATHS = NO; 207 | CLANG_ANALYZER_NONNULL = YES; 208 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 209 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 210 | CLANG_CXX_LIBRARY = "libc++"; 211 | CLANG_ENABLE_MODULES = YES; 212 | CLANG_ENABLE_OBJC_ARC = YES; 213 | CLANG_ENABLE_OBJC_WEAK = YES; 214 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 215 | CLANG_WARN_BOOL_CONVERSION = YES; 216 | CLANG_WARN_COMMA = YES; 217 | CLANG_WARN_CONSTANT_CONVERSION = YES; 218 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 219 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 220 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 221 | CLANG_WARN_EMPTY_BODY = YES; 222 | CLANG_WARN_ENUM_CONVERSION = YES; 223 | CLANG_WARN_INFINITE_RECURSION = YES; 224 | CLANG_WARN_INT_CONVERSION = YES; 225 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 226 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 227 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 228 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 229 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 230 | CLANG_WARN_STRICT_PROTOTYPES = YES; 231 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 232 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 233 | CLANG_WARN_UNREACHABLE_CODE = YES; 234 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 235 | COPY_PHASE_STRIP = NO; 236 | DEBUG_INFORMATION_FORMAT = dwarf; 237 | ENABLE_STRICT_OBJC_MSGSEND = YES; 238 | ENABLE_TESTABILITY = YES; 239 | GCC_C_LANGUAGE_STANDARD = gnu11; 240 | GCC_DYNAMIC_NO_PIC = NO; 241 | GCC_NO_COMMON_BLOCKS = YES; 242 | GCC_OPTIMIZATION_LEVEL = 0; 243 | GCC_PREPROCESSOR_DEFINITIONS = ( 244 | "DEBUG=1", 245 | "$(inherited)", 246 | ); 247 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 248 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 249 | GCC_WARN_UNDECLARED_SELECTOR = YES; 250 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 251 | GCC_WARN_UNUSED_FUNCTION = YES; 252 | GCC_WARN_UNUSED_VARIABLE = YES; 253 | IPHONEOS_DEPLOYMENT_TARGET = 13.5; 254 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 255 | MTL_FAST_MATH = YES; 256 | ONLY_ACTIVE_ARCH = YES; 257 | SDKROOT = iphoneos; 258 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 259 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 260 | }; 261 | name = Debug; 262 | }; 263 | 7D7EDCD52586233700E17C13 /* Release */ = { 264 | isa = XCBuildConfiguration; 265 | buildSettings = { 266 | ALWAYS_SEARCH_USER_PATHS = NO; 267 | CLANG_ANALYZER_NONNULL = YES; 268 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 269 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 270 | CLANG_CXX_LIBRARY = "libc++"; 271 | CLANG_ENABLE_MODULES = YES; 272 | CLANG_ENABLE_OBJC_ARC = YES; 273 | CLANG_ENABLE_OBJC_WEAK = YES; 274 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 275 | CLANG_WARN_BOOL_CONVERSION = YES; 276 | CLANG_WARN_COMMA = YES; 277 | CLANG_WARN_CONSTANT_CONVERSION = YES; 278 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 279 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 280 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 281 | CLANG_WARN_EMPTY_BODY = YES; 282 | CLANG_WARN_ENUM_CONVERSION = YES; 283 | CLANG_WARN_INFINITE_RECURSION = YES; 284 | CLANG_WARN_INT_CONVERSION = YES; 285 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 286 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 287 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 288 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 289 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 290 | CLANG_WARN_STRICT_PROTOTYPES = YES; 291 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 292 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 293 | CLANG_WARN_UNREACHABLE_CODE = YES; 294 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 295 | COPY_PHASE_STRIP = NO; 296 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 297 | ENABLE_NS_ASSERTIONS = NO; 298 | ENABLE_STRICT_OBJC_MSGSEND = YES; 299 | GCC_C_LANGUAGE_STANDARD = gnu11; 300 | GCC_NO_COMMON_BLOCKS = YES; 301 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 302 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 303 | GCC_WARN_UNDECLARED_SELECTOR = YES; 304 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 305 | GCC_WARN_UNUSED_FUNCTION = YES; 306 | GCC_WARN_UNUSED_VARIABLE = YES; 307 | IPHONEOS_DEPLOYMENT_TARGET = 13.5; 308 | MTL_ENABLE_DEBUG_INFO = NO; 309 | MTL_FAST_MATH = YES; 310 | SDKROOT = iphoneos; 311 | SWIFT_COMPILATION_MODE = wholemodule; 312 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 313 | VALIDATE_PRODUCT = YES; 314 | }; 315 | name = Release; 316 | }; 317 | 7D7EDCD72586233700E17C13 /* Debug */ = { 318 | isa = XCBuildConfiguration; 319 | buildSettings = { 320 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 321 | CODE_SIGN_STYLE = Automatic; 322 | DEVELOPMENT_ASSET_PATHS = "\"SwiftUIApp/Preview Content\""; 323 | ENABLE_PREVIEWS = YES; 324 | INFOPLIST_FILE = SwiftUIApp/Info.plist; 325 | LD_RUNPATH_SEARCH_PATHS = ( 326 | "$(inherited)", 327 | "@executable_path/Frameworks", 328 | ); 329 | PRODUCT_BUNDLE_IDENTIFIER = com.MasterWatcher.SwiftUIApp; 330 | PRODUCT_NAME = "$(TARGET_NAME)"; 331 | SWIFT_VERSION = 5.0; 332 | TARGETED_DEVICE_FAMILY = "1,2"; 333 | }; 334 | name = Debug; 335 | }; 336 | 7D7EDCD82586233700E17C13 /* Release */ = { 337 | isa = XCBuildConfiguration; 338 | buildSettings = { 339 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 340 | CODE_SIGN_STYLE = Automatic; 341 | DEVELOPMENT_ASSET_PATHS = "\"SwiftUIApp/Preview Content\""; 342 | ENABLE_PREVIEWS = YES; 343 | INFOPLIST_FILE = SwiftUIApp/Info.plist; 344 | LD_RUNPATH_SEARCH_PATHS = ( 345 | "$(inherited)", 346 | "@executable_path/Frameworks", 347 | ); 348 | PRODUCT_BUNDLE_IDENTIFIER = com.MasterWatcher.SwiftUIApp; 349 | PRODUCT_NAME = "$(TARGET_NAME)"; 350 | SWIFT_VERSION = 5.0; 351 | TARGETED_DEVICE_FAMILY = "1,2"; 352 | }; 353 | name = Release; 354 | }; 355 | /* End XCBuildConfiguration section */ 356 | 357 | /* Begin XCConfigurationList section */ 358 | 7D7EDCBD2586233600E17C13 /* Build configuration list for PBXProject "SwiftUIApp" */ = { 359 | isa = XCConfigurationList; 360 | buildConfigurations = ( 361 | 7D7EDCD42586233700E17C13 /* Debug */, 362 | 7D7EDCD52586233700E17C13 /* Release */, 363 | ); 364 | defaultConfigurationIsVisible = 0; 365 | defaultConfigurationName = Release; 366 | }; 367 | 7D7EDCD62586233700E17C13 /* Build configuration list for PBXNativeTarget "SwiftUIApp" */ = { 368 | isa = XCConfigurationList; 369 | buildConfigurations = ( 370 | 7D7EDCD72586233700E17C13 /* Debug */, 371 | 7D7EDCD82586233700E17C13 /* Release */, 372 | ); 373 | defaultConfigurationIsVisible = 0; 374 | defaultConfigurationName = Release; 375 | }; 376 | /* End XCConfigurationList section */ 377 | }; 378 | rootObject = 7D7EDCBA2586233600E17C13 /* Project object */; 379 | } 380 | -------------------------------------------------------------------------------- /SwiftUIApp/SwiftUIApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftUIApp/SwiftUIApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftUIApp/SwiftUIApp.xcodeproj/xcuserdata/antongoncharov.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SwiftUIApp.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 3 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SwiftUIApp/SwiftUIApp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SwiftUIApp 4 | // 5 | // Created by Anton Goncharov on 13.12.2020. 6 | // Copyright © 2020 Anton Goncharov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /SwiftUIApp/SwiftUIApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /SwiftUIApp/SwiftUIApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUIApp/SwiftUIApp/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 | -------------------------------------------------------------------------------- /SwiftUIApp/SwiftUIApp/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // SwiftUIApp 4 | // 5 | // Created by Anton Goncharov on 13.12.2020. 6 | // Copyright © 2020 Anton Goncharov. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import UDF 11 | import AppModel 12 | 13 | struct ContentView: View { 14 | 15 | @EnvironmentObject 16 | var store: SwiftUIStore 17 | 18 | func statusToError(_ status: FieldStatus) -> String? { 19 | switch status { 20 | case .default, .valid: 21 | return nil 22 | case let .tooShort(minLength): 23 | return "Minimum \(minLength) characters" 24 | case let .tooLong(maxLength): 25 | return "Maximum \(maxLength) characters" 26 | case .numbersOnly: 27 | return "Only numbers allowed" 28 | } 29 | } 30 | 31 | var body: some View { 32 | NavigationView { 33 | VStack { 34 | FieldView( 35 | label: "Name", 36 | text: store.binding(get: { $0.name.value.orEmpty }, send: Actions.nameDidChange), 37 | error: statusToError(store.state.name.status)) 38 | FieldView( 39 | label: "Pincode", 40 | text: store.binding(get: { $0.pincode.value.orEmpty }, send: Actions.pincodeDidChange), 41 | error: statusToError(store.state.pincode.status)) 42 | FieldView( 43 | label: "Dog's name", 44 | text: store.binding(get: { $0.dogName.value.orEmpty }, send: Actions.dogNameDidChange), 45 | error: statusToError(store.state.dogName.status)) 46 | Spacer() 47 | } 48 | .padding(16) 49 | .navigationBarTitle("Some Form", displayMode: .inline) 50 | .navigationBarItems( 51 | trailing: 52 | Button(action: {}) { 53 | Text("Save") 54 | } 55 | .disabled(!store.state.isValidForm) 56 | ) 57 | } 58 | } 59 | } 60 | 61 | struct FieldView: View { 62 | 63 | var label: String 64 | @Binding var text: String 65 | var error: String? 66 | 67 | var body: some View { 68 | VStack(alignment: .leading, spacing: 10) { 69 | TextField(label, text: $text) 70 | .textFieldStyle(RoundedBorderTextFieldStyle()) 71 | if error != nil { 72 | Text(error.orEmpty) 73 | .font(.system(size: 12)) 74 | .foregroundColor(.red) 75 | } 76 | } 77 | } 78 | } 79 | 80 | struct ContentView_Previews: PreviewProvider { 81 | static var previews: some View { 82 | ContentView() 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /SwiftUIApp/SwiftUIApp/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | 37 | 38 | 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /SwiftUIApp/SwiftUIApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUIApp/SwiftUIApp/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // SwiftUIApp 4 | // 5 | // Created by Anton Goncharov on 13.12.2020. 6 | // Copyright © 2020 Anton Goncharov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | import UDF 12 | import AppModel 13 | 14 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 15 | 16 | var window: UIWindow? 17 | 18 | var store: SwiftUIStore = SwiftUIStore(state: FormState(), reducer: reduce) 19 | 20 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 21 | let contentView = ContentView() 22 | .environmentObject(store) 23 | 24 | // Use a UIHostingController as window root view controller. 25 | if let windowScene = scene as? UIWindowScene { 26 | let window = UIWindow(windowScene: windowScene) 27 | window.rootViewController = UIHostingController(rootView: contentView) 28 | self.window = window 29 | window.makeKeyAndVisible() 30 | } 31 | } 32 | 33 | func sceneDidDisconnect(_ scene: UIScene) { 34 | // Called as the scene is being released by the system. 35 | // This occurs shortly after the scene enters the background, or when its session is discarded. 36 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 37 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 38 | } 39 | 40 | func sceneDidBecomeActive(_ scene: UIScene) { 41 | // Called when the scene has moved from an inactive state to an active state. 42 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 43 | } 44 | 45 | func sceneWillResignActive(_ scene: UIScene) { 46 | // Called when the scene will move from an active state to an inactive state. 47 | // This may occur due to temporary interruptions (ex. an incoming phone call). 48 | } 49 | 50 | func sceneWillEnterForeground(_ scene: UIScene) { 51 | // Called as the scene transitions from the background to the foreground. 52 | // Use this method to undo the changes made on entering the background. 53 | } 54 | 55 | func sceneDidEnterBackground(_ scene: UIScene) { 56 | // Called as the scene transitions from the foreground to the background. 57 | // Use this method to save data, release shared resources, and store enough scene-specific state information 58 | // to restore the scene back to its current state. 59 | } 60 | 61 | 62 | } 63 | 64 | -------------------------------------------------------------------------------- /UDF/UDF.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7D7EDC0B25861D9500E17C13 /* UDF.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D7EDC0925861D9500E17C13 /* UDF.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 7D7EDC1325861DAC00E17C13 /* Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D7EDC1125861DAC00E17C13 /* Action.swift */; }; 12 | 7D7EDC1425861DAC00E17C13 /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D7EDC1225861DAC00E17C13 /* Store.swift */; }; 13 | 7D7EDCE22586317C00E17C13 /* SwiftUIStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D7EDCE12586317C00E17C13 /* SwiftUIStore.swift */; }; 14 | /* End PBXBuildFile section */ 15 | 16 | /* Begin PBXFileReference section */ 17 | 7D7EDC0625861D9500E17C13 /* UDF.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = UDF.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 18 | 7D7EDC0925861D9500E17C13 /* UDF.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UDF.h; sourceTree = ""; }; 19 | 7D7EDC0A25861D9500E17C13 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 20 | 7D7EDC1125861DAC00E17C13 /* Action.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Action.swift; sourceTree = ""; }; 21 | 7D7EDC1225861DAC00E17C13 /* Store.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Store.swift; sourceTree = ""; }; 22 | 7D7EDCE12586317C00E17C13 /* SwiftUIStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIStore.swift; sourceTree = ""; }; 23 | /* End PBXFileReference section */ 24 | 25 | /* Begin PBXFrameworksBuildPhase section */ 26 | 7D7EDC0325861D9500E17C13 /* Frameworks */ = { 27 | isa = PBXFrameworksBuildPhase; 28 | buildActionMask = 2147483647; 29 | files = ( 30 | ); 31 | runOnlyForDeploymentPostprocessing = 0; 32 | }; 33 | /* End PBXFrameworksBuildPhase section */ 34 | 35 | /* Begin PBXGroup section */ 36 | 7D7EDBFC25861D9500E17C13 = { 37 | isa = PBXGroup; 38 | children = ( 39 | 7D7EDC0825861D9500E17C13 /* UDF */, 40 | 7D7EDC0725861D9500E17C13 /* Products */, 41 | ); 42 | sourceTree = ""; 43 | }; 44 | 7D7EDC0725861D9500E17C13 /* Products */ = { 45 | isa = PBXGroup; 46 | children = ( 47 | 7D7EDC0625861D9500E17C13 /* UDF.framework */, 48 | ); 49 | name = Products; 50 | sourceTree = ""; 51 | }; 52 | 7D7EDC0825861D9500E17C13 /* UDF */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 7D7EDC932586207D00E17C13 /* Sources */, 56 | 7D7EDC7D2586205700E17C13 /* SupportingFiles */, 57 | ); 58 | path = UDF; 59 | sourceTree = ""; 60 | }; 61 | 7D7EDC7D2586205700E17C13 /* SupportingFiles */ = { 62 | isa = PBXGroup; 63 | children = ( 64 | 7D7EDC0925861D9500E17C13 /* UDF.h */, 65 | 7D7EDC0A25861D9500E17C13 /* Info.plist */, 66 | ); 67 | path = SupportingFiles; 68 | sourceTree = ""; 69 | }; 70 | 7D7EDC932586207D00E17C13 /* Sources */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 7D7EDC1125861DAC00E17C13 /* Action.swift */, 74 | 7D7EDC1225861DAC00E17C13 /* Store.swift */, 75 | 7D7EDCE12586317C00E17C13 /* SwiftUIStore.swift */, 76 | ); 77 | path = Sources; 78 | sourceTree = ""; 79 | }; 80 | /* End PBXGroup section */ 81 | 82 | /* Begin PBXHeadersBuildPhase section */ 83 | 7D7EDC0125861D9500E17C13 /* Headers */ = { 84 | isa = PBXHeadersBuildPhase; 85 | buildActionMask = 2147483647; 86 | files = ( 87 | 7D7EDC0B25861D9500E17C13 /* UDF.h in Headers */, 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | /* End PBXHeadersBuildPhase section */ 92 | 93 | /* Begin PBXNativeTarget section */ 94 | 7D7EDC0525861D9500E17C13 /* UDF */ = { 95 | isa = PBXNativeTarget; 96 | buildConfigurationList = 7D7EDC0E25861D9500E17C13 /* Build configuration list for PBXNativeTarget "UDF" */; 97 | buildPhases = ( 98 | 7D7EDC0125861D9500E17C13 /* Headers */, 99 | 7D7EDC0225861D9500E17C13 /* Sources */, 100 | 7D7EDC0325861D9500E17C13 /* Frameworks */, 101 | 7D7EDC0425861D9500E17C13 /* Resources */, 102 | ); 103 | buildRules = ( 104 | ); 105 | dependencies = ( 106 | ); 107 | name = UDF; 108 | productName = UDF; 109 | productReference = 7D7EDC0625861D9500E17C13 /* UDF.framework */; 110 | productType = "com.apple.product-type.framework"; 111 | }; 112 | /* End PBXNativeTarget section */ 113 | 114 | /* Begin PBXProject section */ 115 | 7D7EDBFD25861D9500E17C13 /* Project object */ = { 116 | isa = PBXProject; 117 | attributes = { 118 | LastUpgradeCheck = 1150; 119 | ORGANIZATIONNAME = "Anton Goncharov"; 120 | TargetAttributes = { 121 | 7D7EDC0525861D9500E17C13 = { 122 | CreatedOnToolsVersion = 11.5; 123 | LastSwiftMigration = 1150; 124 | }; 125 | }; 126 | }; 127 | buildConfigurationList = 7D7EDC0025861D9500E17C13 /* Build configuration list for PBXProject "UDF" */; 128 | compatibilityVersion = "Xcode 9.3"; 129 | developmentRegion = en; 130 | hasScannedForEncodings = 0; 131 | knownRegions = ( 132 | en, 133 | Base, 134 | ); 135 | mainGroup = 7D7EDBFC25861D9500E17C13; 136 | productRefGroup = 7D7EDC0725861D9500E17C13 /* Products */; 137 | projectDirPath = ""; 138 | projectRoot = ""; 139 | targets = ( 140 | 7D7EDC0525861D9500E17C13 /* UDF */, 141 | ); 142 | }; 143 | /* End PBXProject section */ 144 | 145 | /* Begin PBXResourcesBuildPhase section */ 146 | 7D7EDC0425861D9500E17C13 /* Resources */ = { 147 | isa = PBXResourcesBuildPhase; 148 | buildActionMask = 2147483647; 149 | files = ( 150 | ); 151 | runOnlyForDeploymentPostprocessing = 0; 152 | }; 153 | /* End PBXResourcesBuildPhase section */ 154 | 155 | /* Begin PBXSourcesBuildPhase section */ 156 | 7D7EDC0225861D9500E17C13 /* Sources */ = { 157 | isa = PBXSourcesBuildPhase; 158 | buildActionMask = 2147483647; 159 | files = ( 160 | 7D7EDCE22586317C00E17C13 /* SwiftUIStore.swift in Sources */, 161 | 7D7EDC1325861DAC00E17C13 /* Action.swift in Sources */, 162 | 7D7EDC1425861DAC00E17C13 /* Store.swift in Sources */, 163 | ); 164 | runOnlyForDeploymentPostprocessing = 0; 165 | }; 166 | /* End PBXSourcesBuildPhase section */ 167 | 168 | /* Begin XCBuildConfiguration section */ 169 | 7D7EDC0C25861D9500E17C13 /* Debug */ = { 170 | isa = XCBuildConfiguration; 171 | buildSettings = { 172 | ALWAYS_SEARCH_USER_PATHS = NO; 173 | CLANG_ANALYZER_NONNULL = YES; 174 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 175 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 176 | CLANG_CXX_LIBRARY = "libc++"; 177 | CLANG_ENABLE_MODULES = YES; 178 | CLANG_ENABLE_OBJC_ARC = YES; 179 | CLANG_ENABLE_OBJC_WEAK = YES; 180 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 181 | CLANG_WARN_BOOL_CONVERSION = YES; 182 | CLANG_WARN_COMMA = YES; 183 | CLANG_WARN_CONSTANT_CONVERSION = YES; 184 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 185 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 186 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 187 | CLANG_WARN_EMPTY_BODY = YES; 188 | CLANG_WARN_ENUM_CONVERSION = YES; 189 | CLANG_WARN_INFINITE_RECURSION = YES; 190 | CLANG_WARN_INT_CONVERSION = YES; 191 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 192 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 193 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 194 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 195 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 196 | CLANG_WARN_STRICT_PROTOTYPES = YES; 197 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 198 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 199 | CLANG_WARN_UNREACHABLE_CODE = YES; 200 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 201 | COPY_PHASE_STRIP = NO; 202 | CURRENT_PROJECT_VERSION = 1; 203 | DEBUG_INFORMATION_FORMAT = dwarf; 204 | ENABLE_STRICT_OBJC_MSGSEND = YES; 205 | ENABLE_TESTABILITY = YES; 206 | GCC_C_LANGUAGE_STANDARD = gnu11; 207 | GCC_DYNAMIC_NO_PIC = NO; 208 | GCC_NO_COMMON_BLOCKS = YES; 209 | GCC_OPTIMIZATION_LEVEL = 0; 210 | GCC_PREPROCESSOR_DEFINITIONS = ( 211 | "DEBUG=1", 212 | "$(inherited)", 213 | ); 214 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 215 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 216 | GCC_WARN_UNDECLARED_SELECTOR = YES; 217 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 218 | GCC_WARN_UNUSED_FUNCTION = YES; 219 | GCC_WARN_UNUSED_VARIABLE = YES; 220 | IPHONEOS_DEPLOYMENT_TARGET = 13.5; 221 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 222 | MTL_FAST_MATH = YES; 223 | ONLY_ACTIVE_ARCH = YES; 224 | SDKROOT = iphoneos; 225 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 226 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 227 | VERSIONING_SYSTEM = "apple-generic"; 228 | VERSION_INFO_PREFIX = ""; 229 | }; 230 | name = Debug; 231 | }; 232 | 7D7EDC0D25861D9500E17C13 /* Release */ = { 233 | isa = XCBuildConfiguration; 234 | buildSettings = { 235 | ALWAYS_SEARCH_USER_PATHS = NO; 236 | CLANG_ANALYZER_NONNULL = YES; 237 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 238 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 239 | CLANG_CXX_LIBRARY = "libc++"; 240 | CLANG_ENABLE_MODULES = YES; 241 | CLANG_ENABLE_OBJC_ARC = YES; 242 | CLANG_ENABLE_OBJC_WEAK = YES; 243 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 244 | CLANG_WARN_BOOL_CONVERSION = YES; 245 | CLANG_WARN_COMMA = YES; 246 | CLANG_WARN_CONSTANT_CONVERSION = YES; 247 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 249 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 250 | CLANG_WARN_EMPTY_BODY = YES; 251 | CLANG_WARN_ENUM_CONVERSION = YES; 252 | CLANG_WARN_INFINITE_RECURSION = YES; 253 | CLANG_WARN_INT_CONVERSION = YES; 254 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 255 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 256 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 257 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 258 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 259 | CLANG_WARN_STRICT_PROTOTYPES = YES; 260 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 261 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 262 | CLANG_WARN_UNREACHABLE_CODE = YES; 263 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 264 | COPY_PHASE_STRIP = NO; 265 | CURRENT_PROJECT_VERSION = 1; 266 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 267 | ENABLE_NS_ASSERTIONS = NO; 268 | ENABLE_STRICT_OBJC_MSGSEND = YES; 269 | GCC_C_LANGUAGE_STANDARD = gnu11; 270 | GCC_NO_COMMON_BLOCKS = YES; 271 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 272 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 273 | GCC_WARN_UNDECLARED_SELECTOR = YES; 274 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 275 | GCC_WARN_UNUSED_FUNCTION = YES; 276 | GCC_WARN_UNUSED_VARIABLE = YES; 277 | IPHONEOS_DEPLOYMENT_TARGET = 13.5; 278 | MTL_ENABLE_DEBUG_INFO = NO; 279 | MTL_FAST_MATH = YES; 280 | SDKROOT = iphoneos; 281 | SWIFT_COMPILATION_MODE = wholemodule; 282 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 283 | VALIDATE_PRODUCT = YES; 284 | VERSIONING_SYSTEM = "apple-generic"; 285 | VERSION_INFO_PREFIX = ""; 286 | }; 287 | name = Release; 288 | }; 289 | 7D7EDC0F25861D9500E17C13 /* Debug */ = { 290 | isa = XCBuildConfiguration; 291 | buildSettings = { 292 | CLANG_ENABLE_MODULES = YES; 293 | CODE_SIGN_STYLE = Automatic; 294 | DEFINES_MODULE = YES; 295 | DYLIB_COMPATIBILITY_VERSION = 1; 296 | DYLIB_CURRENT_VERSION = 1; 297 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 298 | INFOPLIST_FILE = UDF/SupportingFiles/Info.plist; 299 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 300 | LD_RUNPATH_SEARCH_PATHS = ( 301 | "$(inherited)", 302 | "@executable_path/Frameworks", 303 | "@loader_path/Frameworks", 304 | ); 305 | PRODUCT_BUNDLE_IDENTIFIER = com.MasterWatcher.UDF; 306 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 307 | SKIP_INSTALL = YES; 308 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 309 | SWIFT_VERSION = 5.0; 310 | TARGETED_DEVICE_FAMILY = "1,2"; 311 | }; 312 | name = Debug; 313 | }; 314 | 7D7EDC1025861D9500E17C13 /* Release */ = { 315 | isa = XCBuildConfiguration; 316 | buildSettings = { 317 | CLANG_ENABLE_MODULES = YES; 318 | CODE_SIGN_STYLE = Automatic; 319 | DEFINES_MODULE = YES; 320 | DYLIB_COMPATIBILITY_VERSION = 1; 321 | DYLIB_CURRENT_VERSION = 1; 322 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 323 | INFOPLIST_FILE = UDF/SupportingFiles/Info.plist; 324 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 325 | LD_RUNPATH_SEARCH_PATHS = ( 326 | "$(inherited)", 327 | "@executable_path/Frameworks", 328 | "@loader_path/Frameworks", 329 | ); 330 | PRODUCT_BUNDLE_IDENTIFIER = com.MasterWatcher.UDF; 331 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 332 | SKIP_INSTALL = YES; 333 | SWIFT_VERSION = 5.0; 334 | TARGETED_DEVICE_FAMILY = "1,2"; 335 | }; 336 | name = Release; 337 | }; 338 | /* End XCBuildConfiguration section */ 339 | 340 | /* Begin XCConfigurationList section */ 341 | 7D7EDC0025861D9500E17C13 /* Build configuration list for PBXProject "UDF" */ = { 342 | isa = XCConfigurationList; 343 | buildConfigurations = ( 344 | 7D7EDC0C25861D9500E17C13 /* Debug */, 345 | 7D7EDC0D25861D9500E17C13 /* Release */, 346 | ); 347 | defaultConfigurationIsVisible = 0; 348 | defaultConfigurationName = Release; 349 | }; 350 | 7D7EDC0E25861D9500E17C13 /* Build configuration list for PBXNativeTarget "UDF" */ = { 351 | isa = XCConfigurationList; 352 | buildConfigurations = ( 353 | 7D7EDC0F25861D9500E17C13 /* Debug */, 354 | 7D7EDC1025861D9500E17C13 /* Release */, 355 | ); 356 | defaultConfigurationIsVisible = 0; 357 | defaultConfigurationName = Release; 358 | }; 359 | /* End XCConfigurationList section */ 360 | }; 361 | rootObject = 7D7EDBFD25861D9500E17C13 /* Project object */; 362 | } 363 | -------------------------------------------------------------------------------- /UDF/UDF.xcodeproj/xcuserdata/antongoncharov.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | UDF.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 1 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /UDF/UDF/Sources/Action.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Action.swift 3 | // UDFExample 4 | // 5 | // Created by Anton Goncharov on 24.11.2020. 6 | // 7 | 8 | import Foundation 9 | 10 | public protocol Action {} 11 | -------------------------------------------------------------------------------- /UDF/UDF/Sources/Store.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Store.swift 3 | // UDFExample 4 | // 5 | // Created by Anton Goncharov on 24.11.2020. 6 | // 7 | 8 | import Foundation 9 | 10 | public class Store { 11 | 12 | public typealias Reducer = (inout State, Action) -> Void 13 | public typealias Subscription = (State) -> Void 14 | 15 | private(set) var state: State 16 | private let reducer: Reducer 17 | private var subscribers = [UUID: Subscription]() 18 | 19 | public init(state: State, reducer: @escaping Reducer) { 20 | self.state = state 21 | self.reducer = reducer 22 | } 23 | 24 | public func dispatch(_ action: Action) { 25 | reducer(&state, action) 26 | subscribers.forEach { $0.1(state) } 27 | } 28 | 29 | public func subscribe(_ subscription: @escaping Subscription) -> UUID { 30 | let key = UUID() 31 | subscribers[key] = subscription 32 | subscription(state) 33 | 34 | return key 35 | } 36 | 37 | public func unsubscribe(id: UUID) { 38 | subscribers.removeValue(forKey: id) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /UDF/UDF/Sources/SwiftUIStore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUIStore.swift 3 | // UDF 4 | // 5 | // Created by Anton Goncharov on 13.12.2020. 6 | // Copyright © 2020 Anton Goncharov. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Combine 11 | import SwiftUI 12 | 13 | public class SwiftUIStore: ObservableObject { 14 | 15 | public typealias Reducer = (inout State, Action) -> Void 16 | 17 | @Published public private(set) var state: State 18 | private let reducer: Reducer 19 | 20 | public init(state: State, reducer: @escaping Reducer) { 21 | self.state = state 22 | self.reducer = reducer 23 | } 24 | 25 | public func dispatch(_ action: Action) { 26 | reducer(&state, action) 27 | } 28 | 29 | public func binding( 30 | get: @escaping (State) -> LocalState, 31 | send localStateToViewAction: @escaping (LocalState) -> Action 32 | ) -> Binding { 33 | Binding( 34 | get: { get(self.state) }, 35 | set: { newLocalState, transaction in 36 | self.dispatch(localStateToViewAction(newLocalState)) 37 | }) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /UDF/UDF/SupportingFiles/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /UDF/UDF/SupportingFiles/UDF.h: -------------------------------------------------------------------------------- 1 | // 2 | // UDF.h 3 | // UDF 4 | // 5 | // Created by Anton Goncharov on 13.12.2020. 6 | // Copyright © 2020 Anton Goncharov. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for UDF. 12 | FOUNDATION_EXPORT double UDFVersionNumber; 13 | 14 | //! Project version string for UDF. 15 | FOUNDATION_EXPORT const unsigned char UDFVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /UDFExample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /UDFExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /UDFExample.xcworkspace/xcuserdata/antongoncharov.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /UIKitApp/UIKitApp.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7D7EDC4925861EFB00E17C13 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D7EDC4825861EFB00E17C13 /* AppDelegate.swift */; }; 11 | 7D7EDC4D25861EFB00E17C13 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D7EDC4C25861EFB00E17C13 /* ViewController.swift */; }; 12 | 7D7EDC5025861EFB00E17C13 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7D7EDC4E25861EFB00E17C13 /* Main.storyboard */; }; 13 | 7D7EDC5225861EFD00E17C13 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7D7EDC5125861EFD00E17C13 /* Assets.xcassets */; }; 14 | 7D7EDC5525861EFD00E17C13 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7D7EDC5325861EFD00E17C13 /* LaunchScreen.storyboard */; }; 15 | 7D7EDC6525861FD000E17C13 /* UDF.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D7EDC6425861FD000E17C13 /* UDF.framework */; }; 16 | 7D7EDC6625861FD000E17C13 /* UDF.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7D7EDC6425861FD000E17C13 /* UDF.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 17 | 7D7EDCB72586219200E17C13 /* AppModel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D7EDCB62586219200E17C13 /* AppModel.framework */; }; 18 | 7D7EDCB82586219200E17C13 /* AppModel.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7D7EDCB62586219200E17C13 /* AppModel.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXCopyFilesBuildPhase section */ 22 | 7D7EDC6725861FD100E17C13 /* Embed Frameworks */ = { 23 | isa = PBXCopyFilesBuildPhase; 24 | buildActionMask = 2147483647; 25 | dstPath = ""; 26 | dstSubfolderSpec = 10; 27 | files = ( 28 | 7D7EDCB82586219200E17C13 /* AppModel.framework in Embed Frameworks */, 29 | 7D7EDC6625861FD000E17C13 /* UDF.framework in Embed Frameworks */, 30 | ); 31 | name = "Embed Frameworks"; 32 | runOnlyForDeploymentPostprocessing = 0; 33 | }; 34 | /* End PBXCopyFilesBuildPhase section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | 7D7EDC4525861EFB00E17C13 /* UIKitApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UIKitApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 7D7EDC4825861EFB00E17C13 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 39 | 7D7EDC4C25861EFB00E17C13 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 40 | 7D7EDC4F25861EFB00E17C13 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 41 | 7D7EDC5125861EFD00E17C13 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 42 | 7D7EDC5425861EFD00E17C13 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 43 | 7D7EDC5625861EFD00E17C13 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 44 | 7D7EDC6425861FD000E17C13 /* UDF.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = UDF.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | 7D7EDCB62586219200E17C13 /* AppModel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = AppModel.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | /* End PBXFileReference section */ 47 | 48 | /* Begin PBXFrameworksBuildPhase section */ 49 | 7D7EDC4225861EFB00E17C13 /* Frameworks */ = { 50 | isa = PBXFrameworksBuildPhase; 51 | buildActionMask = 2147483647; 52 | files = ( 53 | 7D7EDCB72586219200E17C13 /* AppModel.framework in Frameworks */, 54 | 7D7EDC6525861FD000E17C13 /* UDF.framework in Frameworks */, 55 | ); 56 | runOnlyForDeploymentPostprocessing = 0; 57 | }; 58 | /* End PBXFrameworksBuildPhase section */ 59 | 60 | /* Begin PBXGroup section */ 61 | 7D7EDC3C25861EFB00E17C13 = { 62 | isa = PBXGroup; 63 | children = ( 64 | 7D7EDC4725861EFB00E17C13 /* UIKitApp */, 65 | 7D7EDC4625861EFB00E17C13 /* Products */, 66 | 7D7EDC6325861FD000E17C13 /* Frameworks */, 67 | ); 68 | sourceTree = ""; 69 | }; 70 | 7D7EDC4625861EFB00E17C13 /* Products */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 7D7EDC4525861EFB00E17C13 /* UIKitApp.app */, 74 | ); 75 | name = Products; 76 | sourceTree = ""; 77 | }; 78 | 7D7EDC4725861EFB00E17C13 /* UIKitApp */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 7D7EDC4825861EFB00E17C13 /* AppDelegate.swift */, 82 | 7D7EDC4C25861EFB00E17C13 /* ViewController.swift */, 83 | 7D7EDC4E25861EFB00E17C13 /* Main.storyboard */, 84 | 7D7EDC5125861EFD00E17C13 /* Assets.xcassets */, 85 | 7D7EDC5325861EFD00E17C13 /* LaunchScreen.storyboard */, 86 | 7D7EDC5625861EFD00E17C13 /* Info.plist */, 87 | ); 88 | path = UIKitApp; 89 | sourceTree = ""; 90 | }; 91 | 7D7EDC6325861FD000E17C13 /* Frameworks */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 7D7EDCB62586219200E17C13 /* AppModel.framework */, 95 | 7D7EDC6425861FD000E17C13 /* UDF.framework */, 96 | ); 97 | name = Frameworks; 98 | sourceTree = ""; 99 | }; 100 | /* End PBXGroup section */ 101 | 102 | /* Begin PBXNativeTarget section */ 103 | 7D7EDC4425861EFB00E17C13 /* UIKitApp */ = { 104 | isa = PBXNativeTarget; 105 | buildConfigurationList = 7D7EDC5925861EFD00E17C13 /* Build configuration list for PBXNativeTarget "UIKitApp" */; 106 | buildPhases = ( 107 | 7D7EDC4125861EFB00E17C13 /* Sources */, 108 | 7D7EDC4225861EFB00E17C13 /* Frameworks */, 109 | 7D7EDC4325861EFB00E17C13 /* Resources */, 110 | 7D7EDC6725861FD100E17C13 /* Embed Frameworks */, 111 | ); 112 | buildRules = ( 113 | ); 114 | dependencies = ( 115 | ); 116 | name = UIKitApp; 117 | productName = UIKitApp; 118 | productReference = 7D7EDC4525861EFB00E17C13 /* UIKitApp.app */; 119 | productType = "com.apple.product-type.application"; 120 | }; 121 | /* End PBXNativeTarget section */ 122 | 123 | /* Begin PBXProject section */ 124 | 7D7EDC3D25861EFB00E17C13 /* Project object */ = { 125 | isa = PBXProject; 126 | attributes = { 127 | LastSwiftUpdateCheck = 1150; 128 | LastUpgradeCheck = 1150; 129 | ORGANIZATIONNAME = "Anton Goncharov"; 130 | TargetAttributes = { 131 | 7D7EDC4425861EFB00E17C13 = { 132 | CreatedOnToolsVersion = 11.5; 133 | }; 134 | }; 135 | }; 136 | buildConfigurationList = 7D7EDC4025861EFB00E17C13 /* Build configuration list for PBXProject "UIKitApp" */; 137 | compatibilityVersion = "Xcode 9.3"; 138 | developmentRegion = en; 139 | hasScannedForEncodings = 0; 140 | knownRegions = ( 141 | en, 142 | Base, 143 | ); 144 | mainGroup = 7D7EDC3C25861EFB00E17C13; 145 | productRefGroup = 7D7EDC4625861EFB00E17C13 /* Products */; 146 | projectDirPath = ""; 147 | projectRoot = ""; 148 | targets = ( 149 | 7D7EDC4425861EFB00E17C13 /* UIKitApp */, 150 | ); 151 | }; 152 | /* End PBXProject section */ 153 | 154 | /* Begin PBXResourcesBuildPhase section */ 155 | 7D7EDC4325861EFB00E17C13 /* Resources */ = { 156 | isa = PBXResourcesBuildPhase; 157 | buildActionMask = 2147483647; 158 | files = ( 159 | 7D7EDC5525861EFD00E17C13 /* LaunchScreen.storyboard in Resources */, 160 | 7D7EDC5225861EFD00E17C13 /* Assets.xcassets in Resources */, 161 | 7D7EDC5025861EFB00E17C13 /* Main.storyboard in Resources */, 162 | ); 163 | runOnlyForDeploymentPostprocessing = 0; 164 | }; 165 | /* End PBXResourcesBuildPhase section */ 166 | 167 | /* Begin PBXSourcesBuildPhase section */ 168 | 7D7EDC4125861EFB00E17C13 /* Sources */ = { 169 | isa = PBXSourcesBuildPhase; 170 | buildActionMask = 2147483647; 171 | files = ( 172 | 7D7EDC4D25861EFB00E17C13 /* ViewController.swift in Sources */, 173 | 7D7EDC4925861EFB00E17C13 /* AppDelegate.swift in Sources */, 174 | ); 175 | runOnlyForDeploymentPostprocessing = 0; 176 | }; 177 | /* End PBXSourcesBuildPhase section */ 178 | 179 | /* Begin PBXVariantGroup section */ 180 | 7D7EDC4E25861EFB00E17C13 /* Main.storyboard */ = { 181 | isa = PBXVariantGroup; 182 | children = ( 183 | 7D7EDC4F25861EFB00E17C13 /* Base */, 184 | ); 185 | name = Main.storyboard; 186 | sourceTree = ""; 187 | }; 188 | 7D7EDC5325861EFD00E17C13 /* LaunchScreen.storyboard */ = { 189 | isa = PBXVariantGroup; 190 | children = ( 191 | 7D7EDC5425861EFD00E17C13 /* Base */, 192 | ); 193 | name = LaunchScreen.storyboard; 194 | sourceTree = ""; 195 | }; 196 | /* End PBXVariantGroup section */ 197 | 198 | /* Begin XCBuildConfiguration section */ 199 | 7D7EDC5725861EFD00E17C13 /* Debug */ = { 200 | isa = XCBuildConfiguration; 201 | buildSettings = { 202 | ALWAYS_SEARCH_USER_PATHS = NO; 203 | CLANG_ANALYZER_NONNULL = YES; 204 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 205 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 206 | CLANG_CXX_LIBRARY = "libc++"; 207 | CLANG_ENABLE_MODULES = YES; 208 | CLANG_ENABLE_OBJC_ARC = YES; 209 | CLANG_ENABLE_OBJC_WEAK = YES; 210 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 211 | CLANG_WARN_BOOL_CONVERSION = YES; 212 | CLANG_WARN_COMMA = YES; 213 | CLANG_WARN_CONSTANT_CONVERSION = YES; 214 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 215 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 216 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 217 | CLANG_WARN_EMPTY_BODY = YES; 218 | CLANG_WARN_ENUM_CONVERSION = YES; 219 | CLANG_WARN_INFINITE_RECURSION = YES; 220 | CLANG_WARN_INT_CONVERSION = YES; 221 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 222 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 223 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 224 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 225 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 226 | CLANG_WARN_STRICT_PROTOTYPES = YES; 227 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 228 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 229 | CLANG_WARN_UNREACHABLE_CODE = YES; 230 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 231 | COPY_PHASE_STRIP = NO; 232 | DEBUG_INFORMATION_FORMAT = dwarf; 233 | ENABLE_STRICT_OBJC_MSGSEND = YES; 234 | ENABLE_TESTABILITY = YES; 235 | GCC_C_LANGUAGE_STANDARD = gnu11; 236 | GCC_DYNAMIC_NO_PIC = NO; 237 | GCC_NO_COMMON_BLOCKS = YES; 238 | GCC_OPTIMIZATION_LEVEL = 0; 239 | GCC_PREPROCESSOR_DEFINITIONS = ( 240 | "DEBUG=1", 241 | "$(inherited)", 242 | ); 243 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 244 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 245 | GCC_WARN_UNDECLARED_SELECTOR = YES; 246 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 247 | GCC_WARN_UNUSED_FUNCTION = YES; 248 | GCC_WARN_UNUSED_VARIABLE = YES; 249 | IPHONEOS_DEPLOYMENT_TARGET = 13.5; 250 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 251 | MTL_FAST_MATH = YES; 252 | ONLY_ACTIVE_ARCH = YES; 253 | SDKROOT = iphoneos; 254 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 255 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 256 | }; 257 | name = Debug; 258 | }; 259 | 7D7EDC5825861EFD00E17C13 /* Release */ = { 260 | isa = XCBuildConfiguration; 261 | buildSettings = { 262 | ALWAYS_SEARCH_USER_PATHS = NO; 263 | CLANG_ANALYZER_NONNULL = YES; 264 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 265 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 266 | CLANG_CXX_LIBRARY = "libc++"; 267 | CLANG_ENABLE_MODULES = YES; 268 | CLANG_ENABLE_OBJC_ARC = YES; 269 | CLANG_ENABLE_OBJC_WEAK = YES; 270 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 271 | CLANG_WARN_BOOL_CONVERSION = YES; 272 | CLANG_WARN_COMMA = YES; 273 | CLANG_WARN_CONSTANT_CONVERSION = YES; 274 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 275 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 276 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 277 | CLANG_WARN_EMPTY_BODY = YES; 278 | CLANG_WARN_ENUM_CONVERSION = YES; 279 | CLANG_WARN_INFINITE_RECURSION = YES; 280 | CLANG_WARN_INT_CONVERSION = YES; 281 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 282 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 283 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 284 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 285 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 286 | CLANG_WARN_STRICT_PROTOTYPES = YES; 287 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 288 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 289 | CLANG_WARN_UNREACHABLE_CODE = YES; 290 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 291 | COPY_PHASE_STRIP = NO; 292 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 293 | ENABLE_NS_ASSERTIONS = NO; 294 | ENABLE_STRICT_OBJC_MSGSEND = YES; 295 | GCC_C_LANGUAGE_STANDARD = gnu11; 296 | GCC_NO_COMMON_BLOCKS = YES; 297 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 298 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 299 | GCC_WARN_UNDECLARED_SELECTOR = YES; 300 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 301 | GCC_WARN_UNUSED_FUNCTION = YES; 302 | GCC_WARN_UNUSED_VARIABLE = YES; 303 | IPHONEOS_DEPLOYMENT_TARGET = 13.5; 304 | MTL_ENABLE_DEBUG_INFO = NO; 305 | MTL_FAST_MATH = YES; 306 | SDKROOT = iphoneos; 307 | SWIFT_COMPILATION_MODE = wholemodule; 308 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 309 | VALIDATE_PRODUCT = YES; 310 | }; 311 | name = Release; 312 | }; 313 | 7D7EDC5A25861EFD00E17C13 /* Debug */ = { 314 | isa = XCBuildConfiguration; 315 | buildSettings = { 316 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 317 | CODE_SIGN_STYLE = Automatic; 318 | INFOPLIST_FILE = UIKitApp/Info.plist; 319 | LD_RUNPATH_SEARCH_PATHS = ( 320 | "$(inherited)", 321 | "@executable_path/Frameworks", 322 | ); 323 | PRODUCT_BUNDLE_IDENTIFIER = com.MasterWatcher.UIKitApp; 324 | PRODUCT_NAME = "$(TARGET_NAME)"; 325 | SWIFT_VERSION = 5.0; 326 | TARGETED_DEVICE_FAMILY = "1,2"; 327 | }; 328 | name = Debug; 329 | }; 330 | 7D7EDC5B25861EFD00E17C13 /* Release */ = { 331 | isa = XCBuildConfiguration; 332 | buildSettings = { 333 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 334 | CODE_SIGN_STYLE = Automatic; 335 | INFOPLIST_FILE = UIKitApp/Info.plist; 336 | LD_RUNPATH_SEARCH_PATHS = ( 337 | "$(inherited)", 338 | "@executable_path/Frameworks", 339 | ); 340 | PRODUCT_BUNDLE_IDENTIFIER = com.MasterWatcher.UIKitApp; 341 | PRODUCT_NAME = "$(TARGET_NAME)"; 342 | SWIFT_VERSION = 5.0; 343 | TARGETED_DEVICE_FAMILY = "1,2"; 344 | }; 345 | name = Release; 346 | }; 347 | /* End XCBuildConfiguration section */ 348 | 349 | /* Begin XCConfigurationList section */ 350 | 7D7EDC4025861EFB00E17C13 /* Build configuration list for PBXProject "UIKitApp" */ = { 351 | isa = XCConfigurationList; 352 | buildConfigurations = ( 353 | 7D7EDC5725861EFD00E17C13 /* Debug */, 354 | 7D7EDC5825861EFD00E17C13 /* Release */, 355 | ); 356 | defaultConfigurationIsVisible = 0; 357 | defaultConfigurationName = Release; 358 | }; 359 | 7D7EDC5925861EFD00E17C13 /* Build configuration list for PBXNativeTarget "UIKitApp" */ = { 360 | isa = XCConfigurationList; 361 | buildConfigurations = ( 362 | 7D7EDC5A25861EFD00E17C13 /* Debug */, 363 | 7D7EDC5B25861EFD00E17C13 /* Release */, 364 | ); 365 | defaultConfigurationIsVisible = 0; 366 | defaultConfigurationName = Release; 367 | }; 368 | /* End XCConfigurationList section */ 369 | }; 370 | rootObject = 7D7EDC3D25861EFB00E17C13 /* Project object */; 371 | } 372 | -------------------------------------------------------------------------------- /UIKitApp/UIKitApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /UIKitApp/UIKitApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /UIKitApp/UIKitApp.xcodeproj/xcuserdata/antongoncharov.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | UIKitApp.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /UIKitApp/UIKitApp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // UIKitApp 4 | // 5 | // Created by Anton Goncharov on 13.12.2020. 6 | // Copyright © 2020 Anton Goncharov. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import UDF 11 | import AppModel 12 | 13 | @UIApplicationMain 14 | class AppDelegate: UIResponder, UIApplicationDelegate { 15 | 16 | var window: UIWindow? 17 | 18 | var store: Store = Store(state: FormState(), reducer: reduce) 19 | 20 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 21 | setupRootViewController() 22 | return true 23 | } 24 | 25 | private func setupRootViewController() { 26 | let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as! ViewController 27 | viewController.store = store 28 | 29 | let navigatonController = UINavigationController() 30 | navigatonController.viewControllers = [viewController] 31 | 32 | window = UIWindow() 33 | window?.rootViewController = navigatonController 34 | window?.makeKeyAndVisible() 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /UIKitApp/UIKitApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /UIKitApp/UIKitApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /UIKitApp/UIKitApp/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 | -------------------------------------------------------------------------------- /UIKitApp/UIKitApp/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 | 26 | 35 | 36 | 37 | 38 | 39 | 40 | 49 | 50 | 51 | 52 | 53 | 54 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /UIKitApp/UIKitApp/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /UIKitApp/UIKitApp/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // UDFExample 4 | // 5 | // Created by Anton Goncharov on 24.11.2020. 6 | // 7 | 8 | import UIKit 9 | import UDF 10 | import AppModel 11 | 12 | class ViewController: UIViewController { 13 | 14 | var store: Store! 15 | var subscription: UUID? 16 | 17 | @IBOutlet weak var nameTextField: UITextField! 18 | @IBOutlet weak var nameErrorLabel: UILabel! 19 | 20 | @IBOutlet weak var pincodeTextField: UITextField! 21 | @IBOutlet weak var pincodeErrorLabel: UILabel! 22 | 23 | @IBOutlet weak var dogNameTextField: UITextField! 24 | @IBOutlet weak var dogNameErrorLabel: UILabel! 25 | 26 | @IBOutlet weak var saveButton: UIBarButtonItem! 27 | 28 | deinit { 29 | subscription = nil 30 | } 31 | 32 | override func viewDidLoad() { 33 | super.viewDidLoad() 34 | 35 | nameTextField.addTarget(self, action: #selector(nameTextFieldDidChange), for: .editingChanged) 36 | pincodeTextField.addTarget(self, action: #selector(pincodeTextFieldDidChange), for: .editingChanged) 37 | dogNameTextField.addTarget(self, action: #selector(dogNameTextFieldDidChange), for: .editingChanged) 38 | 39 | subscription = store.subscribe { [weak self] state in 40 | self?.render(state) 41 | } 42 | } 43 | 44 | private func render(_ state: FormState) { 45 | nameTextField.text = state.name.value 46 | render(status: state.name.status, to: nameErrorLabel) 47 | 48 | pincodeTextField.text = state.pincode.value 49 | render(status: state.pincode.status, to: pincodeErrorLabel) 50 | 51 | dogNameTextField.text = state.dogName.value 52 | render(status: state.dogName.status, to: dogNameErrorLabel) 53 | 54 | saveButton.isEnabled = state.isValidForm 55 | } 56 | 57 | private func render(status: FieldStatus, to label: UILabel) { 58 | switch status { 59 | case .default, .valid: 60 | label.isHidden = true 61 | case let .tooShort(minLength): 62 | label.text = "Minimum \(minLength) characters" 63 | label.isHidden = false 64 | case let .tooLong(maxLength): 65 | label.text = "Maximum \(maxLength) characters" 66 | label.isHidden = false 67 | case .numbersOnly: 68 | label.text = "Only numbers allowed" 69 | label.isHidden = false 70 | } 71 | } 72 | 73 | @objc private func nameTextFieldDidChange(_ textField: UITextField) { 74 | store.dispatch(Actions.nameDidChange(textField.text)) 75 | } 76 | 77 | @objc private func pincodeTextFieldDidChange(_ textField: UITextField) { 78 | store.dispatch(Actions.pincodeDidChange(textField.text)) 79 | } 80 | 81 | @objc private func dogNameTextFieldDidChange(_ textField: UITextField) { 82 | store.dispatch(Actions.dogNameDidChange(textField.text)) 83 | } 84 | } 85 | --------------------------------------------------------------------------------