├── .gitignore ├── DataConvertible.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── DataConvertible.xcscheme │ └── DataConvertibleTests.xcscheme ├── DataConvertible ├── DataConvertible.h ├── DataConvertible.swift ├── DataConvertibleStore.swift ├── Info.plist └── UserDefaults+.swift ├── DataConvertibleTests ├── DataConvertibleTests.swift ├── Info.plist ├── Resources │ └── UserProfileViewController.storyboard └── UserDefaultsTests.swift ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | ### https://raw.github.com/github/gitignore/e6dd3a81e6037cc923e503e372c80326f65ccb25/Global/macos.gitignore 2 | 3 | *.DS_Store 4 | .AppleDouble 5 | .LSOverride 6 | 7 | # Icon must end with two \r 8 | Icon 9 | 10 | 11 | # Thumbnails 12 | ._* 13 | 14 | # Files that might appear in the root of a volume 15 | .DocumentRevisions-V100 16 | .fseventsd 17 | .Spotlight-V100 18 | .TemporaryItems 19 | .Trashes 20 | .VolumeIcon.icns 21 | .com.apple.timemachine.donotpresent 22 | 23 | # Directories potentially created on remote AFP share 24 | .AppleDB 25 | .AppleDesktop 26 | Network Trash Folder 27 | Temporary Items 28 | .apdisk 29 | 30 | 31 | ### https://raw.github.com/github/gitignore/e6dd3a81e6037cc923e503e372c80326f65ccb25/Global/xcode.gitignore 32 | 33 | # Xcode 34 | # 35 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 36 | 37 | ## Build generated 38 | build/ 39 | DerivedData/ 40 | 41 | ## Various settings 42 | *.pbxuser 43 | !default.pbxuser 44 | *.mode1v3 45 | !default.mode1v3 46 | *.mode2v3 47 | !default.mode2v3 48 | *.perspectivev3 49 | !default.perspectivev3 50 | xcuserdata/ 51 | 52 | ## Other 53 | *.moved-aside 54 | *.xccheckout 55 | *.xcscmblueprint 56 | UserInterfaceState.xcuserstate 57 | 58 | #Carthage/Build 59 | Carthage 60 | 61 | -------------------------------------------------------------------------------- /DataConvertible.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 24028DCE20484ABD00721297 /* DataConvertibleStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24028DCD20484ABD00721297 /* DataConvertibleStore.swift */; }; 11 | 242FC79D2025DB0600D8F92A /* UserProfileViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 242FC79C2025DB0600D8F92A /* UserProfileViewController.storyboard */; }; 12 | 249298192025B52600A1EF37 /* DataConvertible.h in Headers */ = {isa = PBXBuildFile; fileRef = 249298172025B52600A1EF37 /* DataConvertible.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13 | 249298202025B5BC00A1EF37 /* DataConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2492981F2025B5BC00A1EF37 /* DataConvertible.swift */; }; 14 | 249298282025B5DC00A1EF37 /* DataConvertibleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 249298272025B5DC00A1EF37 /* DataConvertibleTests.swift */; }; 15 | 2492982A2025B5DC00A1EF37 /* DataConvertible.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 249298142025B52600A1EF37 /* DataConvertible.framework */; }; 16 | 249298312025BAF300A1EF37 /* UserDefaults+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 249298302025BAF300A1EF37 /* UserDefaults+.swift */; }; 17 | 249298332025BB3300A1EF37 /* UserDefaultsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 249298322025BB3300A1EF37 /* UserDefaultsTests.swift */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXContainerItemProxy section */ 21 | 2492982B2025B5DC00A1EF37 /* PBXContainerItemProxy */ = { 22 | isa = PBXContainerItemProxy; 23 | containerPortal = 2492980B2025B52600A1EF37 /* Project object */; 24 | proxyType = 1; 25 | remoteGlobalIDString = 249298132025B52600A1EF37; 26 | remoteInfo = DataConvertible; 27 | }; 28 | /* End PBXContainerItemProxy section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | 24028DCD20484ABD00721297 /* DataConvertibleStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataConvertibleStore.swift; sourceTree = ""; }; 32 | 242FC79C2025DB0600D8F92A /* UserProfileViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = UserProfileViewController.storyboard; sourceTree = ""; }; 33 | 249298142025B52600A1EF37 /* DataConvertible.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DataConvertible.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | 249298172025B52600A1EF37 /* DataConvertible.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataConvertible.h; sourceTree = ""; }; 35 | 249298182025B52600A1EF37 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 36 | 2492981F2025B5BC00A1EF37 /* DataConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataConvertible.swift; sourceTree = ""; }; 37 | 249298252025B5DC00A1EF37 /* DataConvertibleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DataConvertibleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 249298272025B5DC00A1EF37 /* DataConvertibleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataConvertibleTests.swift; sourceTree = ""; }; 39 | 249298292025B5DC00A1EF37 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | 249298302025BAF300A1EF37 /* UserDefaults+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+.swift"; sourceTree = ""; }; 41 | 249298322025BB3300A1EF37 /* UserDefaultsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsTests.swift; sourceTree = ""; }; 42 | /* End PBXFileReference section */ 43 | 44 | /* Begin PBXFrameworksBuildPhase section */ 45 | 249298102025B52600A1EF37 /* Frameworks */ = { 46 | isa = PBXFrameworksBuildPhase; 47 | buildActionMask = 2147483647; 48 | files = ( 49 | ); 50 | runOnlyForDeploymentPostprocessing = 0; 51 | }; 52 | 249298222025B5DC00A1EF37 /* Frameworks */ = { 53 | isa = PBXFrameworksBuildPhase; 54 | buildActionMask = 2147483647; 55 | files = ( 56 | 2492982A2025B5DC00A1EF37 /* DataConvertible.framework in Frameworks */, 57 | ); 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | /* End PBXFrameworksBuildPhase section */ 61 | 62 | /* Begin PBXGroup section */ 63 | 242FC79B2025DAF800D8F92A /* Resources */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 242FC79C2025DB0600D8F92A /* UserProfileViewController.storyboard */, 67 | ); 68 | path = Resources; 69 | sourceTree = ""; 70 | }; 71 | 2492980A2025B52600A1EF37 = { 72 | isa = PBXGroup; 73 | children = ( 74 | 249298162025B52600A1EF37 /* DataConvertible */, 75 | 249298262025B5DC00A1EF37 /* DataConvertibleTests */, 76 | 249298152025B52600A1EF37 /* Products */, 77 | ); 78 | sourceTree = ""; 79 | }; 80 | 249298152025B52600A1EF37 /* Products */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 249298142025B52600A1EF37 /* DataConvertible.framework */, 84 | 249298252025B5DC00A1EF37 /* DataConvertibleTests.xctest */, 85 | ); 86 | name = Products; 87 | sourceTree = ""; 88 | }; 89 | 249298162025B52600A1EF37 /* DataConvertible */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 249298172025B52600A1EF37 /* DataConvertible.h */, 93 | 249298182025B52600A1EF37 /* Info.plist */, 94 | 2492981F2025B5BC00A1EF37 /* DataConvertible.swift */, 95 | 24028DCD20484ABD00721297 /* DataConvertibleStore.swift */, 96 | 249298302025BAF300A1EF37 /* UserDefaults+.swift */, 97 | ); 98 | path = DataConvertible; 99 | sourceTree = ""; 100 | }; 101 | 249298262025B5DC00A1EF37 /* DataConvertibleTests */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 242FC79B2025DAF800D8F92A /* Resources */, 105 | 249298272025B5DC00A1EF37 /* DataConvertibleTests.swift */, 106 | 249298322025BB3300A1EF37 /* UserDefaultsTests.swift */, 107 | 249298292025B5DC00A1EF37 /* Info.plist */, 108 | ); 109 | path = DataConvertibleTests; 110 | sourceTree = ""; 111 | }; 112 | /* End PBXGroup section */ 113 | 114 | /* Begin PBXHeadersBuildPhase section */ 115 | 249298112025B52600A1EF37 /* Headers */ = { 116 | isa = PBXHeadersBuildPhase; 117 | buildActionMask = 2147483647; 118 | files = ( 119 | 249298192025B52600A1EF37 /* DataConvertible.h in Headers */, 120 | ); 121 | runOnlyForDeploymentPostprocessing = 0; 122 | }; 123 | /* End PBXHeadersBuildPhase section */ 124 | 125 | /* Begin PBXNativeTarget section */ 126 | 249298132025B52600A1EF37 /* DataConvertible */ = { 127 | isa = PBXNativeTarget; 128 | buildConfigurationList = 2492981C2025B52600A1EF37 /* Build configuration list for PBXNativeTarget "DataConvertible" */; 129 | buildPhases = ( 130 | 2492980F2025B52600A1EF37 /* Sources */, 131 | 249298102025B52600A1EF37 /* Frameworks */, 132 | 249298112025B52600A1EF37 /* Headers */, 133 | 249298122025B52600A1EF37 /* Resources */, 134 | ); 135 | buildRules = ( 136 | ); 137 | dependencies = ( 138 | ); 139 | name = DataConvertible; 140 | productName = DataConvertible; 141 | productReference = 249298142025B52600A1EF37 /* DataConvertible.framework */; 142 | productType = "com.apple.product-type.framework"; 143 | }; 144 | 249298242025B5DC00A1EF37 /* DataConvertibleTests */ = { 145 | isa = PBXNativeTarget; 146 | buildConfigurationList = 2492982D2025B5DC00A1EF37 /* Build configuration list for PBXNativeTarget "DataConvertibleTests" */; 147 | buildPhases = ( 148 | 249298212025B5DC00A1EF37 /* Sources */, 149 | 249298222025B5DC00A1EF37 /* Frameworks */, 150 | 249298232025B5DC00A1EF37 /* Resources */, 151 | ); 152 | buildRules = ( 153 | ); 154 | dependencies = ( 155 | 2492982C2025B5DC00A1EF37 /* PBXTargetDependency */, 156 | ); 157 | name = DataConvertibleTests; 158 | productName = DataConvertibleTests; 159 | productReference = 249298252025B5DC00A1EF37 /* DataConvertibleTests.xctest */; 160 | productType = "com.apple.product-type.bundle.unit-test"; 161 | }; 162 | /* End PBXNativeTarget section */ 163 | 164 | /* Begin PBXProject section */ 165 | 2492980B2025B52600A1EF37 /* Project object */ = { 166 | isa = PBXProject; 167 | attributes = { 168 | LastSwiftUpdateCheck = 0920; 169 | LastUpgradeCheck = 0920; 170 | ORGANIZATIONNAME = tattn; 171 | TargetAttributes = { 172 | 249298132025B52600A1EF37 = { 173 | CreatedOnToolsVersion = 9.2; 174 | LastSwiftMigration = 0920; 175 | ProvisioningStyle = Automatic; 176 | }; 177 | 249298242025B5DC00A1EF37 = { 178 | CreatedOnToolsVersion = 9.2; 179 | ProvisioningStyle = Automatic; 180 | }; 181 | }; 182 | }; 183 | buildConfigurationList = 2492980E2025B52600A1EF37 /* Build configuration list for PBXProject "DataConvertible" */; 184 | compatibilityVersion = "Xcode 8.0"; 185 | developmentRegion = en; 186 | hasScannedForEncodings = 0; 187 | knownRegions = ( 188 | en, 189 | ); 190 | mainGroup = 2492980A2025B52600A1EF37; 191 | productRefGroup = 249298152025B52600A1EF37 /* Products */; 192 | projectDirPath = ""; 193 | projectRoot = ""; 194 | targets = ( 195 | 249298132025B52600A1EF37 /* DataConvertible */, 196 | 249298242025B5DC00A1EF37 /* DataConvertibleTests */, 197 | ); 198 | }; 199 | /* End PBXProject section */ 200 | 201 | /* Begin PBXResourcesBuildPhase section */ 202 | 249298122025B52600A1EF37 /* Resources */ = { 203 | isa = PBXResourcesBuildPhase; 204 | buildActionMask = 2147483647; 205 | files = ( 206 | ); 207 | runOnlyForDeploymentPostprocessing = 0; 208 | }; 209 | 249298232025B5DC00A1EF37 /* Resources */ = { 210 | isa = PBXResourcesBuildPhase; 211 | buildActionMask = 2147483647; 212 | files = ( 213 | 242FC79D2025DB0600D8F92A /* UserProfileViewController.storyboard in Resources */, 214 | ); 215 | runOnlyForDeploymentPostprocessing = 0; 216 | }; 217 | /* End PBXResourcesBuildPhase section */ 218 | 219 | /* Begin PBXSourcesBuildPhase section */ 220 | 2492980F2025B52600A1EF37 /* Sources */ = { 221 | isa = PBXSourcesBuildPhase; 222 | buildActionMask = 2147483647; 223 | files = ( 224 | 24028DCE20484ABD00721297 /* DataConvertibleStore.swift in Sources */, 225 | 249298312025BAF300A1EF37 /* UserDefaults+.swift in Sources */, 226 | 249298202025B5BC00A1EF37 /* DataConvertible.swift in Sources */, 227 | ); 228 | runOnlyForDeploymentPostprocessing = 0; 229 | }; 230 | 249298212025B5DC00A1EF37 /* Sources */ = { 231 | isa = PBXSourcesBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | 249298332025BB3300A1EF37 /* UserDefaultsTests.swift in Sources */, 235 | 249298282025B5DC00A1EF37 /* DataConvertibleTests.swift in Sources */, 236 | ); 237 | runOnlyForDeploymentPostprocessing = 0; 238 | }; 239 | /* End PBXSourcesBuildPhase section */ 240 | 241 | /* Begin PBXTargetDependency section */ 242 | 2492982C2025B5DC00A1EF37 /* PBXTargetDependency */ = { 243 | isa = PBXTargetDependency; 244 | target = 249298132025B52600A1EF37 /* DataConvertible */; 245 | targetProxy = 2492982B2025B5DC00A1EF37 /* PBXContainerItemProxy */; 246 | }; 247 | /* End PBXTargetDependency section */ 248 | 249 | /* Begin XCBuildConfiguration section */ 250 | 2492981A2025B52600A1EF37 /* Debug */ = { 251 | isa = XCBuildConfiguration; 252 | buildSettings = { 253 | ALWAYS_SEARCH_USER_PATHS = NO; 254 | CLANG_ANALYZER_NONNULL = YES; 255 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 256 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 257 | CLANG_CXX_LIBRARY = "libc++"; 258 | CLANG_ENABLE_MODULES = YES; 259 | CLANG_ENABLE_OBJC_ARC = YES; 260 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 261 | CLANG_WARN_BOOL_CONVERSION = YES; 262 | CLANG_WARN_COMMA = YES; 263 | CLANG_WARN_CONSTANT_CONVERSION = YES; 264 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 265 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 266 | CLANG_WARN_EMPTY_BODY = YES; 267 | CLANG_WARN_ENUM_CONVERSION = YES; 268 | CLANG_WARN_INFINITE_RECURSION = YES; 269 | CLANG_WARN_INT_CONVERSION = YES; 270 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 271 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 272 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 273 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 274 | CLANG_WARN_STRICT_PROTOTYPES = YES; 275 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 276 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 277 | CLANG_WARN_UNREACHABLE_CODE = YES; 278 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 279 | CODE_SIGN_IDENTITY = "iPhone Developer"; 280 | COPY_PHASE_STRIP = NO; 281 | CURRENT_PROJECT_VERSION = 1; 282 | DEBUG_INFORMATION_FORMAT = dwarf; 283 | ENABLE_STRICT_OBJC_MSGSEND = YES; 284 | ENABLE_TESTABILITY = YES; 285 | GCC_C_LANGUAGE_STANDARD = gnu11; 286 | GCC_DYNAMIC_NO_PIC = NO; 287 | GCC_NO_COMMON_BLOCKS = YES; 288 | GCC_OPTIMIZATION_LEVEL = 0; 289 | GCC_PREPROCESSOR_DEFINITIONS = ( 290 | "DEBUG=1", 291 | "$(inherited)", 292 | ); 293 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 294 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 295 | GCC_WARN_UNDECLARED_SELECTOR = YES; 296 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 297 | GCC_WARN_UNUSED_FUNCTION = YES; 298 | GCC_WARN_UNUSED_VARIABLE = YES; 299 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 300 | MTL_ENABLE_DEBUG_INFO = YES; 301 | ONLY_ACTIVE_ARCH = YES; 302 | SDKROOT = iphoneos; 303 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 304 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 305 | VERSIONING_SYSTEM = "apple-generic"; 306 | VERSION_INFO_PREFIX = ""; 307 | }; 308 | name = Debug; 309 | }; 310 | 2492981B2025B52600A1EF37 /* Release */ = { 311 | isa = XCBuildConfiguration; 312 | buildSettings = { 313 | ALWAYS_SEARCH_USER_PATHS = NO; 314 | CLANG_ANALYZER_NONNULL = YES; 315 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 316 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 317 | CLANG_CXX_LIBRARY = "libc++"; 318 | CLANG_ENABLE_MODULES = YES; 319 | CLANG_ENABLE_OBJC_ARC = YES; 320 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 321 | CLANG_WARN_BOOL_CONVERSION = YES; 322 | CLANG_WARN_COMMA = YES; 323 | CLANG_WARN_CONSTANT_CONVERSION = YES; 324 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 325 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 326 | CLANG_WARN_EMPTY_BODY = YES; 327 | CLANG_WARN_ENUM_CONVERSION = YES; 328 | CLANG_WARN_INFINITE_RECURSION = YES; 329 | CLANG_WARN_INT_CONVERSION = YES; 330 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 331 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 332 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 333 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 334 | CLANG_WARN_STRICT_PROTOTYPES = YES; 335 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 336 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 337 | CLANG_WARN_UNREACHABLE_CODE = YES; 338 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 339 | CODE_SIGN_IDENTITY = "iPhone Developer"; 340 | COPY_PHASE_STRIP = NO; 341 | CURRENT_PROJECT_VERSION = 1; 342 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 343 | ENABLE_NS_ASSERTIONS = NO; 344 | ENABLE_STRICT_OBJC_MSGSEND = YES; 345 | GCC_C_LANGUAGE_STANDARD = gnu11; 346 | GCC_NO_COMMON_BLOCKS = YES; 347 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 348 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 349 | GCC_WARN_UNDECLARED_SELECTOR = YES; 350 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 351 | GCC_WARN_UNUSED_FUNCTION = YES; 352 | GCC_WARN_UNUSED_VARIABLE = YES; 353 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 354 | MTL_ENABLE_DEBUG_INFO = NO; 355 | SDKROOT = iphoneos; 356 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 357 | VALIDATE_PRODUCT = YES; 358 | VERSIONING_SYSTEM = "apple-generic"; 359 | VERSION_INFO_PREFIX = ""; 360 | }; 361 | name = Release; 362 | }; 363 | 2492981D2025B52600A1EF37 /* Debug */ = { 364 | isa = XCBuildConfiguration; 365 | buildSettings = { 366 | CLANG_ENABLE_MODULES = YES; 367 | CODE_SIGN_IDENTITY = ""; 368 | CODE_SIGN_STYLE = Automatic; 369 | DEFINES_MODULE = YES; 370 | DYLIB_COMPATIBILITY_VERSION = 1; 371 | DYLIB_CURRENT_VERSION = 1; 372 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 373 | INFOPLIST_FILE = DataConvertible/Info.plist; 374 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 375 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 376 | PRODUCT_BUNDLE_IDENTIFIER = com.github.tattn.DataConvertible; 377 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 378 | SKIP_INSTALL = YES; 379 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 380 | SWIFT_VERSION = 4.0; 381 | TARGETED_DEVICE_FAMILY = "1,2"; 382 | }; 383 | name = Debug; 384 | }; 385 | 2492981E2025B52600A1EF37 /* Release */ = { 386 | isa = XCBuildConfiguration; 387 | buildSettings = { 388 | CLANG_ENABLE_MODULES = YES; 389 | CODE_SIGN_IDENTITY = ""; 390 | CODE_SIGN_STYLE = Automatic; 391 | DEFINES_MODULE = YES; 392 | DYLIB_COMPATIBILITY_VERSION = 1; 393 | DYLIB_CURRENT_VERSION = 1; 394 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 395 | INFOPLIST_FILE = DataConvertible/Info.plist; 396 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 397 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 398 | PRODUCT_BUNDLE_IDENTIFIER = com.github.tattn.DataConvertible; 399 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 400 | SKIP_INSTALL = YES; 401 | SWIFT_VERSION = 4.0; 402 | TARGETED_DEVICE_FAMILY = "1,2"; 403 | }; 404 | name = Release; 405 | }; 406 | 2492982E2025B5DC00A1EF37 /* Debug */ = { 407 | isa = XCBuildConfiguration; 408 | buildSettings = { 409 | CODE_SIGN_STYLE = Automatic; 410 | INFOPLIST_FILE = DataConvertibleTests/Info.plist; 411 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 412 | PRODUCT_BUNDLE_IDENTIFIER = com.github.tattn.DataConvertibleTests; 413 | PRODUCT_NAME = "$(TARGET_NAME)"; 414 | SWIFT_VERSION = 4.0; 415 | TARGETED_DEVICE_FAMILY = "1,2"; 416 | }; 417 | name = Debug; 418 | }; 419 | 2492982F2025B5DC00A1EF37 /* Release */ = { 420 | isa = XCBuildConfiguration; 421 | buildSettings = { 422 | CODE_SIGN_STYLE = Automatic; 423 | INFOPLIST_FILE = DataConvertibleTests/Info.plist; 424 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 425 | PRODUCT_BUNDLE_IDENTIFIER = com.github.tattn.DataConvertibleTests; 426 | PRODUCT_NAME = "$(TARGET_NAME)"; 427 | SWIFT_VERSION = 4.0; 428 | TARGETED_DEVICE_FAMILY = "1,2"; 429 | }; 430 | name = Release; 431 | }; 432 | /* End XCBuildConfiguration section */ 433 | 434 | /* Begin XCConfigurationList section */ 435 | 2492980E2025B52600A1EF37 /* Build configuration list for PBXProject "DataConvertible" */ = { 436 | isa = XCConfigurationList; 437 | buildConfigurations = ( 438 | 2492981A2025B52600A1EF37 /* Debug */, 439 | 2492981B2025B52600A1EF37 /* Release */, 440 | ); 441 | defaultConfigurationIsVisible = 0; 442 | defaultConfigurationName = Release; 443 | }; 444 | 2492981C2025B52600A1EF37 /* Build configuration list for PBXNativeTarget "DataConvertible" */ = { 445 | isa = XCConfigurationList; 446 | buildConfigurations = ( 447 | 2492981D2025B52600A1EF37 /* Debug */, 448 | 2492981E2025B52600A1EF37 /* Release */, 449 | ); 450 | defaultConfigurationIsVisible = 0; 451 | defaultConfigurationName = Release; 452 | }; 453 | 2492982D2025B5DC00A1EF37 /* Build configuration list for PBXNativeTarget "DataConvertibleTests" */ = { 454 | isa = XCConfigurationList; 455 | buildConfigurations = ( 456 | 2492982E2025B5DC00A1EF37 /* Debug */, 457 | 2492982F2025B5DC00A1EF37 /* Release */, 458 | ); 459 | defaultConfigurationIsVisible = 0; 460 | defaultConfigurationName = Release; 461 | }; 462 | /* End XCConfigurationList section */ 463 | }; 464 | rootObject = 2492980B2025B52600A1EF37 /* Project object */; 465 | } 466 | -------------------------------------------------------------------------------- /DataConvertible.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DataConvertible.xcodeproj/xcshareddata/xcschemes/DataConvertible.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 34 | 40 | 41 | 42 | 43 | 44 | 50 | 51 | 52 | 53 | 54 | 55 | 66 | 67 | 73 | 74 | 75 | 76 | 77 | 78 | 84 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /DataConvertible.xcodeproj/xcshareddata/xcschemes/DataConvertibleTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 16 | 18 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 41 | 42 | 43 | 44 | 50 | 51 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /DataConvertible/DataConvertible.h: -------------------------------------------------------------------------------- 1 | // 2 | // DataConvertible.h 3 | // DataConvertible 4 | // 5 | // Created by Tatsuya Tanaka on 20180203. 6 | // Copyright © 2018年 tattn. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for DataConvertible. 12 | FOUNDATION_EXPORT double DataConvertibleVersionNumber; 13 | 14 | //! Project version string for DataConvertible. 15 | FOUNDATION_EXPORT const unsigned char DataConvertibleVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /DataConvertible/DataConvertible.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataConvertible.swift 3 | // DataConvertible 4 | // 5 | // Created by Tatsuya Tanaka on 20180203. 6 | // Copyright © 2018年 tattn. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol DataConvertible { 12 | init(data: Data) throws 13 | func convertToData() throws -> Data 14 | } 15 | 16 | public extension DataConvertible where Self: Decodable { 17 | init(data: Data) throws { 18 | self = try JSONDecoder().decode(Self.self, from: data) 19 | } 20 | } 21 | 22 | public extension DataConvertible where Self: Encodable { 23 | func convertToData() throws -> Data { 24 | return try JSONEncoder().encode(self) 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /DataConvertible/DataConvertibleStore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataConvertibleStore.swift 3 | // DataConvertible 4 | // 5 | // Created by Tatsuya Tanaka on 20180301. 6 | // Copyright © 2018年 tattn. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol DataConvertibleStore { 12 | func set(_ value: DataConvertible, forKey key: String) throws 13 | func value(_ type: T.Type, forKey key: String) -> T? 14 | } 15 | -------------------------------------------------------------------------------- /DataConvertible/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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /DataConvertible/UserDefaults+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserDefaults+.swift 3 | // DataConvertible 4 | // 5 | // Created by Tatsuya Tanaka on 20180203. 6 | // Copyright © 2018年 tattn. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension UserDefaults: DataConvertibleStore { 12 | public func set(_ value: DataConvertible, forKey key: String) throws { 13 | let data = try value.convertToData() 14 | set(data, forKey: key) 15 | } 16 | 17 | public func value(_ type: T.Type = T.self, forKey key: String) -> T? { 18 | let data = self.data(forKey: key) 19 | let value: T?? = try? data.map(T.init) 20 | return value.flatMap { $0 } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /DataConvertibleTests/DataConvertibleTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataConvertibleTests.swift 3 | // DataConvertibleTests 4 | // 5 | // Created by Tatsuya Tanaka on 20180203. 6 | // Copyright © 2018年 tattn. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import DataConvertible 11 | 12 | class DataConvertibleTests: XCTestCase { 13 | 14 | struct Model: Codable, DataConvertible { 15 | let string: String 16 | let int: Int 17 | } 18 | 19 | override func setUp() { 20 | super.setUp() 21 | } 22 | 23 | override func tearDown() { 24 | super.tearDown() 25 | } 26 | 27 | func testEncodeAndDecode() throws { 28 | let model = Model(string: "abc", int: 123) 29 | let data = try model.convertToData() 30 | let decoded = try Model(data: data) 31 | XCTAssertEqual(model.string, decoded.string) 32 | XCTAssertEqual(model.int, decoded.int) 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /DataConvertibleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /DataConvertibleTests/Resources/UserProfileViewController.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /DataConvertibleTests/UserDefaultsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserDefaultsTests.swift 3 | // DataConvertibleTests 4 | // 5 | // Created by Tatsuya Tanaka on 20180203. 6 | // Copyright © 2018年 tattn. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import DataConvertible 11 | 12 | class UserDefaultsTests: XCTestCase { 13 | 14 | private let userDefaults = UserDefaults.standard 15 | 16 | struct Model: Codable, DataConvertible { 17 | let string: String 18 | let int: Int 19 | } 20 | 21 | override func setUp() { 22 | super.setUp() 23 | } 24 | 25 | override func tearDown() { 26 | super.tearDown() 27 | } 28 | 29 | func testSetAndGet() throws { 30 | let model = Model(string: "abc", int: 123) 31 | try userDefaults.set(model, forKey: "model") 32 | let _model = userDefaults.value(Model.self, forKey: "model")! 33 | XCTAssertEqual(_model.string, model.string) 34 | XCTAssertEqual(_model.int, model.int) 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Tatsuya Tanaka 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DataConvertible 2 | === 3 | 4 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 5 | [![Swift Version](https://img.shields.io/badge/Swift-4-F16D39.svg)](https://developer.apple.com/swift) 6 | 7 | DataConvertible is a support library for converting models to `Data`. 8 | 9 | # How to use 10 | 11 | ## Encode / Decode 12 | 13 | ```swift 14 | struct Model: Codable, DataConvertible { 15 | let string: String 16 | let int: Int 17 | } 18 | 19 | let model = Model(string: "abc", int: 123) 20 | let data: Data = try model.convertToData() 21 | let decoded: Model = try Model(data: data) 22 | ``` 23 | 24 | ## Save to UserDefaults / Get from UserDefaults 25 | 26 | ```swift 27 | let model = Model(string: "abc", int: 123) 28 | try userDefaults.set(model, forKey: "model") 29 | let saved: Model? = userDefaults.value(Model.self, forKey: "model") 30 | ``` 31 | 32 | ## Adapt to other data store type 33 | 34 | ```swift 35 | // e.g. Keychain 36 | struct Keychain { /* implementation */ } 37 | 38 | extension Keychain: DataConvertibleStore { 39 | public func set(_ value: DataConvertible, forKey key: String) throws { 40 | // store the value 41 | } 42 | 43 | public func value(_ type: T.Type = T.self, forKey key: String) -> T? { 44 | // get the value by the key 45 | } 46 | 47 | } 48 | ``` 49 | 50 | 51 | ## Conform to DataConvertible 52 | 53 | ```swift 54 | extension YourClass: DataConvertible { 55 | init(data: Data) throws { 56 | // initialize form Data 57 | } 58 | 59 | func convertToData() throws -> Data { 60 | // convert to data 61 | } 62 | } 63 | ``` 64 | 65 | If your class conforms to Codable, the class can conform to DataConvertible without any additional implementation. 66 | 67 | # Installation 68 | 69 | ## Carthage 70 | 71 | ```ruby 72 | github "tattn/DataConvertible" 73 | ``` 74 | 75 | # Contributing 76 | 77 | 1. Fork it! 78 | 2. Create your feature branch: `git checkout -b my-new-feature` 79 | 3. Commit your changes: `git commit -am 'Add some feature'` 80 | 4. Push to the branch: `git push origin my-new-feature` 81 | 5. Submit a pull request :D 82 | 83 | # License 84 | 85 | DataConvertible is released under the MIT license. See LICENSE for details. 86 | --------------------------------------------------------------------------------