├── PerfectSetup ├── PerfectProject.xcodeproj │ ├── project.pbxproj │ ├── xcshareddata │ │ └── xcschemes │ │ │ └── PerfectProject.xcscheme │ └── xcuserdata │ │ └── nichrago.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── PerfectProject │ ├── Info.plist │ ├── PerfectHandlers.swift │ └── PerfectProject.h └── PerfectProjectTests │ ├── Info.plist │ └── PerfectProjectTests.swift └── README.md /PerfectSetup/PerfectProject.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 670138EA1CD906BD004F6756 /* PerfectProject.h in Headers */ = {isa = PBXBuildFile; fileRef = 670138E91CD906BD004F6756 /* PerfectProject.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 670138F11CD906BE004F6756 /* PerfectProject.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 670138E61CD906BD004F6756 /* PerfectProject.framework */; }; 12 | 670138F61CD906BE004F6756 /* PerfectProjectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 670138F51CD906BE004F6756 /* PerfectProjectTests.swift */; }; 13 | 670139011CD906E4004F6756 /* PerfectLib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 670139001CD906E4004F6756 /* PerfectLib.framework */; }; 14 | 670139031CD90767004F6756 /* PerfectHandlers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 670139021CD90767004F6756 /* PerfectHandlers.swift */; }; 15 | 6731B3EE1CDAB184000CB252 /* MySQL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6731B3ED1CDAB184000CB252 /* MySQL.framework */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXContainerItemProxy section */ 19 | 670138F21CD906BE004F6756 /* PBXContainerItemProxy */ = { 20 | isa = PBXContainerItemProxy; 21 | containerPortal = 670138DD1CD906BD004F6756 /* Project object */; 22 | proxyType = 1; 23 | remoteGlobalIDString = 670138E51CD906BD004F6756; 24 | remoteInfo = PerfectProject; 25 | }; 26 | /* End PBXContainerItemProxy section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 670138E61CD906BD004F6756 /* PerfectProject.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PerfectProject.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 670138E91CD906BD004F6756 /* PerfectProject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PerfectProject.h; sourceTree = ""; }; 31 | 670138EB1CD906BD004F6756 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32 | 670138F01CD906BE004F6756 /* PerfectProjectTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PerfectProjectTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | 670138F51CD906BE004F6756 /* PerfectProjectTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PerfectProjectTests.swift; sourceTree = ""; }; 34 | 670138F71CD906BE004F6756 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 35 | 670139001CD906E4004F6756 /* PerfectLib.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PerfectLib.framework; path = "../../../Library/Developer/Xcode/DerivedData/PerfectTestSpace-foraxypqkpbceagphnpfqmgqgpca/Build/Products/Debug/PerfectLib.framework"; sourceTree = ""; }; 36 | 670139021CD90767004F6756 /* PerfectHandlers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PerfectHandlers.swift; sourceTree = ""; }; 37 | 6731B3ED1CDAB184000CB252 /* MySQL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MySQL.framework; path = "../../../Library/Developer/Xcode/DerivedData/PerfectTestSpace-foraxypqkpbceagphnpfqmgqgpca/Build/Products/Debug/MySQL.framework"; sourceTree = ""; }; 38 | /* End PBXFileReference section */ 39 | 40 | /* Begin PBXFrameworksBuildPhase section */ 41 | 670138E21CD906BD004F6756 /* Frameworks */ = { 42 | isa = PBXFrameworksBuildPhase; 43 | buildActionMask = 2147483647; 44 | files = ( 45 | 6731B3EE1CDAB184000CB252 /* MySQL.framework in Frameworks */, 46 | 670139011CD906E4004F6756 /* PerfectLib.framework in Frameworks */, 47 | ); 48 | runOnlyForDeploymentPostprocessing = 0; 49 | }; 50 | 670138ED1CD906BE004F6756 /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | 670138F11CD906BE004F6756 /* PerfectProject.framework in Frameworks */, 55 | ); 56 | runOnlyForDeploymentPostprocessing = 0; 57 | }; 58 | /* End PBXFrameworksBuildPhase section */ 59 | 60 | /* Begin PBXGroup section */ 61 | 670138DC1CD906BD004F6756 = { 62 | isa = PBXGroup; 63 | children = ( 64 | 6731B3ED1CDAB184000CB252 /* MySQL.framework */, 65 | 670139001CD906E4004F6756 /* PerfectLib.framework */, 66 | 670138E81CD906BD004F6756 /* PerfectProject */, 67 | 670138F41CD906BE004F6756 /* PerfectProjectTests */, 68 | 670138E71CD906BD004F6756 /* Products */, 69 | ); 70 | sourceTree = ""; 71 | }; 72 | 670138E71CD906BD004F6756 /* Products */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | 670138E61CD906BD004F6756 /* PerfectProject.framework */, 76 | 670138F01CD906BE004F6756 /* PerfectProjectTests.xctest */, 77 | ); 78 | name = Products; 79 | sourceTree = ""; 80 | }; 81 | 670138E81CD906BD004F6756 /* PerfectProject */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | 670139021CD90767004F6756 /* PerfectHandlers.swift */, 85 | 670138E91CD906BD004F6756 /* PerfectProject.h */, 86 | 670138EB1CD906BD004F6756 /* Info.plist */, 87 | ); 88 | path = PerfectProject; 89 | sourceTree = ""; 90 | }; 91 | 670138F41CD906BE004F6756 /* PerfectProjectTests */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 670138F51CD906BE004F6756 /* PerfectProjectTests.swift */, 95 | 670138F71CD906BE004F6756 /* Info.plist */, 96 | ); 97 | path = PerfectProjectTests; 98 | sourceTree = ""; 99 | }; 100 | /* End PBXGroup section */ 101 | 102 | /* Begin PBXHeadersBuildPhase section */ 103 | 670138E31CD906BD004F6756 /* Headers */ = { 104 | isa = PBXHeadersBuildPhase; 105 | buildActionMask = 2147483647; 106 | files = ( 107 | 670138EA1CD906BD004F6756 /* PerfectProject.h in Headers */, 108 | ); 109 | runOnlyForDeploymentPostprocessing = 0; 110 | }; 111 | /* End PBXHeadersBuildPhase section */ 112 | 113 | /* Begin PBXNativeTarget section */ 114 | 670138E51CD906BD004F6756 /* PerfectProject */ = { 115 | isa = PBXNativeTarget; 116 | buildConfigurationList = 670138FA1CD906BE004F6756 /* Build configuration list for PBXNativeTarget "PerfectProject" */; 117 | buildPhases = ( 118 | 670138E11CD906BD004F6756 /* Sources */, 119 | 670138E21CD906BD004F6756 /* Frameworks */, 120 | 670138E31CD906BD004F6756 /* Headers */, 121 | 670138E41CD906BD004F6756 /* Resources */, 122 | ); 123 | buildRules = ( 124 | ); 125 | dependencies = ( 126 | ); 127 | name = PerfectProject; 128 | productName = PerfectProject; 129 | productReference = 670138E61CD906BD004F6756 /* PerfectProject.framework */; 130 | productType = "com.apple.product-type.framework"; 131 | }; 132 | 670138EF1CD906BE004F6756 /* PerfectProjectTests */ = { 133 | isa = PBXNativeTarget; 134 | buildConfigurationList = 670138FD1CD906BE004F6756 /* Build configuration list for PBXNativeTarget "PerfectProjectTests" */; 135 | buildPhases = ( 136 | 670138EC1CD906BE004F6756 /* Sources */, 137 | 670138ED1CD906BE004F6756 /* Frameworks */, 138 | 670138EE1CD906BE004F6756 /* Resources */, 139 | ); 140 | buildRules = ( 141 | ); 142 | dependencies = ( 143 | 670138F31CD906BE004F6756 /* PBXTargetDependency */, 144 | ); 145 | name = PerfectProjectTests; 146 | productName = PerfectProjectTests; 147 | productReference = 670138F01CD906BE004F6756 /* PerfectProjectTests.xctest */; 148 | productType = "com.apple.product-type.bundle.unit-test"; 149 | }; 150 | /* End PBXNativeTarget section */ 151 | 152 | /* Begin PBXProject section */ 153 | 670138DD1CD906BD004F6756 /* Project object */ = { 154 | isa = PBXProject; 155 | attributes = { 156 | LastSwiftUpdateCheck = 0730; 157 | LastUpgradeCheck = 0730; 158 | ORGANIZATIONNAME = nichrago; 159 | TargetAttributes = { 160 | 670138E51CD906BD004F6756 = { 161 | CreatedOnToolsVersion = 7.3; 162 | }; 163 | 670138EF1CD906BE004F6756 = { 164 | CreatedOnToolsVersion = 7.3; 165 | }; 166 | }; 167 | }; 168 | buildConfigurationList = 670138E01CD906BD004F6756 /* Build configuration list for PBXProject "PerfectProject" */; 169 | compatibilityVersion = "Xcode 3.2"; 170 | developmentRegion = English; 171 | hasScannedForEncodings = 0; 172 | knownRegions = ( 173 | en, 174 | ); 175 | mainGroup = 670138DC1CD906BD004F6756; 176 | productRefGroup = 670138E71CD906BD004F6756 /* Products */; 177 | projectDirPath = ""; 178 | projectRoot = ""; 179 | targets = ( 180 | 670138E51CD906BD004F6756 /* PerfectProject */, 181 | 670138EF1CD906BE004F6756 /* PerfectProjectTests */, 182 | ); 183 | }; 184 | /* End PBXProject section */ 185 | 186 | /* Begin PBXResourcesBuildPhase section */ 187 | 670138E41CD906BD004F6756 /* Resources */ = { 188 | isa = PBXResourcesBuildPhase; 189 | buildActionMask = 2147483647; 190 | files = ( 191 | ); 192 | runOnlyForDeploymentPostprocessing = 0; 193 | }; 194 | 670138EE1CD906BE004F6756 /* Resources */ = { 195 | isa = PBXResourcesBuildPhase; 196 | buildActionMask = 2147483647; 197 | files = ( 198 | ); 199 | runOnlyForDeploymentPostprocessing = 0; 200 | }; 201 | /* End PBXResourcesBuildPhase section */ 202 | 203 | /* Begin PBXSourcesBuildPhase section */ 204 | 670138E11CD906BD004F6756 /* Sources */ = { 205 | isa = PBXSourcesBuildPhase; 206 | buildActionMask = 2147483647; 207 | files = ( 208 | 670139031CD90767004F6756 /* PerfectHandlers.swift in Sources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | 670138EC1CD906BE004F6756 /* Sources */ = { 213 | isa = PBXSourcesBuildPhase; 214 | buildActionMask = 2147483647; 215 | files = ( 216 | 670138F61CD906BE004F6756 /* PerfectProjectTests.swift in Sources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXSourcesBuildPhase section */ 221 | 222 | /* Begin PBXTargetDependency section */ 223 | 670138F31CD906BE004F6756 /* PBXTargetDependency */ = { 224 | isa = PBXTargetDependency; 225 | target = 670138E51CD906BD004F6756 /* PerfectProject */; 226 | targetProxy = 670138F21CD906BE004F6756 /* PBXContainerItemProxy */; 227 | }; 228 | /* End PBXTargetDependency section */ 229 | 230 | /* Begin XCBuildConfiguration section */ 231 | 670138F81CD906BE004F6756 /* Debug */ = { 232 | isa = XCBuildConfiguration; 233 | buildSettings = { 234 | ALWAYS_SEARCH_USER_PATHS = NO; 235 | CLANG_ANALYZER_NONNULL = YES; 236 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 237 | CLANG_CXX_LIBRARY = "libc++"; 238 | CLANG_ENABLE_MODULES = YES; 239 | CLANG_ENABLE_OBJC_ARC = YES; 240 | CLANG_WARN_BOOL_CONVERSION = YES; 241 | CLANG_WARN_CONSTANT_CONVERSION = YES; 242 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 243 | CLANG_WARN_EMPTY_BODY = YES; 244 | CLANG_WARN_ENUM_CONVERSION = YES; 245 | CLANG_WARN_INT_CONVERSION = YES; 246 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 247 | CLANG_WARN_UNREACHABLE_CODE = YES; 248 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 249 | CODE_SIGN_IDENTITY = "-"; 250 | COPY_PHASE_STRIP = NO; 251 | CURRENT_PROJECT_VERSION = 1; 252 | DEBUG_INFORMATION_FORMAT = dwarf; 253 | ENABLE_STRICT_OBJC_MSGSEND = YES; 254 | ENABLE_TESTABILITY = YES; 255 | GCC_C_LANGUAGE_STANDARD = gnu99; 256 | GCC_DYNAMIC_NO_PIC = NO; 257 | GCC_NO_COMMON_BLOCKS = YES; 258 | GCC_OPTIMIZATION_LEVEL = 0; 259 | GCC_PREPROCESSOR_DEFINITIONS = ( 260 | "DEBUG=1", 261 | "$(inherited)", 262 | ); 263 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 264 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 265 | GCC_WARN_UNDECLARED_SELECTOR = YES; 266 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 267 | GCC_WARN_UNUSED_FUNCTION = YES; 268 | GCC_WARN_UNUSED_VARIABLE = YES; 269 | MACOSX_DEPLOYMENT_TARGET = 10.11; 270 | MTL_ENABLE_DEBUG_INFO = YES; 271 | ONLY_ACTIVE_ARCH = YES; 272 | SDKROOT = macosx; 273 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 274 | VERSIONING_SYSTEM = "apple-generic"; 275 | VERSION_INFO_PREFIX = ""; 276 | }; 277 | name = Debug; 278 | }; 279 | 670138F91CD906BE004F6756 /* Release */ = { 280 | isa = XCBuildConfiguration; 281 | buildSettings = { 282 | ALWAYS_SEARCH_USER_PATHS = NO; 283 | CLANG_ANALYZER_NONNULL = YES; 284 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 285 | CLANG_CXX_LIBRARY = "libc++"; 286 | CLANG_ENABLE_MODULES = YES; 287 | CLANG_ENABLE_OBJC_ARC = YES; 288 | CLANG_WARN_BOOL_CONVERSION = YES; 289 | CLANG_WARN_CONSTANT_CONVERSION = YES; 290 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 291 | CLANG_WARN_EMPTY_BODY = YES; 292 | CLANG_WARN_ENUM_CONVERSION = YES; 293 | CLANG_WARN_INT_CONVERSION = YES; 294 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 295 | CLANG_WARN_UNREACHABLE_CODE = YES; 296 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 297 | CODE_SIGN_IDENTITY = "-"; 298 | COPY_PHASE_STRIP = NO; 299 | CURRENT_PROJECT_VERSION = 1; 300 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 301 | ENABLE_NS_ASSERTIONS = NO; 302 | ENABLE_STRICT_OBJC_MSGSEND = YES; 303 | GCC_C_LANGUAGE_STANDARD = gnu99; 304 | GCC_NO_COMMON_BLOCKS = YES; 305 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 306 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 307 | GCC_WARN_UNDECLARED_SELECTOR = YES; 308 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 309 | GCC_WARN_UNUSED_FUNCTION = YES; 310 | GCC_WARN_UNUSED_VARIABLE = YES; 311 | MACOSX_DEPLOYMENT_TARGET = 10.11; 312 | MTL_ENABLE_DEBUG_INFO = NO; 313 | SDKROOT = macosx; 314 | VERSIONING_SYSTEM = "apple-generic"; 315 | VERSION_INFO_PREFIX = ""; 316 | }; 317 | name = Release; 318 | }; 319 | 670138FB1CD906BE004F6756 /* Debug */ = { 320 | isa = XCBuildConfiguration; 321 | buildSettings = { 322 | CLANG_ENABLE_MODULES = YES; 323 | COMBINE_HIDPI_IMAGES = YES; 324 | DEFINES_MODULE = YES; 325 | DEPLOYMENT_LOCATION = YES; 326 | DSTROOT = "$(CONFIGURATION_BUILD_DIR)"; 327 | DYLIB_COMPATIBILITY_VERSION = 1; 328 | DYLIB_CURRENT_VERSION = 1; 329 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 330 | FRAMEWORK_VERSION = A; 331 | INFOPLIST_FILE = PerfectProject/Info.plist; 332 | INSTALL_PATH = /PerfectLibraries; 333 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 334 | PRODUCT_BUNDLE_IDENTIFIER = com.nichrago.PerfectProject; 335 | PRODUCT_NAME = "$(TARGET_NAME)"; 336 | SKIP_INSTALL = NO; 337 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 338 | }; 339 | name = Debug; 340 | }; 341 | 670138FC1CD906BE004F6756 /* Release */ = { 342 | isa = XCBuildConfiguration; 343 | buildSettings = { 344 | CLANG_ENABLE_MODULES = YES; 345 | COMBINE_HIDPI_IMAGES = YES; 346 | DEFINES_MODULE = YES; 347 | DEPLOYMENT_LOCATION = YES; 348 | DSTROOT = "$(CONFIGURATION_BUILD_DIR)"; 349 | DYLIB_COMPATIBILITY_VERSION = 1; 350 | DYLIB_CURRENT_VERSION = 1; 351 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 352 | FRAMEWORK_VERSION = A; 353 | INFOPLIST_FILE = PerfectProject/Info.plist; 354 | INSTALL_PATH = /PerfectLibraries; 355 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 356 | PRODUCT_BUNDLE_IDENTIFIER = com.nichrago.PerfectProject; 357 | PRODUCT_NAME = "$(TARGET_NAME)"; 358 | SKIP_INSTALL = NO; 359 | }; 360 | name = Release; 361 | }; 362 | 670138FE1CD906BE004F6756 /* Debug */ = { 363 | isa = XCBuildConfiguration; 364 | buildSettings = { 365 | COMBINE_HIDPI_IMAGES = YES; 366 | INFOPLIST_FILE = PerfectProjectTests/Info.plist; 367 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 368 | PRODUCT_BUNDLE_IDENTIFIER = com.nichrago.PerfectProjectTests; 369 | PRODUCT_NAME = "$(TARGET_NAME)"; 370 | }; 371 | name = Debug; 372 | }; 373 | 670138FF1CD906BE004F6756 /* Release */ = { 374 | isa = XCBuildConfiguration; 375 | buildSettings = { 376 | COMBINE_HIDPI_IMAGES = YES; 377 | INFOPLIST_FILE = PerfectProjectTests/Info.plist; 378 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 379 | PRODUCT_BUNDLE_IDENTIFIER = com.nichrago.PerfectProjectTests; 380 | PRODUCT_NAME = "$(TARGET_NAME)"; 381 | }; 382 | name = Release; 383 | }; 384 | /* End XCBuildConfiguration section */ 385 | 386 | /* Begin XCConfigurationList section */ 387 | 670138E01CD906BD004F6756 /* Build configuration list for PBXProject "PerfectProject" */ = { 388 | isa = XCConfigurationList; 389 | buildConfigurations = ( 390 | 670138F81CD906BE004F6756 /* Debug */, 391 | 670138F91CD906BE004F6756 /* Release */, 392 | ); 393 | defaultConfigurationIsVisible = 0; 394 | defaultConfigurationName = Release; 395 | }; 396 | 670138FA1CD906BE004F6756 /* Build configuration list for PBXNativeTarget "PerfectProject" */ = { 397 | isa = XCConfigurationList; 398 | buildConfigurations = ( 399 | 670138FB1CD906BE004F6756 /* Debug */, 400 | 670138FC1CD906BE004F6756 /* Release */, 401 | ); 402 | defaultConfigurationIsVisible = 0; 403 | defaultConfigurationName = Release; 404 | }; 405 | 670138FD1CD906BE004F6756 /* Build configuration list for PBXNativeTarget "PerfectProjectTests" */ = { 406 | isa = XCConfigurationList; 407 | buildConfigurations = ( 408 | 670138FE1CD906BE004F6756 /* Debug */, 409 | 670138FF1CD906BE004F6756 /* Release */, 410 | ); 411 | defaultConfigurationIsVisible = 0; 412 | defaultConfigurationName = Release; 413 | }; 414 | /* End XCConfigurationList section */ 415 | }; 416 | rootObject = 670138DD1CD906BD004F6756 /* Project object */; 417 | } 418 | -------------------------------------------------------------------------------- /PerfectSetup/PerfectProject.xcodeproj/xcshareddata/xcschemes/PerfectProject.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 84 | 90 | 91 | 92 | 93 | 95 | 96 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /PerfectSetup/PerfectProject.xcodeproj/xcuserdata/nichrago.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PerfectProject.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 670138E51CD906BD004F6756 16 | 17 | primary 18 | 19 | 20 | 670138EF1CD906BE004F6756 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /PerfectSetup/PerfectProject/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSHumanReadableCopyright 24 | Copyright © 2016 nichrago. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /PerfectSetup/PerfectProject/PerfectHandlers.swift: -------------------------------------------------------------------------------- 1 | 2 | 3 | import PerfectLib 4 | import MySQL 5 | 6 | 7 | let HOST = "localhost" 8 | let USER = "perfectuser" 9 | let PASSWORD = "perfectpass" 10 | let DB_NAME = "PerfectTesting" 11 | let TABLE_NAME = "Messages" 12 | 13 | 14 | func createDatabase() { 15 | let mysql = MySQL() 16 | let connected = mysql.connect(HOST, user: USER, password: PASSWORD) 17 | 18 | guard connected else { print(mysql.errorMessage()); return } 19 | 20 | defer { mysql.close() } 21 | 22 | var isDatabase = mysql.selectDatabase(DB_NAME) 23 | if !isDatabase { 24 | isDatabase = mysql.query("CREATE DATABASE \(DB_NAME);") 25 | } 26 | 27 | let isTable = mysql.query("CREATE TABLE IF NOT EXISTS \(TABLE_NAME) (message TEXT, author TEXT);") 28 | 29 | guard isDatabase && isTable else { 30 | print(mysql.errorMessage()); return 31 | } 32 | } 33 | 34 | 35 | public func PerfectServerModuleInit() { 36 | Routing.Handler.registerGlobally() 37 | 38 | Routing.Routes["GET", "/messages"] = { _ in return GetAllMessages() } 39 | Routing.Routes["GET", "/messagesForAuthor"] = { _ in return GetMessagesForAuthor() } 40 | Routing.Routes["POST", "/postMessage"] = { _ in return PostMessage() } 41 | 42 | createDatabase() 43 | } 44 | 45 | 46 | func resultsToJSON(results results: MySQL.Results, _ fields: [String]) -> String? { 47 | if results.numFields() != fields.count { return nil } 48 | 49 | let encoder = JSONEncoder() 50 | var rowValues = [[String: JSONValue]]() 51 | 52 | results.forEachRow{ row in 53 | var rowValue = [String: JSONValue]() 54 | for c in 0 ..< fields.count { 55 | rowValue[fields[c]] = row[c] 56 | } 57 | rowValues.append(rowValue) 58 | } 59 | 60 | var responseString = "[" 61 | 62 | do { 63 | for c in 0 ..< rowValues.count { 64 | let rowJSON = try encoder.encode(rowValues[c]) 65 | responseString += rowJSON 66 | if c != rowValues.count - 1 { responseString += "," } 67 | else { responseString += "]" } 68 | } 69 | return responseString 70 | } catch { 71 | return nil 72 | } 73 | } 74 | 75 | 76 | class GetAllMessages: RequestHandler { 77 | func handleRequest(request: WebRequest, response: WebResponse) { 78 | let mysql = MySQL() 79 | let connected = mysql.connect(HOST, user: USER, password: PASSWORD) 80 | 81 | guard connected else { 82 | print(mysql.errorMessage()) 83 | response.setStatus(500, message: "Couldn't connect to MySQL") 84 | response.requestCompletedCallback(); return 85 | } 86 | 87 | mysql.selectDatabase(DB_NAME) 88 | defer { mysql.close() } 89 | 90 | let querySuccess = mysql.query("SELECT * FROM \(TABLE_NAME);") 91 | guard querySuccess else { 92 | print(mysql.errorMessage()) 93 | response.setStatus(500, message: "Things went wrong querying the table") 94 | response.requestCompletedCallback(); return 95 | } 96 | 97 | let results = mysql.storeResults() 98 | guard results != nil else { 99 | print("no messages were found") 100 | response.setStatus(500, message: "No Data in the table") 101 | response.requestCompletedCallback(); return 102 | } 103 | 104 | let result = resultsToJSON(results: results!, ["message", "author"]) 105 | guard result != nil else { 106 | print("json encoding did not work very well... or at all") 107 | response.setStatus(500, message: "no goo json encoding oops") 108 | response.requestCompletedCallback(); return 109 | } 110 | 111 | response.appendBodyString(result!) 112 | response.setStatus(200, message: "Mission Success Here is all the messages") 113 | response.requestCompletedCallback() 114 | } 115 | } 116 | 117 | 118 | class GetMessagesForAuthor: RequestHandler { 119 | func handleRequest(request: WebRequest, response: WebResponse) { 120 | let mysql = MySQL() 121 | let connected = mysql.connect(HOST, user: USER, password: PASSWORD) 122 | 123 | guard connected else { 124 | print(mysql.errorMessage()) 125 | response.setStatus(500, message: "couldnt connect to mysql") 126 | response.requestCompletedCallback(); return 127 | } 128 | 129 | let author = request.param("author") 130 | guard author != nil else { 131 | response.setStatus(400, message: "give me an author dammit") 132 | response.requestCompletedCallback(); return 133 | } 134 | 135 | mysql.selectDatabase(DB_NAME) 136 | defer { mysql.close() } 137 | 138 | let querySuccess = mysql.query("SELECT * FROM \(TABLE_NAME) WHERE author='\(author!)';") 139 | guard querySuccess else { 140 | print(mysql.errorMessage()) 141 | response.setStatus(500, message: "Query Error whatevs") 142 | response.requestCompletedCallback(); return 143 | } 144 | 145 | let results = mysql.storeResults() 146 | guard results != nil else { 147 | response.setStatus(500, message: "no results sorry mate") 148 | response.requestCompletedCallback(); return 149 | } 150 | 151 | let result = resultsToJSON(results: results!, ["message", "author"]) 152 | guard result != nil else { 153 | response.setStatus(500, message: "json encoding fail") 154 | response.requestCompletedCallback(); return 155 | } 156 | 157 | response.appendBodyString(result!) 158 | response.setStatus(200, message: "Mission Success whatsgud") 159 | response.requestCompletedCallback() 160 | } 161 | } 162 | 163 | 164 | class PostMessage: RequestHandler { 165 | func handleRequest(request: WebRequest, response: WebResponse) { 166 | let params = request.postParams 167 | guard params.count == 2 else { 168 | response.setStatus(400, message: "Params were no good") 169 | response.requestCompletedCallback(); return 170 | } 171 | 172 | let message = params[0].1 173 | let author = params[1].1 174 | 175 | let mysql = MySQL() 176 | let connected = mysql.connect(HOST, user: USER, password: PASSWORD) 177 | 178 | guard connected else { 179 | print(mysql.errorMessage()) 180 | response.setStatus(500, message: "Didnt connect to the thing bro") 181 | response.requestCompletedCallback(); return 182 | } 183 | 184 | mysql.selectDatabase(DB_NAME) 185 | let querySuccess = mysql.query("INSERT INTO \(TABLE_NAME) VALUES ('\(message)', '\(author)');") 186 | guard querySuccess else { 187 | print(mysql.errorMessage()) 188 | response.setStatus(500, message: "couldnt because it got mad") 189 | response.requestCompletedCallback(); return 190 | } 191 | 192 | response.setStatus(200, message: "post success thank you postman sorry for saying bro") 193 | response.requestCompletedCallback() 194 | } 195 | } 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /PerfectSetup/PerfectProject/PerfectProject.h: -------------------------------------------------------------------------------- 1 | // 2 | // PerfectProject.h 3 | // PerfectProject 4 | // 5 | // Created by nichrago on 2016-05-03. 6 | // Copyright © 2016 nichrago. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for PerfectProject. 12 | FOUNDATION_EXPORT double PerfectProjectVersionNumber; 13 | 14 | //! Project version string for PerfectProject. 15 | FOUNDATION_EXPORT const unsigned char PerfectProjectVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /PerfectSetup/PerfectProjectTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /PerfectSetup/PerfectProjectTests/PerfectProjectTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PerfectProjectTests.swift 3 | // PerfectProjectTests 4 | // 5 | // Created by nichrago on 2016-05-03. 6 | // Copyright © 2016 nichrago. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import PerfectProject 11 | 12 | class PerfectProjectTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome Anyone! 2 | This is a repo holding my Perfect video tutorials with its corresponding source code. 3 | 4 | I plan on making tutorials on Perfect as I continue to learn the framework so you will learn as I will. Unless of course you 5 | learn Perfect at a faster pace than I upload tutorials... This is highly recommended. 6 | 7 | A list of other Perfect Tutorials can be found at [perfect.org/tutorials](http://perfect.org/tutorials.html). 8 | 9 | Also, my favourite Perfect video tutorials series that I've found so far [Ryan Collins - Perfect Tutorials](https://www.youtube.com/playlist?list=PLE2M81Pddau3LrJRGPbc6UXMy3VQuA2lL). There he covers similar topics that I did plus more and in much greater detail. 10 | 11 | # Tutorial Index 12 | ### Perfect Setup 13 | 14 | A walkthrough of getting yourself settled in Perfect and setting up a basic service. 15 | [Perfect : Server Side Swift - Server Setup, Request Handling, and MySQL Connection](https://www.youtube.com/watch?v=vY-g5eqQ6oA) 16 | --------------------------------------------------------------------------------