From 375f4fee2b451f166a2a553a1dad2bca45af7244 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sun, 17 Feb 2019 12:03:46 +0100 Subject: [PATCH 01/37] Feat: define base structure of API --- Content/Response.swift | 12 + Example/Podfile.lock | 16 + .../Pods/Local Podspecs/PunkAPI.podspec.json | 22 + Example/Pods/Manifest.lock | 16 + Example/Pods/Pods.xcodeproj/project.pbxproj | 816 ++++++++++++++++++ .../Pods-PunkAPI_Example/Info.plist | 26 + ...-PunkAPI_Example-acknowledgements.markdown | 26 + ...ods-PunkAPI_Example-acknowledgements.plist | 58 ++ .../Pods-PunkAPI_Example-dummy.m | 5 + .../Pods-PunkAPI_Example-frameworks.sh | 153 ++++ .../Pods-PunkAPI_Example-resources.sh | 118 +++ .../Pods-PunkAPI_Example-umbrella.h | 16 + .../Pods-PunkAPI_Example.debug.xcconfig | 11 + .../Pods-PunkAPI_Example.modulemap | 6 + .../Pods-PunkAPI_Example.release.xcconfig | 11 + .../Pods-PunkAPI_Tests/Info.plist | 26 + ...ds-PunkAPI_Tests-acknowledgements.markdown | 3 + .../Pods-PunkAPI_Tests-acknowledgements.plist | 29 + .../Pods-PunkAPI_Tests-dummy.m | 5 + .../Pods-PunkAPI_Tests-frameworks.sh | 146 ++++ .../Pods-PunkAPI_Tests-resources.sh | 118 +++ .../Pods-PunkAPI_Tests-umbrella.h | 16 + .../Pods-PunkAPI_Tests.debug.xcconfig | 8 + .../Pods-PunkAPI_Tests.modulemap | 6 + .../Pods-PunkAPI_Tests.release.xcconfig | 8 + .../Target Support Files/PunkAPI/Info.plist | 26 + .../PunkAPI/PunkAPI-dummy.m | 5 + .../PunkAPI/PunkAPI-prefix.pch | 12 + .../PunkAPI/PunkAPI-umbrella.h | 16 + .../PunkAPI/PunkAPI.modulemap | 6 + .../PunkAPI/PunkAPI.xcconfig | 9 + Example/PunkAPI.xcodeproj/project.pbxproj | 49 +- .../xcschemes/PunkAPI-Example.xcscheme | 4 +- .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + Example/PunkAPI/AppDelegate.swift | 2 +- PunkAPI/Classes/Configuration.swift | 21 + PunkAPI/Classes/PunkAPI.swift | 26 + PunkAPI/Classes/ReplaceMe.swift | 0 PunkAPI/Classes/Request/Request.swift | 12 + PunkAPI/Classes/Request/Result.swift | 14 + 41 files changed, 1879 insertions(+), 18 deletions(-) create mode 100644 Content/Response.swift create mode 100644 Example/Podfile.lock create mode 100644 Example/Pods/Local Podspecs/PunkAPI.podspec.json create mode 100644 Example/Pods/Manifest.lock create mode 100644 Example/Pods/Pods.xcodeproj/project.pbxproj create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Example/Info.plist create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-acknowledgements.markdown create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-acknowledgements.plist create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-dummy.m create mode 100755 Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-frameworks.sh create mode 100755 Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-resources.sh create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-umbrella.h create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.debug.xcconfig create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.modulemap create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.release.xcconfig create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Info.plist create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-acknowledgements.markdown create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-acknowledgements.plist create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-dummy.m create mode 100755 Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-frameworks.sh create mode 100755 Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-resources.sh create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-umbrella.h create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.debug.xcconfig create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.modulemap create mode 100644 Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.release.xcconfig create mode 100644 Example/Pods/Target Support Files/PunkAPI/Info.plist create mode 100644 Example/Pods/Target Support Files/PunkAPI/PunkAPI-dummy.m create mode 100644 Example/Pods/Target Support Files/PunkAPI/PunkAPI-prefix.pch create mode 100644 Example/Pods/Target Support Files/PunkAPI/PunkAPI-umbrella.h create mode 100644 Example/Pods/Target Support Files/PunkAPI/PunkAPI.modulemap create mode 100644 Example/Pods/Target Support Files/PunkAPI/PunkAPI.xcconfig create mode 100644 Example/PunkAPI.xcworkspace/contents.xcworkspacedata create mode 100644 Example/PunkAPI.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 PunkAPI/Classes/Configuration.swift create mode 100644 PunkAPI/Classes/PunkAPI.swift delete mode 100644 PunkAPI/Classes/ReplaceMe.swift create mode 100644 PunkAPI/Classes/Request/Request.swift create mode 100644 PunkAPI/Classes/Request/Result.swift diff --git a/Content/Response.swift b/Content/Response.swift new file mode 100644 index 0000000..837b882 --- /dev/null +++ b/Content/Response.swift @@ -0,0 +1,12 @@ +// +// Response.swift +// PunkAPI +// +// Created by Andrea Altea on 17/02/2019. +// + +import Foundation + +struct Response { + +} diff --git a/Example/Podfile.lock b/Example/Podfile.lock new file mode 100644 index 0000000..dfeada2 --- /dev/null +++ b/Example/Podfile.lock @@ -0,0 +1,16 @@ +PODS: + - PunkAPI (0.1.0) + +DEPENDENCIES: + - PunkAPI (from `../`) + +EXTERNAL SOURCES: + PunkAPI: + :path: "../" + +SPEC CHECKSUMS: + PunkAPI: 3604e01855fc2f1e591d704f2728e7e2cbce27ad + +PODFILE CHECKSUM: 77a7edfbda92bc42f026175f2a4105df175a2c99 + +COCOAPODS: 1.5.3 diff --git a/Example/Pods/Local Podspecs/PunkAPI.podspec.json b/Example/Pods/Local Podspecs/PunkAPI.podspec.json new file mode 100644 index 0000000..7597051 --- /dev/null +++ b/Example/Pods/Local Podspecs/PunkAPI.podspec.json @@ -0,0 +1,22 @@ +{ + "name": "PunkAPI", + "version": "0.1.0", + "summary": "A short description of PunkAPI.", + "description": "TODO: Add long description of the pod here.", + "homepage": "https://github.com/acct=/PunkAPI", + "license": { + "type": "MIT", + "file": "LICENSE" + }, + "authors": { + "acct=": "oni.zerone@gmail.com" + }, + "source": { + "git": "https://github.com/acct=/PunkAPI.git", + "tag": "0.1.0" + }, + "platforms": { + "ios": "8.0" + }, + "source_files": "PunkAPI/Classes/**/*" +} diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock new file mode 100644 index 0000000..dfeada2 --- /dev/null +++ b/Example/Pods/Manifest.lock @@ -0,0 +1,16 @@ +PODS: + - PunkAPI (0.1.0) + +DEPENDENCIES: + - PunkAPI (from `../`) + +EXTERNAL SOURCES: + PunkAPI: + :path: "../" + +SPEC CHECKSUMS: + PunkAPI: 3604e01855fc2f1e591d704f2728e7e2cbce27ad + +PODFILE CHECKSUM: 77a7edfbda92bc42f026175f2a4105df175a2c99 + +COCOAPODS: 1.5.3 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 0000000..8df05b4 --- /dev/null +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,816 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1DEF7BF616CC3F2EF46A7F9E5514F9AC /* Pods-PunkAPI_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E9F6D3BEDEF11CDF5DC7C24AEF5989 /* Pods-PunkAPI_Tests-dummy.m */; }; + 3D7A5283D0833518F12109285F42CDD6 /* PunkAPI-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DB27FF57BF224EBB035E6BD38B873FD /* PunkAPI-dummy.m */; }; + 4DE6F5415AA32E45E1A1B40AA8194B63 /* Pods-PunkAPI_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E322AC54183F0711E107C333BF42C3CF /* Pods-PunkAPI_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4F478C6F6571A694E377026C7020B987 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */; }; + 5563E1330468FB6D76F769A6697DF682 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */; }; + 861F0ED5029160D63BEA52EEDC4F5B2D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */; }; + 94ACB62152B83DE972430EAA4B24D449 /* PunkAPI-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E72CC1703129F4F85A80F609B175F2AA /* PunkAPI-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9767CBEA2219744000E684C4 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBE92219744000E684C4 /* Result.swift */; }; + 9767CBED2219755E00E684C4 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBEC2219755E00E684C4 /* Response.swift */; }; + 9DEE51DC320AFD89F8CCE79E659D0E92 /* Pods-PunkAPI_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AD6B8F0860FB91889F808D08F168E096 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBF879A7A0C8CE59F1DD2A17BB11873 /* Request.swift */; }; + B0D852DC953C7A0E2C1CB872F9E315BB /* Pods-PunkAPI_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */; }; + DB20D4F60BC185671791B119F6F2629E /* PunkAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C8708EEF51A0078E3211F1AA5F78C06 /* PunkAPI.swift */; }; + FB6E32A7831DCA2AE93BD8C3F87FA8E3 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AD5D712F315E66077D59EE9C31CF689 /* Configuration.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 1BD9253D912BA229A3617AE941991ACC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 104A4972E6668483EF3BA6EE08D840AF; + remoteInfo = PunkAPI; + }; + 26AB40795B0BA17DA83D7BA25EA5107F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = C1DB41E820BFF9D57C1A713EEC3A7C98; + remoteInfo = "Pods-PunkAPI_Example"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 06BAF05CBDEA8E295E4784A5A5D4506C /* Pods-PunkAPI_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PunkAPI_Tests-acknowledgements.plist"; sourceTree = ""; }; + 08865B1A9072612C58080056C52A36BE /* Pods-PunkAPI_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Example.modulemap"; sourceTree = ""; }; + 0AD5D712F315E66077D59EE9C31CF689 /* Configuration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Configuration.swift; path = PunkAPI/Classes/Configuration.swift; sourceTree = ""; }; + 1A11ED2EBFB85AEE905043364BD068DB /* PunkAPI.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PunkAPI.xcconfig; sourceTree = ""; }; + 1AFB7D35FB6048047A48B079FB616B3E /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; + 2293F81F3EBE30B333C3070B12ABBF5B /* PunkAPI.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = PunkAPI.modulemap; sourceTree = ""; }; + 2EC29BADC6D4B129C97F077B8D1AAD24 /* Pods-PunkAPI_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Example-frameworks.sh"; sourceTree = ""; }; + 34E9F6D3BEDEF11CDF5DC7C24AEF5989 /* Pods-PunkAPI_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Tests-dummy.m"; sourceTree = ""; }; + 3CA7DD0E0D9E3D052F0DA83C7B3B79FC /* Pods_PunkAPI_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 492C127C07A0D9D778B3D645FCDED6AC /* Pods-PunkAPI_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Tests.release.xcconfig"; sourceTree = ""; }; + 5C8708EEF51A0078E3211F1AA5F78C06 /* PunkAPI.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PunkAPI.swift; path = PunkAPI/Classes/PunkAPI.swift; sourceTree = ""; }; + 608E9332AF8468043B49B03317025805 /* Pods-PunkAPI_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Tests-frameworks.sh"; sourceTree = ""; }; + 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PunkAPI_Example-umbrella.h"; sourceTree = ""; }; + 6EDD1194CE9C142C26AD6C6803C306E4 /* Pods-PunkAPI_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Tests.debug.xcconfig"; sourceTree = ""; }; + 7F7764549D1799C2D5D6A7B2D65E3550 /* Pods-PunkAPI_Example-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Example-resources.sh"; sourceTree = ""; }; + 8342B62283B06E1CA90A14E1BCB6D62B /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8458C84A594F726E1A8DB6294F78DB73 /* Pods-PunkAPI_Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Tests-resources.sh"; sourceTree = ""; }; + 8DB27FF57BF224EBB035E6BD38B873FD /* PunkAPI-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PunkAPI-dummy.m"; sourceTree = ""; }; + 92229C81AD3A318707A49C8449AEB2F5 /* Pods-PunkAPI_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PunkAPI_Example-acknowledgements.plist"; sourceTree = ""; }; + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9767CBE92219744000E684C4 /* Result.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Result.swift; path = PunkAPI/Classes/Request/Result.swift; sourceTree = ""; }; + 9767CBEC2219755E00E684C4 /* Response.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = ""; }; + 9D14926C4AE138B3C55CE27E18BE194D /* Pods-PunkAPI_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Tests.modulemap"; sourceTree = ""; }; + 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Example-dummy.m"; sourceTree = ""; }; + A5D146483FC9684CF2C15F85C081EF35 /* Pods-PunkAPI_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Example.release.xcconfig"; sourceTree = ""; }; + BAFFC5AEB631CBE680C80CE0652ADBE2 /* PunkAPI-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PunkAPI-prefix.pch"; sourceTree = ""; }; + BBBF879A7A0C8CE59F1DD2A17BB11873 /* Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = ""; }; + D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + DEDE7F6F743486EEE8CDF26C3F19CF0F /* PunkAPI.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; path = PunkAPI.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + E322AC54183F0711E107C333BF42C3CF /* Pods-PunkAPI_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PunkAPI_Tests-umbrella.h"; sourceTree = ""; }; + E722B264627A535D845CCF418E225784 /* Pods-PunkAPI_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PunkAPI_Tests-acknowledgements.markdown"; sourceTree = ""; }; + E72CC1703129F4F85A80F609B175F2AA /* PunkAPI-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PunkAPI-umbrella.h"; sourceTree = ""; }; + E816F7DA6C1CBE532E1590E0F05B9532 /* Pods-PunkAPI_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Example.debug.xcconfig"; sourceTree = ""; }; + E874B75DA5C3ABAE4B0B94E8DB6C6045 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + EAE741F8D3D7DED0544AD07D421892ED /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + F03BE7FD6C231D53225FB54CC54F7FC1 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + FA66D5ED6E33AA7DD32A8C962841F3B0 /* PunkAPI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PunkAPI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FB1D3C212D7A0519F22CF554E249675E /* Pods-PunkAPI_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PunkAPI_Example-acknowledgements.markdown"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2AC16E9D9907618B6A4F41C69D4587F0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4F478C6F6571A694E377026C7020B987 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64469F9A8CDA0C6CFDD8BA665E002A2F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5563E1330468FB6D76F769A6697DF682 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 76E7A3CBB25A47B13596EDBA2CE7AB07 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 861F0ED5029160D63BEA52EEDC4F5B2D /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 44D5347904CF754D6785B84253F2574A /* iOS */ = { + isa = PBXGroup; + children = ( + D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */, + ); + name = iOS; + sourceTree = ""; + }; + 4922267629DB1812F5525CC2246D2338 /* Support Files */ = { + isa = PBXGroup; + children = ( + F03BE7FD6C231D53225FB54CC54F7FC1 /* Info.plist */, + 2293F81F3EBE30B333C3070B12ABBF5B /* PunkAPI.modulemap */, + 1A11ED2EBFB85AEE905043364BD068DB /* PunkAPI.xcconfig */, + 8DB27FF57BF224EBB035E6BD38B873FD /* PunkAPI-dummy.m */, + BAFFC5AEB631CBE680C80CE0652ADBE2 /* PunkAPI-prefix.pch */, + E72CC1703129F4F85A80F609B175F2AA /* PunkAPI-umbrella.h */, + ); + name = "Support Files"; + path = "Example/Pods/Target Support Files/PunkAPI"; + sourceTree = ""; + }; + 5E6C37C04887F82A8C550F9B76E5B746 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 9BFECB8663CD309F9214B4311C96BCB5 /* Pods-PunkAPI_Example */, + B2D5CC793D96E6B1A0442EA2481F7DF2 /* Pods-PunkAPI_Tests */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + 6719D069938A455DA268A952D46C9D57 /* Request */ = { + isa = PBXGroup; + children = ( + BBBF879A7A0C8CE59F1DD2A17BB11873 /* Request.swift */, + ); + name = Request; + path = PunkAPI/Classes/Request; + sourceTree = ""; + }; + 6C92B5E2C39B71B9A3D59EB753CF598A /* Products */ = { + isa = PBXGroup; + children = ( + 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */, + 3CA7DD0E0D9E3D052F0DA83C7B3B79FC /* Pods_PunkAPI_Tests.framework */, + FA66D5ED6E33AA7DD32A8C962841F3B0 /* PunkAPI.framework */, + ); + name = Products; + sourceTree = ""; + }; + 7DB346D0F39D3F0E887471402A8071AB = { + isa = PBXGroup; + children = ( + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, + B4EA824994F2844B351D845077BAB557 /* Development Pods */, + BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */, + 6C92B5E2C39B71B9A3D59EB753CF598A /* Products */, + 5E6C37C04887F82A8C550F9B76E5B746 /* Targets Support Files */, + ); + sourceTree = ""; + }; + 7F3D670CFD2E3B9BFC42CB165C936B98 /* Pod */ = { + isa = PBXGroup; + children = ( + 1AFB7D35FB6048047A48B079FB616B3E /* LICENSE */, + DEDE7F6F743486EEE8CDF26C3F19CF0F /* PunkAPI.podspec */, + E874B75DA5C3ABAE4B0B94E8DB6C6045 /* README.md */, + ); + name = Pod; + sourceTree = ""; + }; + 890261190D25DC439794AA100CC2F689 /* PunkAPI */ = { + isa = PBXGroup; + children = ( + 9767CBE92219744000E684C4 /* Result.swift */, + 0AD5D712F315E66077D59EE9C31CF689 /* Configuration.swift */, + 5C8708EEF51A0078E3211F1AA5F78C06 /* PunkAPI.swift */, + 9767CBEE2219756C00E684C4 /* Content */, + 7F3D670CFD2E3B9BFC42CB165C936B98 /* Pod */, + 6719D069938A455DA268A952D46C9D57 /* Request */, + 4922267629DB1812F5525CC2246D2338 /* Support Files */, + ); + name = PunkAPI; + path = ../..; + sourceTree = ""; + }; + 9767CBEE2219756C00E684C4 /* Content */ = { + isa = PBXGroup; + children = ( + 9767CBEC2219755E00E684C4 /* Response.swift */, + ); + path = Content; + sourceTree = ""; + }; + 9BFECB8663CD309F9214B4311C96BCB5 /* Pods-PunkAPI_Example */ = { + isa = PBXGroup; + children = ( + 8342B62283B06E1CA90A14E1BCB6D62B /* Info.plist */, + 08865B1A9072612C58080056C52A36BE /* Pods-PunkAPI_Example.modulemap */, + FB1D3C212D7A0519F22CF554E249675E /* Pods-PunkAPI_Example-acknowledgements.markdown */, + 92229C81AD3A318707A49C8449AEB2F5 /* Pods-PunkAPI_Example-acknowledgements.plist */, + A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */, + 2EC29BADC6D4B129C97F077B8D1AAD24 /* Pods-PunkAPI_Example-frameworks.sh */, + 7F7764549D1799C2D5D6A7B2D65E3550 /* Pods-PunkAPI_Example-resources.sh */, + 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */, + E816F7DA6C1CBE532E1590E0F05B9532 /* Pods-PunkAPI_Example.debug.xcconfig */, + A5D146483FC9684CF2C15F85C081EF35 /* Pods-PunkAPI_Example.release.xcconfig */, + ); + name = "Pods-PunkAPI_Example"; + path = "Target Support Files/Pods-PunkAPI_Example"; + sourceTree = ""; + }; + B2D5CC793D96E6B1A0442EA2481F7DF2 /* Pods-PunkAPI_Tests */ = { + isa = PBXGroup; + children = ( + EAE741F8D3D7DED0544AD07D421892ED /* Info.plist */, + 9D14926C4AE138B3C55CE27E18BE194D /* Pods-PunkAPI_Tests.modulemap */, + E722B264627A535D845CCF418E225784 /* Pods-PunkAPI_Tests-acknowledgements.markdown */, + 06BAF05CBDEA8E295E4784A5A5D4506C /* Pods-PunkAPI_Tests-acknowledgements.plist */, + 34E9F6D3BEDEF11CDF5DC7C24AEF5989 /* Pods-PunkAPI_Tests-dummy.m */, + 608E9332AF8468043B49B03317025805 /* Pods-PunkAPI_Tests-frameworks.sh */, + 8458C84A594F726E1A8DB6294F78DB73 /* Pods-PunkAPI_Tests-resources.sh */, + E322AC54183F0711E107C333BF42C3CF /* Pods-PunkAPI_Tests-umbrella.h */, + 6EDD1194CE9C142C26AD6C6803C306E4 /* Pods-PunkAPI_Tests.debug.xcconfig */, + 492C127C07A0D9D778B3D645FCDED6AC /* Pods-PunkAPI_Tests.release.xcconfig */, + ); + name = "Pods-PunkAPI_Tests"; + path = "Target Support Files/Pods-PunkAPI_Tests"; + sourceTree = ""; + }; + B4EA824994F2844B351D845077BAB557 /* Development Pods */ = { + isa = PBXGroup; + children = ( + 890261190D25DC439794AA100CC2F689 /* PunkAPI */, + ); + name = "Development Pods"; + sourceTree = ""; + }; + BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */ = { + isa = PBXGroup; + children = ( + 44D5347904CF754D6785B84253F2574A /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 6BAF60135FDFD6B381631C7BED9969B3 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 94ACB62152B83DE972430EAA4B24D449 /* PunkAPI-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 88CEDC5C00738D5465027D297EB9644D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4DE6F5415AA32E45E1A1B40AA8194B63 /* Pods-PunkAPI_Tests-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E95C4D0DC25D5A98B2A4C4AAFDAD0596 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 9DEE51DC320AFD89F8CCE79E659D0E92 /* Pods-PunkAPI_Example-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 104A4972E6668483EF3BA6EE08D840AF /* PunkAPI */ = { + isa = PBXNativeTarget; + buildConfigurationList = C5CFB8D87EAAD43FF2A708011ADF9DF5 /* Build configuration list for PBXNativeTarget "PunkAPI" */; + buildPhases = ( + 6BAF60135FDFD6B381631C7BED9969B3 /* Headers */, + FE130DA14D328C73F836837F31FCCCEC /* Sources */, + 64469F9A8CDA0C6CFDD8BA665E002A2F /* Frameworks */, + 971F83F24AFBDD4CF88BD6ED289EEB1C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PunkAPI; + productName = PunkAPI; + productReference = FA66D5ED6E33AA7DD32A8C962841F3B0 /* PunkAPI.framework */; + productType = "com.apple.product-type.framework"; + }; + C1DB41E820BFF9D57C1A713EEC3A7C98 /* Pods-PunkAPI_Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = B97836D74BBC103F707A992128BA2EBA /* Build configuration list for PBXNativeTarget "Pods-PunkAPI_Example" */; + buildPhases = ( + E95C4D0DC25D5A98B2A4C4AAFDAD0596 /* Headers */, + AEF952ACEC65192DB68BBAE0B794131A /* Sources */, + 2AC16E9D9907618B6A4F41C69D4587F0 /* Frameworks */, + C0A4E0BED8488FF565D86ADC701B8084 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + AC80DFE7429FC940D34413A8CD236866 /* PBXTargetDependency */, + ); + name = "Pods-PunkAPI_Example"; + productName = "Pods-PunkAPI_Example"; + productReference = 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */; + productType = "com.apple.product-type.framework"; + }; + D4B40E035E9C8A43CF581FE371EB5EA1 /* Pods-PunkAPI_Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 418812EEE776D4446934FDEFBBAAB6E0 /* Build configuration list for PBXNativeTarget "Pods-PunkAPI_Tests" */; + buildPhases = ( + 88CEDC5C00738D5465027D297EB9644D /* Headers */, + 7D76001470C4ECFAD45A4E50C07DF2B8 /* Sources */, + 76E7A3CBB25A47B13596EDBA2CE7AB07 /* Frameworks */, + 6822401903D7AFC3F5ECA9D7C022FFB9 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 4F84539F116C2CCA3F4B274DE3A3066E /* PBXTargetDependency */, + ); + name = "Pods-PunkAPI_Tests"; + productName = "Pods-PunkAPI_Tests"; + productReference = 3CA7DD0E0D9E3D052F0DA83C7B3B79FC /* Pods_PunkAPI_Tests.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0930; + LastUpgradeCheck = 0930; + TargetAttributes = { + 104A4972E6668483EF3BA6EE08D840AF = { + LastSwiftMigration = 1010; + }; + }; + }; + buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 7DB346D0F39D3F0E887471402A8071AB; + productRefGroup = 6C92B5E2C39B71B9A3D59EB753CF598A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + C1DB41E820BFF9D57C1A713EEC3A7C98 /* Pods-PunkAPI_Example */, + D4B40E035E9C8A43CF581FE371EB5EA1 /* Pods-PunkAPI_Tests */, + 104A4972E6668483EF3BA6EE08D840AF /* PunkAPI */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 6822401903D7AFC3F5ECA9D7C022FFB9 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 971F83F24AFBDD4CF88BD6ED289EEB1C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C0A4E0BED8488FF565D86ADC701B8084 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7D76001470C4ECFAD45A4E50C07DF2B8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1DEF7BF616CC3F2EF46A7F9E5514F9AC /* Pods-PunkAPI_Tests-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AEF952ACEC65192DB68BBAE0B794131A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B0D852DC953C7A0E2C1CB872F9E315BB /* Pods-PunkAPI_Example-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FE130DA14D328C73F836837F31FCCCEC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FB6E32A7831DCA2AE93BD8C3F87FA8E3 /* Configuration.swift in Sources */, + 9767CBEA2219744000E684C4 /* Result.swift in Sources */, + 3D7A5283D0833518F12109285F42CDD6 /* PunkAPI-dummy.m in Sources */, + DB20D4F60BC185671791B119F6F2629E /* PunkAPI.swift in Sources */, + 9767CBED2219755E00E684C4 /* Response.swift in Sources */, + AD6B8F0860FB91889F808D08F168E096 /* Request.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 4F84539F116C2CCA3F4B274DE3A3066E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Pods-PunkAPI_Example"; + target = C1DB41E820BFF9D57C1A713EEC3A7C98 /* Pods-PunkAPI_Example */; + targetProxy = 26AB40795B0BA17DA83D7BA25EA5107F /* PBXContainerItemProxy */; + }; + AC80DFE7429FC940D34413A8CD236866 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = PunkAPI; + target = 104A4972E6668483EF3BA6EE08D840AF /* PunkAPI */; + targetProxy = 1BD9253D912BA229A3617AE941991ACC /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 0A32C10549B40B79BD750860BACF73EA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1A11ED2EBFB85AEE905043364BD068DB /* PunkAPI.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/PunkAPI/PunkAPI-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/PunkAPI/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/PunkAPI/PunkAPI.modulemap"; + PRODUCT_MODULE_NAME = PunkAPI; + PRODUCT_NAME = PunkAPI; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 403B3CA7AD0B06503DC7AB172EBAC118 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6EDD1194CE9C142C26AD6C6803C306E4 /* Pods-PunkAPI_Tests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Tests/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 46AF96B59BED2112D06B134F951A4153 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A5D146483FC9684CF2C15F85C081EF35 /* Pods-PunkAPI_Example.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Example/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 50646285DD9FD95AF390BDA3FB1948EA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_ALLOWED = NO; + CODE_SIGNING_REQUIRED = NO; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.2; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + 58DCB2BA7C34E84C00C38CEF18A96D11 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_ALLOWED = NO; + CODE_SIGNING_REQUIRED = NO; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 4.2; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + 9289467C07440D2A81F24C3126E8A2CD /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1A11ED2EBFB85AEE905043364BD068DB /* PunkAPI.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/PunkAPI/PunkAPI-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/PunkAPI/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/PunkAPI/PunkAPI.modulemap"; + PRODUCT_MODULE_NAME = PunkAPI; + PRODUCT_NAME = PunkAPI; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + CEA1F7ADD2A14B78BDC2402ECBA8804F /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 492C127C07A0D9D778B3D645FCDED6AC /* Pods-PunkAPI_Tests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Tests/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D1B38F9CCE04509C680580A3EE523419 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E816F7DA6C1CBE532E1590E0F05B9532 /* Pods-PunkAPI_Example.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Example/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 50646285DD9FD95AF390BDA3FB1948EA /* Debug */, + 58DCB2BA7C34E84C00C38CEF18A96D11 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 418812EEE776D4446934FDEFBBAAB6E0 /* Build configuration list for PBXNativeTarget "Pods-PunkAPI_Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 403B3CA7AD0B06503DC7AB172EBAC118 /* Debug */, + CEA1F7ADD2A14B78BDC2402ECBA8804F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B97836D74BBC103F707A992128BA2EBA /* Build configuration list for PBXNativeTarget "Pods-PunkAPI_Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D1B38F9CCE04509C680580A3EE523419 /* Debug */, + 46AF96B59BED2112D06B134F951A4153 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C5CFB8D87EAAD43FF2A708011ADF9DF5 /* Build configuration list for PBXNativeTarget "PunkAPI" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9289467C07440D2A81F24C3126E8A2CD /* Debug */, + 0A32C10549B40B79BD750860BACF73EA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; +} diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Info.plist b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Info.plist new file mode 100644 index 0000000..2243fe6 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-acknowledgements.markdown b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-acknowledgements.markdown new file mode 100644 index 0000000..d23ace9 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-acknowledgements.markdown @@ -0,0 +1,26 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## PunkAPI + +Copyright (c) 2019 acct= + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Generated by CocoaPods - https://cocoapods.org diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-acknowledgements.plist b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-acknowledgements.plist new file mode 100644 index 0000000..8ef8216 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-acknowledgements.plist @@ -0,0 +1,58 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2019 acct<blob>=<NULL> <oni.zerone@gmail.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + License + MIT + Title + PunkAPI + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-dummy.m b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-dummy.m new file mode 100644 index 0000000..34e855b --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_PunkAPI_Example : NSObject +@end +@implementation PodsDummy_Pods_PunkAPI_Example +@end diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-frameworks.sh b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-frameworks.sh new file mode 100755 index 0000000..7684ffc --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-frameworks.sh @@ -0,0 +1,153 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + if [ -r "$source" ]; then + # Copy the dSYM into a the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .framework.dSYM "$source")" + binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then + strip_invalid_archs "$binary" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" + fi + fi +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identitiy + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" || exit 1 + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/PunkAPI/PunkAPI.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/PunkAPI/PunkAPI.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-resources.sh b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-resources.sh new file mode 100755 index 0000000..345301f --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-resources.sh @@ -0,0 +1,118 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then + # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy + # resources to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + +RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt +> "$RESOURCES_TO_COPY" + +XCASSET_FILES=() + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +case "${TARGETED_DEVICE_FAMILY:-}" in + 1,2) + TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" + ;; + 1) + TARGET_DEVICE_ARGS="--target-device iphone" + ;; + 2) + TARGET_DEVICE_ARGS="--target-device ipad" + ;; + 3) + TARGET_DEVICE_ARGS="--target-device tv" + ;; + 4) + TARGET_DEVICE_ARGS="--target-device watch" + ;; + *) + TARGET_DEVICE_ARGS="--target-device mac" + ;; +esac + +install_resource() +{ + if [[ "$1" = /* ]] ; then + RESOURCE_PATH="$1" + else + RESOURCE_PATH="${PODS_ROOT}/$1" + fi + if [[ ! -e "$RESOURCE_PATH" ]] ; then + cat << EOM +error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. +EOM + exit 1 + fi + case $RESOURCE_PATH in + *.storyboard) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.xib) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.framework) + echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + ;; + *.xcdatamodel) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" + ;; + *.xcdatamodeld) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" + ;; + *.xcmappingmodel) + echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true + xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" + ;; + *.xcassets) + ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" + XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") + ;; + *) + echo "$RESOURCE_PATH" || true + echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" + ;; + esac +} + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then + mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi +rm -f "$RESOURCES_TO_COPY" + +if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] +then + # Find all other xcassets (this unfortunately includes those of path pods and other targets). + OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) + while read line; do + if [[ $line != "${PODS_ROOT}*" ]]; then + XCASSET_FILES+=("$line") + fi + done <<<"$OTHER_XCASSETS" + + if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + else + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" + fi +fi diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-umbrella.h b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-umbrella.h new file mode 100644 index 0000000..280b7e1 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_PunkAPI_ExampleVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_PunkAPI_ExampleVersionString[]; + diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.debug.xcconfig b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.debug.xcconfig new file mode 100644 index 0000000..b09d6b7 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.debug.xcconfig @@ -0,0 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI/PunkAPI.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "PunkAPI" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.modulemap b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.modulemap new file mode 100644 index 0000000..d58ae30 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.modulemap @@ -0,0 +1,6 @@ +framework module Pods_PunkAPI_Example { + umbrella header "Pods-PunkAPI_Example-umbrella.h" + + export * + module * { export * } +} diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.release.xcconfig b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.release.xcconfig new file mode 100644 index 0000000..b09d6b7 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.release.xcconfig @@ -0,0 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI/PunkAPI.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "PunkAPI" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Info.plist b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Info.plist new file mode 100644 index 0000000..2243fe6 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-acknowledgements.markdown b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-acknowledgements.markdown new file mode 100644 index 0000000..102af75 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-acknowledgements.markdown @@ -0,0 +1,3 @@ +# Acknowledgements +This application makes use of the following third party libraries: +Generated by CocoaPods - https://cocoapods.org diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-acknowledgements.plist b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-acknowledgements.plist new file mode 100644 index 0000000..7acbad1 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-acknowledgements.plist @@ -0,0 +1,29 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-dummy.m b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-dummy.m new file mode 100644 index 0000000..32454a2 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_PunkAPI_Tests : NSObject +@end +@implementation PodsDummy_Pods_PunkAPI_Tests +@end diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-frameworks.sh b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-frameworks.sh new file mode 100755 index 0000000..08e3eaa --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-frameworks.sh @@ -0,0 +1,146 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + if [ -r "$source" ]; then + # Copy the dSYM into a the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .framework.dSYM "$source")" + binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then + strip_invalid_archs "$binary" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" + fi + fi +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identitiy + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" || exit 1 + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-resources.sh b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-resources.sh new file mode 100755 index 0000000..345301f --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-resources.sh @@ -0,0 +1,118 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then + # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy + # resources to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + +RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt +> "$RESOURCES_TO_COPY" + +XCASSET_FILES=() + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +case "${TARGETED_DEVICE_FAMILY:-}" in + 1,2) + TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" + ;; + 1) + TARGET_DEVICE_ARGS="--target-device iphone" + ;; + 2) + TARGET_DEVICE_ARGS="--target-device ipad" + ;; + 3) + TARGET_DEVICE_ARGS="--target-device tv" + ;; + 4) + TARGET_DEVICE_ARGS="--target-device watch" + ;; + *) + TARGET_DEVICE_ARGS="--target-device mac" + ;; +esac + +install_resource() +{ + if [[ "$1" = /* ]] ; then + RESOURCE_PATH="$1" + else + RESOURCE_PATH="${PODS_ROOT}/$1" + fi + if [[ ! -e "$RESOURCE_PATH" ]] ; then + cat << EOM +error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. +EOM + exit 1 + fi + case $RESOURCE_PATH in + *.storyboard) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.xib) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.framework) + echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + ;; + *.xcdatamodel) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" + ;; + *.xcdatamodeld) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" + ;; + *.xcmappingmodel) + echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true + xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" + ;; + *.xcassets) + ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" + XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") + ;; + *) + echo "$RESOURCE_PATH" || true + echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" + ;; + esac +} + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then + mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi +rm -f "$RESOURCES_TO_COPY" + +if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] +then + # Find all other xcassets (this unfortunately includes those of path pods and other targets). + OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) + while read line; do + if [[ $line != "${PODS_ROOT}*" ]]; then + XCASSET_FILES+=("$line") + fi + done <<<"$OTHER_XCASSETS" + + if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + else + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" + fi +fi diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-umbrella.h b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-umbrella.h new file mode 100644 index 0000000..f7d6167 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_PunkAPI_TestsVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_PunkAPI_TestsVersionString[]; + diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.debug.xcconfig b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.debug.xcconfig new file mode 100644 index 0000000..179485a --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.debug.xcconfig @@ -0,0 +1,8 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI/PunkAPI.framework/Headers" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.modulemap b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.modulemap new file mode 100644 index 0000000..ec6f6fd --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.modulemap @@ -0,0 +1,6 @@ +framework module Pods_PunkAPI_Tests { + umbrella header "Pods-PunkAPI_Tests-umbrella.h" + + export * + module * { export * } +} diff --git a/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.release.xcconfig b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.release.xcconfig new file mode 100644 index 0000000..179485a --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.release.xcconfig @@ -0,0 +1,8 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI/PunkAPI.framework/Headers" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Example/Pods/Target Support Files/PunkAPI/Info.plist b/Example/Pods/Target Support Files/PunkAPI/Info.plist new file mode 100644 index 0000000..161a9d3 --- /dev/null +++ b/Example/Pods/Target Support Files/PunkAPI/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Example/Pods/Target Support Files/PunkAPI/PunkAPI-dummy.m b/Example/Pods/Target Support Files/PunkAPI/PunkAPI-dummy.m new file mode 100644 index 0000000..d5552c2 --- /dev/null +++ b/Example/Pods/Target Support Files/PunkAPI/PunkAPI-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_PunkAPI : NSObject +@end +@implementation PodsDummy_PunkAPI +@end diff --git a/Example/Pods/Target Support Files/PunkAPI/PunkAPI-prefix.pch b/Example/Pods/Target Support Files/PunkAPI/PunkAPI-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Example/Pods/Target Support Files/PunkAPI/PunkAPI-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Example/Pods/Target Support Files/PunkAPI/PunkAPI-umbrella.h b/Example/Pods/Target Support Files/PunkAPI/PunkAPI-umbrella.h new file mode 100644 index 0000000..77f87f6 --- /dev/null +++ b/Example/Pods/Target Support Files/PunkAPI/PunkAPI-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double PunkAPIVersionNumber; +FOUNDATION_EXPORT const unsigned char PunkAPIVersionString[]; + diff --git a/Example/Pods/Target Support Files/PunkAPI/PunkAPI.modulemap b/Example/Pods/Target Support Files/PunkAPI/PunkAPI.modulemap new file mode 100644 index 0000000..cc71a00 --- /dev/null +++ b/Example/Pods/Target Support Files/PunkAPI/PunkAPI.modulemap @@ -0,0 +1,6 @@ +framework module PunkAPI { + umbrella header "PunkAPI-umbrella.h" + + export * + module * { export * } +} diff --git a/Example/Pods/Target Support Files/PunkAPI/PunkAPI.xcconfig b/Example/Pods/Target Support Files/PunkAPI/PunkAPI.xcconfig new file mode 100644 index 0000000..c450857 --- /dev/null +++ b/Example/Pods/Target Support Files/PunkAPI/PunkAPI.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/PunkAPI +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Example/PunkAPI.xcodeproj/project.pbxproj b/Example/PunkAPI.xcodeproj/project.pbxproj index a2f9776..da52770 100644 --- a/Example/PunkAPI.xcodeproj/project.pbxproj +++ b/Example/PunkAPI.xcodeproj/project.pbxproj @@ -29,8 +29,8 @@ /* Begin PBXFileReference section */ 00C6BA9ADC6CC9CF141BE6E8 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CA29904BB7426E73CC31E50 /* PunkAPI.podspec */ = {isa = PBXFileReference; includeInIndex = 1; name = PunkAPI.podspec; path = ../PunkAPI.podspec; sourceTree = ""; }; - 19516DEBCED4A6F0ADCEC345 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; + 0CA29904BB7426E73CC31E50 /* PunkAPI.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = PunkAPI.podspec; path = ../PunkAPI.podspec; sourceTree = ""; }; + 19516DEBCED4A6F0ADCEC345 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 46341D8F014E1940E53D4F02 /* Pods_PunkAPI_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACD01AFB9204008FA782 /* PunkAPI_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PunkAPI_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -43,7 +43,7 @@ 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 613B14F018C28CF1557EC3D5 /* Pods-PunkAPI_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.debug.xcconfig"; sourceTree = ""; }; - 9A440A355337DF96D159D208 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; name = README.md; path = ../README.md; sourceTree = ""; }; + 9A440A355337DF96D159D208 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; A4CA42C1E1AE14F816574722 /* Pods-PunkAPI_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.debug.xcconfig"; sourceTree = ""; }; E294694CD6DD5DA5A6B471F1 /* Pods-PunkAPI_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.release.xcconfig"; sourceTree = ""; }; F793434367F74B6D00F77A47 /* Pods-PunkAPI_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.release.xcconfig"; sourceTree = ""; }; @@ -167,6 +167,7 @@ buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "PunkAPI_Example" */; buildPhases = ( 44318C15D7E57EAD731D7620 /* [CP] Check Pods Manifest.lock */, + 9767CBEB2219750F00E684C4 /* ShellScript */, 607FACCC1AFB9204008FA782 /* Sources */, 607FACCD1AFB9204008FA782 /* Frameworks */, 607FACCE1AFB9204008FA782 /* Resources */, @@ -207,16 +208,17 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0830; - LastUpgradeCheck = 0830; + LastUpgradeCheck = 1010; ORGANIZATIONNAME = CocoaPods; TargetAttributes = { 607FACCF1AFB9204008FA782 = { CreatedOnToolsVersion = 6.3.1; - LastSwiftMigration = 0900; + DevelopmentTeam = 6RS7DS4QV5; + LastSwiftMigration = 1010; }; 607FACE41AFB9204008FA782 = { CreatedOnToolsVersion = 6.3.1; - LastSwiftMigration = 0900; + LastSwiftMigration = 1010; TestTargetID = 607FACCF1AFB9204008FA782; }; }; @@ -305,6 +307,23 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + 9767CBEB2219750F00E684C4 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export PATH=\"/usr/local/bin:$PATH\"\nexport LANG=en_US.UTF-8\n\nif which swiftlint >/dev/null; then\n\nif [ \"$CI\" == true ]; then\necho swiftlint lint --strict\nelse\necho swiftlint\nfi\n\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + }; E502466B5504391CFC64510C /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -389,12 +408,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -442,12 +463,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -481,13 +504,13 @@ baseConfigurationReference = A4CA42C1E1AE14F816574722 /* Pods-PunkAPI_Example.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = 6RS7DS4QV5; INFOPLIST_FILE = PunkAPI/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -496,13 +519,13 @@ baseConfigurationReference = E294694CD6DD5DA5A6B471F1 /* Pods-PunkAPI_Example.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = 6RS7DS4QV5; INFOPLIST_FILE = PunkAPI/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Release; }; @@ -522,8 +545,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PunkAPI_Example.app/PunkAPI_Example"; }; name = Debug; @@ -540,8 +562,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PunkAPI_Example.app/PunkAPI_Example"; }; name = Release; diff --git a/Example/PunkAPI.xcodeproj/xcshareddata/xcschemes/PunkAPI-Example.xcscheme b/Example/PunkAPI.xcodeproj/xcshareddata/xcschemes/PunkAPI-Example.xcscheme index 9599202..0dfe2e8 100644 --- a/Example/PunkAPI.xcodeproj/xcshareddata/xcschemes/PunkAPI-Example.xcscheme +++ b/Example/PunkAPI.xcodeproj/xcshareddata/xcschemes/PunkAPI-Example.xcscheme @@ -1,6 +1,6 @@ + + + + + + diff --git a/Example/PunkAPI.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example/PunkAPI.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Example/PunkAPI.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Example/PunkAPI/AppDelegate.swift b/Example/PunkAPI/AppDelegate.swift index 423b922..b33b55a 100644 --- a/Example/PunkAPI/AppDelegate.swift +++ b/Example/PunkAPI/AppDelegate.swift @@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } diff --git a/PunkAPI/Classes/Configuration.swift b/PunkAPI/Classes/Configuration.swift new file mode 100644 index 0000000..468f7c9 --- /dev/null +++ b/PunkAPI/Classes/Configuration.swift @@ -0,0 +1,21 @@ +// +// Configuration.swift +// PunkAPI +// +// Created by Andrea Altea on 17/02/2019. +// + +import Foundation + +public struct Configuration { + + var session: URLSession + + var baseComponent: URLComponents + + init(sessionConfiguration: URLSessionConfiguration) { + + self.session = URLSession(configuration: sessionConfiguration) + self.baseComponent = URLComponents(string: "https://api.punkapi.com/v2/")! + } +} diff --git a/PunkAPI/Classes/PunkAPI.swift b/PunkAPI/Classes/PunkAPI.swift new file mode 100644 index 0000000..f0d29c8 --- /dev/null +++ b/PunkAPI/Classes/PunkAPI.swift @@ -0,0 +1,26 @@ +// +// PunkAPI.swift +// Pods-PunkAPI_Example +// +// Created by Andrea Altea on 17/02/2019. +// + +import Foundation + +public class PunkAPI { + + var configuration: Configuration + + public init(sessionConfiguration: URLSessionConfiguration) { + + self.configuration = Configuration(sessionConfiguration: sessionConfiguration) + } + + public convenience init() { + self.init(sessionConfiguration: .default) + } + + func getBeer(_ request: Request, completion: @escaping (Result) -> Void) { + + } +} diff --git a/PunkAPI/Classes/ReplaceMe.swift b/PunkAPI/Classes/ReplaceMe.swift deleted file mode 100644 index e69de29..0000000 diff --git a/PunkAPI/Classes/Request/Request.swift b/PunkAPI/Classes/Request/Request.swift new file mode 100644 index 0000000..50db05c --- /dev/null +++ b/PunkAPI/Classes/Request/Request.swift @@ -0,0 +1,12 @@ +// +// Request.swift +// Pods-PunkAPI_Example +// +// Created by Andrea Altea on 17/02/2019. +// + +import Foundation + +protocol Request { + +} diff --git a/PunkAPI/Classes/Request/Result.swift b/PunkAPI/Classes/Request/Result.swift new file mode 100644 index 0000000..e038c5e --- /dev/null +++ b/PunkAPI/Classes/Request/Result.swift @@ -0,0 +1,14 @@ +// +// Result.swift +// PunkAPI +// +// Created by Andrea Altea on 17/02/2019. +// + +import Foundation + +public enum Result { + + case success(Value) + case failure(Error) +} From a9a4e082727723d4fc00ea77542a9d2fac39de08 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sun, 17 Feb 2019 13:02:31 +0100 Subject: [PATCH 02/37] Feat: complete the request cycle --- Content/Beer.swift | 60 +++++++++++++++++++ Example/Pods/Pods.xcodeproj/project.pbxproj | 16 +++-- Example/PunkAPI/ViewController.swift | 9 ++- .../Classes/Errors.swift | 7 ++- PunkAPI/Classes/PunkAPI.swift | 43 ++++++++++++- PunkAPI/Classes/Request/BeerRequest.swift | 22 +++++++ PunkAPI/Classes/Request/Request.swift | 4 +- 7 files changed, 146 insertions(+), 15 deletions(-) create mode 100644 Content/Beer.swift rename Content/Response.swift => PunkAPI/Classes/Errors.swift (50%) create mode 100644 PunkAPI/Classes/Request/BeerRequest.swift diff --git a/Content/Beer.swift b/Content/Beer.swift new file mode 100644 index 0000000..0828895 --- /dev/null +++ b/Content/Beer.swift @@ -0,0 +1,60 @@ +// +// Beer.swift +// PunkAPI +// +// Created by Andrea Altea on 17/02/2019. +// + +import Foundation + +public struct Beer: Codable { + + var id: Int + var name: String + var tagline: String + var firstBrewed: String + var description: String + var imageUrl: String + + var abv: Float + var ibu: Float + + var targetFg: Float + var targetOg: Float + + var ebc: Float + var srm: Float + var ph: Float + + var attenuationLevel: Float + var volume: Volume + var boilVolume: Volume +// var method: Method +} + +extension Beer { + + struct Volume: Codable { + + var value: Float + var unit: String + } + + struct Temperature: Codable { + + var value: Float + var unit: String + } + + struct Method { + + var mashTemp: [Step] + var fermentation: Temperature + + struct Step { + var temp: Temperature + var duration: Float? + } + } +} + diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 8df05b4..635d910 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -15,7 +15,9 @@ 861F0ED5029160D63BEA52EEDC4F5B2D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */; }; 94ACB62152B83DE972430EAA4B24D449 /* PunkAPI-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E72CC1703129F4F85A80F609B175F2AA /* PunkAPI-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9767CBEA2219744000E684C4 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBE92219744000E684C4 /* Result.swift */; }; - 9767CBED2219755E00E684C4 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBEC2219755E00E684C4 /* Response.swift */; }; + 9767CBF0221977D300E684C4 /* Beer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBEF221977D300E684C4 /* Beer.swift */; }; + 9767CBF22219795E00E684C4 /* BeerRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF12219795E00E684C4 /* BeerRequest.swift */; }; + 9767CBF422197DCC00E684C4 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF322197DCC00E684C4 /* Errors.swift */; }; 9DEE51DC320AFD89F8CCE79E659D0E92 /* Pods-PunkAPI_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; AD6B8F0860FB91889F808D08F168E096 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBF879A7A0C8CE59F1DD2A17BB11873 /* Request.swift */; }; B0D852DC953C7A0E2C1CB872F9E315BB /* Pods-PunkAPI_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */; }; @@ -62,7 +64,9 @@ 92229C81AD3A318707A49C8449AEB2F5 /* Pods-PunkAPI_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PunkAPI_Example-acknowledgements.plist"; sourceTree = ""; }; 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 9767CBE92219744000E684C4 /* Result.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Result.swift; path = PunkAPI/Classes/Request/Result.swift; sourceTree = ""; }; - 9767CBEC2219755E00E684C4 /* Response.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = ""; }; + 9767CBEF221977D300E684C4 /* Beer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Beer.swift; sourceTree = ""; }; + 9767CBF12219795E00E684C4 /* BeerRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerRequest.swift; sourceTree = ""; }; + 9767CBF322197DCC00E684C4 /* Errors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Errors.swift; path = PunkAPI/Classes/Errors.swift; sourceTree = ""; }; 9D14926C4AE138B3C55CE27E18BE194D /* Pods-PunkAPI_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Tests.modulemap"; sourceTree = ""; }; 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Example-dummy.m"; sourceTree = ""; }; @@ -145,6 +149,7 @@ isa = PBXGroup; children = ( BBBF879A7A0C8CE59F1DD2A17BB11873 /* Request.swift */, + 9767CBF12219795E00E684C4 /* BeerRequest.swift */, ); name = Request; path = PunkAPI/Classes/Request; @@ -184,6 +189,7 @@ 890261190D25DC439794AA100CC2F689 /* PunkAPI */ = { isa = PBXGroup; children = ( + 9767CBF322197DCC00E684C4 /* Errors.swift */, 9767CBE92219744000E684C4 /* Result.swift */, 0AD5D712F315E66077D59EE9C31CF689 /* Configuration.swift */, 5C8708EEF51A0078E3211F1AA5F78C06 /* PunkAPI.swift */, @@ -199,7 +205,7 @@ 9767CBEE2219756C00E684C4 /* Content */ = { isa = PBXGroup; children = ( - 9767CBEC2219755E00E684C4 /* Response.swift */, + 9767CBEF221977D300E684C4 /* Beer.swift */, ); path = Content; sourceTree = ""; @@ -423,8 +429,10 @@ FB6E32A7831DCA2AE93BD8C3F87FA8E3 /* Configuration.swift in Sources */, 9767CBEA2219744000E684C4 /* Result.swift in Sources */, 3D7A5283D0833518F12109285F42CDD6 /* PunkAPI-dummy.m in Sources */, + 9767CBF22219795E00E684C4 /* BeerRequest.swift in Sources */, DB20D4F60BC185671791B119F6F2629E /* PunkAPI.swift in Sources */, - 9767CBED2219755E00E684C4 /* Response.swift in Sources */, + 9767CBF0221977D300E684C4 /* Beer.swift in Sources */, + 9767CBF422197DCC00E684C4 /* Errors.swift in Sources */, AD6B8F0860FB91889F808D08F168E096 /* Request.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Example/PunkAPI/ViewController.swift b/Example/PunkAPI/ViewController.swift index ac487a3..b662cf9 100644 --- a/Example/PunkAPI/ViewController.swift +++ b/Example/PunkAPI/ViewController.swift @@ -7,17 +7,16 @@ // import UIKit +import PunkAPI class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. - } - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. + PunkAPI().get(BeerRequest(id: 1), completion: { beers in + print(beers) + }) } } diff --git a/Content/Response.swift b/PunkAPI/Classes/Errors.swift similarity index 50% rename from Content/Response.swift rename to PunkAPI/Classes/Errors.swift index 837b882..9af4562 100644 --- a/Content/Response.swift +++ b/PunkAPI/Classes/Errors.swift @@ -1,5 +1,5 @@ // -// Response.swift +// Errors.swift // PunkAPI // // Created by Andrea Altea on 17/02/2019. @@ -7,6 +7,7 @@ import Foundation -struct Response { - +enum APIError: Error { + case invalidURL + case emptyResponse } diff --git a/PunkAPI/Classes/PunkAPI.swift b/PunkAPI/Classes/PunkAPI.swift index f0d29c8..71fa077 100644 --- a/PunkAPI/Classes/PunkAPI.swift +++ b/PunkAPI/Classes/PunkAPI.swift @@ -20,7 +20,46 @@ public class PunkAPI { self.init(sessionConfiguration: .default) } - func getBeer(_ request: Request, completion: @escaping (Result) -> Void) { - + public func get(_ request: Request, queue: DispatchQueue = .global(qos: .background), completion: @escaping (Result<[Beer]>) -> Void) { + + var urlComponent = self.configuration.baseComponent + urlComponent.path += request.path + guard let url = urlComponent.url else { + queue.async { completion(.failure(APIError.invalidURL)) } + return + } + + self.configuration.session.dataTask(with: url) { (result: Result<[Beer]>) in + queue.async { + completion(result) + } + }.resume() + } +} + +extension URLSession { + + func dataTask(with url: URL, completion: @escaping (Result) -> Void) -> URLSessionDataTask { + return self.dataTask(with: url) { (data, response, error) in + + do { + if let error = error { + throw error + } + + guard let data = data else { + throw APIError.emptyResponse + } + + let decoder = JSONDecoder() + decoder.keyDecodingStrategy = .convertFromSnakeCase + + let beers = try decoder.decode(Value.self, from: data) + completion(.success(beers)) + + } catch let error { + completion(.failure(error)) + } + } } } diff --git a/PunkAPI/Classes/Request/BeerRequest.swift b/PunkAPI/Classes/Request/BeerRequest.swift new file mode 100644 index 0000000..914ac4b --- /dev/null +++ b/PunkAPI/Classes/Request/BeerRequest.swift @@ -0,0 +1,22 @@ +// +// BeerRequest.swift +// PunkAPI +// +// Created by Andrea Altea on 17/02/2019. +// + +import Foundation + +public struct BeerRequest: Request { + + var id: Int + + public var path: String { + return "beers/\(self.id)" + } + + public init(id: Int) { + + self.id = id + } +} diff --git a/PunkAPI/Classes/Request/Request.swift b/PunkAPI/Classes/Request/Request.swift index 50db05c..b29ea0c 100644 --- a/PunkAPI/Classes/Request/Request.swift +++ b/PunkAPI/Classes/Request/Request.swift @@ -7,6 +7,8 @@ import Foundation -protocol Request { +public protocol Request { + + var path: String { get } } From 549eafe3551d9bc7131851d02b6918d32f34b9f9 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sun, 17 Feb 2019 14:01:36 +0100 Subject: [PATCH 03/37] feat: update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 93c86d3..04217b7 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ Carthage/Build # `pod install` in .travis.yml # # Pods/ +IDEWorkspaceChecks.plist From fb0d61314b3152b82d6be8e9cdd43bc5e85874dc Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sun, 17 Feb 2019 20:11:44 +0100 Subject: [PATCH 04/37] Feat: add response stubs --- Example/PunkAPI.xcodeproj/project.pbxproj | 20 ++++-- Example/PunkAPI/ViewController.swift | 1 - Example/Tests/BeerParsingTests.swift | 74 +++++++++++++++++++++++ Example/Tests/BeerStubs.swift | 41 +++++++++++++ Example/Tests/Tests.swift | 28 --------- 5 files changed, 131 insertions(+), 33 deletions(-) create mode 100644 Example/Tests/BeerParsingTests.swift create mode 100644 Example/Tests/BeerStubs.swift delete mode 100644 Example/Tests/Tests.swift diff --git a/Example/PunkAPI.xcodeproj/project.pbxproj b/Example/PunkAPI.xcodeproj/project.pbxproj index da52770..df22b5f 100644 --- a/Example/PunkAPI.xcodeproj/project.pbxproj +++ b/Example/PunkAPI.xcodeproj/project.pbxproj @@ -13,7 +13,8 @@ 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; - 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; }; + 9767CBF7221993F900E684C4 /* BeerParsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF6221993F800E684C4 /* BeerParsingTests.swift */; }; + 9767CBFA2219958F00E684C4 /* BeerStubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF82219958800E684C4 /* BeerStubs.swift */; }; EBB1B4D6901624C6A90359CA /* Pods_PunkAPI_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46341D8F014E1940E53D4F02 /* Pods_PunkAPI_Tests.framework */; }; /* End PBXBuildFile section */ @@ -41,8 +42,9 @@ 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 607FACE51AFB9204008FA782 /* PunkAPI_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PunkAPI_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 613B14F018C28CF1557EC3D5 /* Pods-PunkAPI_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.debug.xcconfig"; sourceTree = ""; }; + 9767CBF6221993F800E684C4 /* BeerParsingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerParsingTests.swift; sourceTree = ""; }; + 9767CBF82219958800E684C4 /* BeerStubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerStubs.swift; sourceTree = ""; }; 9A440A355337DF96D159D208 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; A4CA42C1E1AE14F816574722 /* Pods-PunkAPI_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.debug.xcconfig"; sourceTree = ""; }; E294694CD6DD5DA5A6B471F1 /* Pods-PunkAPI_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.release.xcconfig"; sourceTree = ""; }; @@ -124,7 +126,7 @@ 607FACE81AFB9204008FA782 /* Tests */ = { isa = PBXGroup; children = ( - 607FACEB1AFB9204008FA782 /* Tests.swift */, + 9767CBF5221993DA00E684C4 /* BeerParsing */, 607FACE91AFB9204008FA782 /* Supporting Files */, ); path = Tests; @@ -159,6 +161,15 @@ name = Pods; sourceTree = ""; }; + 9767CBF5221993DA00E684C4 /* BeerParsing */ = { + isa = PBXGroup; + children = ( + 9767CBF6221993F800E684C4 /* BeerParsingTests.swift */, + 9767CBF82219958800E684C4 /* BeerStubs.swift */, + ); + name = BeerParsing; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -362,7 +373,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */, + 9767CBF7221993F900E684C4 /* BeerParsingTests.swift in Sources */, + 9767CBFA2219958F00E684C4 /* BeerStubs.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example/PunkAPI/ViewController.swift b/Example/PunkAPI/ViewController.swift index b662cf9..b96e1eb 100644 --- a/Example/PunkAPI/ViewController.swift +++ b/Example/PunkAPI/ViewController.swift @@ -18,6 +18,5 @@ class ViewController: UIViewController { print(beers) }) } - } diff --git a/Example/Tests/BeerParsingTests.swift b/Example/Tests/BeerParsingTests.swift new file mode 100644 index 0000000..75d3655 --- /dev/null +++ b/Example/Tests/BeerParsingTests.swift @@ -0,0 +1,74 @@ +// +// BeerParsingTests.swift +// PunkAPI_Tests +// +// Created by Andrea Altea on 17/02/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import XCTest +import PunkAPI + +class BeerParsingTests: XCTestCase { + + var parser: JSONDecoder! + + override func setUp() { + + let parser = JSONDecoder() + parser.keyDecodingStrategy = .convertFromSnakeCase + self.parser = parser + } + + override func tearDown() { + self.parser = nil + } + + func testFirst() { + + self.decodeBeers(BeerStub.first) + } + + func testSecond() { + + self.decodeBeers(BeerStub.second) + } + + func testThird() { + + self.decodeBeers(BeerStub.third) + } + + func testFourth() { + + self.decodeBeers(BeerStub.fourth) + } + + func testFifth() { + + self.decodeBeers(BeerStub.fifth) + } + + func testMultipleFirst() { + self.decodeBeers(BeerStub.multipleFirst) + } + + func testMultipleSecond() { + self.decodeBeers(BeerStub.multipleSecond) + } + + @discardableResult + func decodeBeers(_ json: String) -> [Beer]? { + + do { + guard let data = json.data(using: .utf8) else { + XCTFail("invalid stub") + return nil + } + return try self.parser.decode([Beer].self, from: data) + } catch let error { + XCTFail(error.localizedDescription) + return nil + } + } +} diff --git a/Example/Tests/BeerStubs.swift b/Example/Tests/BeerStubs.swift new file mode 100644 index 0000000..7315848 --- /dev/null +++ b/Example/Tests/BeerStubs.swift @@ -0,0 +1,41 @@ +// +// BeerStubs.swift +// PunkAPI_Example +// +// Created by Andrea Altea on 17/02/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + + +import Foundation + +struct BeerStub { + + static let first = """ +[{"id":1,"name":"Buzz","tagline":"A Real Bitter Experience.","first_brewed":"09/2007","description":"A light, crisp and bitter IPA brewed with English and American hops. A small batch brewed only once.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.5,"ibu":60,"target_fg":1010,"target_og":1044,"ebc":20,"srm":10,"ph":4.4,"attenuation_level":75,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":64,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":3.3,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.2,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.4,"unit":"kilograms"}}],"hops":[{"name":"Fuggles","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Fuggles","amount":{"value":37.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"First Gold","amount":{"value":37.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Cascade","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Spicy chicken tikka masala","Grilled chicken quesadilla","Caramel toffee cake"],"brewers_tips":"The earthy and floral aromas from the hops can be overpowering. Drop a little Cascade in at the end of the boil to lift the profile with a bit of citrus.","contributed_by":"Sam Mason "}] +""" + + static let second = """ +[{"id":2,"name":"Trashy Blonde","tagline":"You Know You Shouldn't","first_brewed":"04/2008","description":"A titillating, neurotic, peroxide punk of a Pale Ale. Combining attitude, style, substance, and a little bit of low self esteem for good measure; what would your mother say? The seductive lure of the sassy passion fruit hop proves too much to resist. All that is even before we get onto the fact that there are no additives, preservatives, pasteurization or strings attached. All wrapped up with the customary BrewDog bite and imaginative twist.","image_url":"https://images.punkapi.com/v2/2.png","abv":4.1,"ibu":41.5,"target_fg":1010,"target_og":1041.7,"ebc":15,"srm":15,"ph":4.4,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":69,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":3.25,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.2,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.4,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":13.8,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":13.8,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":26.3,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Motueka","amount":{"value":18.8,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Fresh crab with lemon","Garlic butter dipping sauce","Goats cheese salad","Creamy lemon bar doused in powdered sugar"],"brewers_tips":"Be careful not to collect too much wort from the mash. Once the sugars are all washed out there are some very unpleasant grainy tasting compounds that can be extracted into the wort.","contributed_by":"Sam Mason "}] +""" + + static let third = """ +[{"id":3,"name":"Berliner Weisse With Yuzu - B-Sides","tagline":"Japanese Citrus Berliner Weisse.","first_brewed":"11/2015","description":"Japanese citrus fruit intensifies the sour nature of this German classic.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.2,"ibu":8,"target_fg":1007,"target_og":1040,"ebc":8,"srm":4,"ph":3.2,"attenuation_level":83,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":60,"unit":"celsius"},"duration":10},{"temp":{"value":65,"unit":"celsius"},"duration":30},{"temp":{"value":72,"unit":"celsius"},"duration":10},{"temp":{"value":78,"unit":"celsius"},"duration":5}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Soured naturally using the kettle souring technique, Yuzu fruit: 50g at middle, Yuzu juice: 200ml at FV"},"ingredients":{"malt":[{"name":"Propino Pale Malt","amount":{"value":1.63,"unit":"kilograms"}},{"name":"Wheat Malt","amount":{"value":1.63,"unit":"kilograms"}},{"name":"Propino Pale Malt for kettle 0.03kg souring","amount":{"value":0.03,"unit":"kilograms"}},{"name":"Acidulated Malt for kettle souring","amount":{"value":0.03,"unit":"kilograms"}}],"hops":[{"name":"Bramling Cross","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"bitter"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Smoked chicken wings","Miso ramen","Yuzu cheesecake"],"brewers_tips":"Clean everything twice. All you want is the clean sourness of lactobacillus.","contributed_by":"Sam Mason "}] +""" + + static let fourth = """ +[{"id":4,"name":"Pilsen Lager","tagline":"Unleash the Yeast Series.","first_brewed":"09/2013","description":"Our Unleash the Yeast series was an epic experiment into the differences in aroma and flavour provided by switching up your yeast. We brewed up a wort with a light caramel note and some toasty biscuit flavour, and hopped it with Amarillo and Centennial for a citrusy bitterness. Everything else is down to the yeast. Pilsner yeast ferments with no fruity esters or spicy phenols, although it can add a hint of butterscotch.","image_url":"https://images.punkapi.com/v2/4.png","abv":6.3,"ibu":55,"target_fg":1012,"target_og":1060,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":80,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":9,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.58,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.25,"unit":"kilograms"}}],"hops":[{"name":"Centennial","amount":{"value":5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Amarillo","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Centennial","amount":{"value":17.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":17.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 2007 - Pilsen Lager™"},"food_pairing":["Spicy crab cakes","Spicy cucumber and carrot Thai salad","Sweet filled dumplings"],"brewers_tips":"Play around with the fermentation temperature to get the best flavour profile from the individual yeasts.","contributed_by":"Ali Skinner "}] +""" + + static let fifth = """ +[{"id":5,"name":"Avery Brown Dredge","tagline":"Bloggers' Imperial Pilsner.","first_brewed":"02/2011","description":"An Imperial Pilsner in collaboration with beer writers. Tradition. Homage. Revolution. We wanted to showcase the awesome backbone of the Czech brewing tradition, the noble Saaz hop, and also tip our hats to the modern beers that rock our world, and the people who make them.","image_url":"https://images.punkapi.com/v2/5.png","abv":7.2,"ibu":59,"target_fg":1027,"target_og":1069,"ebc":10,"srm":5,"ph":4.4,"attenuation_level":67,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":66,"unit":"celsius"},"duration":70}],"fermentation":{"temp":{"value":10,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Lager Malt","amount":{"value":6.63,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.38,"unit":"kilograms"}}],"hops":[{"name":"Saaz","amount":{"value":60,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Saaz","amount":{"value":60,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Saaz","amount":{"value":60,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast Pilsner Lager 2007™"},"food_pairing":["Vietnamese squid salad","Chargrilled corn on the cob with paprika butter","Strawberry and rhubarb pie"],"brewers_tips":"Make sure you have a big enough yeast starter to ferment through the OG and lager successfully.","contributed_by":"Sam Mason "}] +""" + + static let multipleFirst = """ +[{"id":26,"name":"Skull Candy","tagline":"Pacific Hopped Amber Bitter.","first_brewed":"02/2010","description":"The first beer that we brewed on our newly commissioned 5000 litre brewhouse in Fraserburgh 2009. A beer with the malt and body of an English bitter, but the heart and soul of vibrant citrus US hops.","image_url":"https://images.punkapi.com/v2/keg.png","abv":3.5,"ibu":33,"target_fg":1012,"target_og":1038,"ebc":50,"srm":25,"ph":4.4,"attenuation_level":68.4,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":2.81,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Crystal 120","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Cascade","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Cascade","amount":{"value":18.8,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":18.8,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":31.3,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Haggis bon bons","Rosemary and lemon roast chicken","Oatmeal and cranberry cookies"],"brewers_tips":"Make sure your hops are well broken up and mixed in when added to the kettle for aroma additions. The wort is not boiling so is not agitating the hops to allow mixing. If the hops aren't steeped properly in the wort you won't get the maximum flavour impact.","contributed_by":"Sam Mason "},{"id":27,"name":"Dog B","tagline":"Cacao, Coffee Chili Anniversary Stout.","first_brewed":"05/2013","description":"Our anniversary stout was based on AB:04, one of our most sought after beers ever. This beer is slightly different each year, with subtle variations coming into play purely down to environmental and fermentation factors. What doesn't change is the rich dark chocolate, bitter coffee and chilli warmth of this monumental Stout.","image_url":"https://images.punkapi.com/v2/27.png","abv":15,"ibu":90,"target_fg":1003,"target_og":1120,"ebc":100,"srm":50,"ph":4.4,"attenuation_level":98,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Based on AB:04, but with added vanilla and 3.5 times the chilli."},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":8,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.38,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.88,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 1","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Honey","amount":{"value":0.7,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":50,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Cascade","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Fuggles","amount":{"value":25,"unit":"grams"},"add":"15","attribute":"bitter"},{"name":"Coffee","amount":{"value":12.5,"unit":"grams"},"add":"15","attribute":"twist"},{"name":"Fuggles","amount":{"value":25,"unit":"grams"},"add":"0","attribute":" aroma"},{"name":"Coffee","amount":{"value":12.5,"unit":"grams"},"add":"0","attribute":"twist"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Blackened cajun beef","Blue cheese","Flourless chocolate cheesecake"],"brewers_tips":"Be really careful when mashing, as this amount of malts can get tough to sparge! Add honey into the boil, and naga chili and vanilla in maturation (soak them in some neutral spirit to sanitise).","contributed_by":"Sam Mason "},{"id":28,"name":"HBC 369","tagline":"Single Hop India Pale Ale – 2012.","first_brewed":"02/2012","description":"HBC 369 brings rich fruity flavours with the tiniest layer of candy coating on top. HBC 369 (the hop) can bring notes of blueberries, pear, and possibly even sweet potato. HBC 369 (the beer) was balanced, with just one hop providing a complex aroma, and a dry bitterness.","image_url":"https://images.punkapi.com/v2/28.png","abv":6.7,"ibu":67,"target_fg":1064,"target_og":1013,"ebc":19,"srm":9.5,"ph":4.4,"attenuation_level":79.7,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":68,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale - Spring Blend","amount":{"value":5.87,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.37,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.19,"unit":"kilograms"}}],"hops":[{"name":"HBC 369","amount":{"value":40,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"HBC 369","amount":{"value":100,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"HBC 369","amount":{"value":250,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Spicy jalapeño & seared steak fajitas","Grilled spicy corn with feta crumbles","Blueberry pie"],"brewers_tips":"HBC 369 is now known as Mosaic!","contributed_by":"Sam Mason "},{"id":29,"name":"10 Heads High","tagline":"Imperial Red Ale.","first_brewed":"04/2013","description":"10 Heads High is loosely based on our awesome 2011 Prototype beer Hops Kill Nazis. This is an uncompromising 7.8% Imperial Red Ale loaded high with American Hops. Think of this as an Imperial India Red Ale, or a super-charged version of 5am Saint. Either way this is a seriously good beer!","image_url":"https://images.punkapi.com/v2/29.png","abv":7.8,"ibu":70,"target_fg":1015,"target_og":1074,"ebc":90,"srm":45,"ph":4.4,"attenuation_level":79.7,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.75,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Chinook","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"bitter"},{"name":"Centennial","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"bitter"},{"name":"Chinook","amount":{"value":62.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":62.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Chinook","amount":{"value":100,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Arrabiata pasta","Mulled cheddar","Toasted almond cake"],"brewers_tips":"Achieve the red colour by using the ratio of Caramalt, Crystal and Dark Crystal malts. The trick is to get the colour, without too much dried fruit character.","contributed_by":"Sam Mason "},{"id":30,"name":"Dana - IPA Is Dead","tagline":"Single Hop India Pale Ale.","first_brewed":"02/2013","description":"Hailing from Slovenia, Dana was originally cross bred from the German Hallertau Magnum and native Slovenian varieties. Like any good faux noble hop should, it infuses a rustic, musty spiciness into a toasty beast of a malt base.","image_url":"https://images.punkapi.com/v2/30.png","abv":6.7,"ibu":70,"target_fg":1015,"target_og":1066,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":77.3,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":5,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Dana","amount":{"value":2.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Dana","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Dana","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Dana","amount":{"value":125,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Spicy Asian-style noodles","Smokey chipotle beef brisket tostada","Sweet potato pie"],"brewers_tips":"Noble hops (and their offspring) have a fundamentally different profile to many other hops, down to their different oil fractions. Chill your hops to retain all of the spicy, delicate volatile hop oils!","contributed_by":"Matt Ball "},{"id":31,"name":"Nanny State","tagline":"Alcohol Free Hoppy Ale.","first_brewed":"08/2009","description":"Brewing a full flavoured craft beer at 0.5% is no easy task. Packed with loads of Centennial, Amarillo, Columbus, Cascade and Simcoe hops, dry hopped to the brink and back and sitting at 55 IBUs, Nanny State is a force to be reckoned with. With a backbone of 8 different specialty malts, Nanny State will tantalise your taste buds and leave you yearning for more.","image_url":"https://images.punkapi.com/v2/31.png","abv":0.5,"ibu":55,"target_fg":1005,"target_og":1007,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":28.6,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":30}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Munich","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.19,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.03,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Rye","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":6.3,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":6.3,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":6.3,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":2.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Centennial","amount":{"value":6.3,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Amarillo","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Cascade","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Ahtanum","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":50,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Cascade","amount":{"value":50,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Ahtanum","amount":{"value":25,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Simcoe","amount":{"value":25,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Columbus","amount":{"value":37.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Earthy mushroom pasta"],"brewers_tips":"Get hops in every stage of the brewing process - mash, run off boil and flame off. There's not too much malt body, so the more hops the better.","contributed_by":"Sam Mason "},{"id":32,"name":"AB:05","tagline":"Belgian Imperial Stout.","first_brewed":"12/2010","description":"Belgian Imperial Stout aged on toasted coconut and cacao. The Belgian yeast strain introduces a whole new dimension to the Imperial Stout style resulting in a beer that resembles a marshmallow toasted on a smouldering barbeque then smothered in dark chocolate. Massively seductive and encapsulating this blacker than midnight beer pours with coffee brown head so thick you could almost stand on it, and with an epic lacing on your glass.","image_url":"https://images.punkapi.com/v2/32.png","abv":12.5,"ibu":40,"target_fg":1030,"target_og":1126,"ebc":180,"srm":90,"ph":4.4,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Toasted coconut flakes: 75g, Cacao Nibs: 25g"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":10,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 1","amount":{"value":0.94,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.94,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.88,"unit":"kilograms"}},{"name":"Pale Crystal","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.63,"unit":"kilograms"}}],"hops":[{"name":"First Gold","amount":{"value":50,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"First Gold","amount":{"value":50,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 3522 - Belgian Ardennes™"},"food_pairing":["Venison with cacao nibs","Apple upside-down cake","Toffee marshmallow pie"],"brewers_tips":"Add the coconut and cacao nibs after primary fermentation and let infuse for at least 6 months at a low temperature.","contributed_by":"Sam Mason "},{"id":33,"name":"Sorachi Ace","tagline":"Single Hop IPA Series - 2011.","first_brewed":"01/2011","description":"A hop that tastes of bubble gum? Seriously? No, we did not believe it either. But it does! This is one unique, son of a bitch of a hop. Lemony, deep, musty with a smoothness that belies its power. This hop is lemony like a lemon who was angry earlier but is now tired because of all the rage. This hop of Japanese origin is best enjoyed trying to make sushi from your gold fish, or trying to persuade your girlfriend (or boyfriend maybe) to dress up as a Geisha for Valentine’s Day.","image_url":"https://images.punkapi.com/v2/33.png","abv":7.5,"ibu":75,"target_fg":1013,"target_og":1068,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":82.1,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Xpale","amount":{"value":6.38,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.25,"unit":"kilograms"}}],"hops":[{"name":"Sorachi Ace","amount":{"value":14.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Sorachi Ace","amount":{"value":20,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Sashimi","Grilled salmon with a herb and citrus infused butter","Basil, lemon and pine nut angel hair pasta with grilled chicken"],"brewers_tips":"Sorachi Ace is hop best handled with care. Too much and your beer may taste like dill pickle and lemons.","contributed_by":"Sam Mason "},{"id":34,"name":"Bourbon Baby","tagline":"Barrel-Aged Scotch Ale.","first_brewed":"01/2014","description":"Santa Paws Scotch ale aged in bourbon barrels - light, dry and toasty, with vanilla, hints of chocolate and ginger biscuit, and a faint spicy hoppiness.","image_url":"https://images.punkapi.com/v2/34.png","abv":5.8,"ibu":35,"target_fg":1005,"target_og":1049,"ebc":44,"srm":22,"ph":4.4,"attenuation_level":90,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":1.75,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.44,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.56,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":0.56,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Weyermann Beech Smoked","amount":{"value":0.06,"unit":"kilograms"}}],"hops":[{"name":"First Gold","amount":{"value":18.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Hallertauer Mittelfrüh","amount":{"value":6,"unit":"grams"},"add":"middle","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Blackened cajun beef","Pulled pork","Millionaire's shortbread"],"brewers_tips":"Use bourbon-soaked oak chips in secondary to achieve barrel character.","contributed_by":"Ali Skinner "},{"id":35,"name":"Berliner Weisse With Raspberries And Rhubarb - B-Sides","tagline":"Fruity Berliner Weisse.","first_brewed":"11/2015","description":"Tart, dry and acidic with a punch of summer berry as rhubarb crumble.","image_url":"https://images.punkapi.com/v2/keg.png","abv":3.6,"ibu":8,"target_fg":1007,"target_og":1040,"ebc":null,"srm":null,"ph":3.2,"attenuation_level":83,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":60,"unit":"celsius"},"duration":10},{"temp":{"value":65,"unit":"celsius"},"duration":30},{"temp":{"value":72,"unit":"celsius"},"duration":10},{"temp":{"value":78,"unit":"celsius"},"duration":5}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Raspberries in the boil, rhubarb at maturation. Soured naturally using the kettle souring technique, Raspberries at middle"},"ingredients":{"malt":[{"name":"Propino Pale Malt","amount":{"value":1.63,"unit":"kilograms"}},{"name":"Wheat Malt","amount":{"value":1.63,"unit":"kilograms"}},{"name":"Propino Pale Malt for kettle souring","amount":{"value":0.03,"unit":"kilograms"}},{"name":"Acidulated Malt for kettle souring","amount":{"value":0.03,"unit":"kilograms"}}],"hops":[{"name":"Bramling Cross","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"bitter"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Grilled salmon","Mac and cheese fries","Cheesecake with raspberry coulis"],"brewers_tips":"Fruits added at the end of the boil for 10 mins and additional added in maturation. Boil for no more than 15 mins.","contributed_by":"Sam Mason "},{"id":36,"name":"Shipwrecker Circus (w/ Oskar Blues)","tagline":"American Barley Wine - Oskar Blues Collab.","first_brewed":"09/2013","description":"In collaboration with the awesome Oskar Blues from Colorado, we created this big, twisted 10.5% American style barley wine. Big boozy aromas and a sweet viscosity, packed in with some heavy-hitting C-hops, for an intense bitterness to balance this full-bodied malt monster.","image_url":"https://images.punkapi.com/v2/36.png","abv":10.5,"ibu":85,"target_fg":1022,"target_og":1102,"ebc":64,"srm":32,"ph":4.4,"attenuation_level":102,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":9.35,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":1,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.06,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":50,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Cascade","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Citra","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Cascade","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Cascade","amount":{"value":125,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Chinook","amount":{"value":125,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Citra","amount":{"value":125,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Stilton","Pan seared steak","Dark Chocolate Fondant"],"brewers_tips":"Age this beer in the cellar for a few months to allow the warm alcohol flavours to reduce.","contributed_by":"Ali Skinner "},{"id":37,"name":"Zephyr","tagline":"There’s A Storm Brewing.","first_brewed":"10/2008","description":"A 9.2% Double IPA aged for 21 months in a 1965 Invergordon cask with 30 kg of fresh highland strawberries. This beer is a riot of whisky, caramel and strawberry, all tempered by a toe curling bitterness enducing rapture in all who taste it. Who needs champagne?","image_url":"https://images.punkapi.com/v2/37.png","abv":12.5,"ibu":125,"target_fg":1016,"target_og":1087,"ebc":40,"srm":20,"ph":4.4,"attenuation_level":81.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Oak chips: 15g, Fresh strawberries: 3kg"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.3,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.29,"unit":"kilograms"}}],"hops":[{"name":"Columbus Extract","amount":{"value":31,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":19.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":19.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Centennial","amount":{"value":19.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":19.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Columbus","amount":{"value":19.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":19.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":115.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Columbus","amount":{"value":96,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Simcoe","amount":{"value":96,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Amarillo","amount":{"value":77,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Poached eggs and smoked salmon","Salt and pepper squid","Key Lime Pie"],"brewers_tips":"Rack into a secondary fermenter and add your strawberries. Use a blow-off rather than an airlock as the fermentation can get pretty wild as the yeast starts using the sugar from the strawberries.","contributed_by":"Sam Mason "},{"id":38,"name":"Belgian Trappist","tagline":"Unleash the Yeast Series.","first_brewed":"09/2013","description":"Our Unleash the Yeast series was an epic experiment into the differences in aroma and flavour provided by switching up your yeast. We brewed up a wort with a light caramel note and some toasty biscuit flavour, and hopped it with Amarillo and Centennial for a citrusy bitterness. Everything else is down to the yeast. Abbey style yeasts add distinctive spicy and fruity notes, and dry out the finished beer.","image_url":"https://images.punkapi.com/v2/38.png","abv":6.3,"ibu":55,"target_fg":1012,"target_og":1060,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":80,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":25,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.58,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.25,"unit":"kilograms"}}],"hops":[{"name":"Centennial","amount":{"value":5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Amarillo","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Centennial","amount":{"value":17.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":17.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"WLP500 Monastery Ale"},"food_pairing":["Roast beef with spicy jus","Ginger bread cookies","Orange tart"],"brewers_tips":"Play around with the fermentation temperature to get the best flavour profile from the individual yeasts.","contributed_by":"Ali Skinner "},{"id":39,"name":"Kohatu - IPA Is Dead","tagline":"Single Hop India Pale Ale.","first_brewed":"02/2014","description":"As you’d expect from a New Zealand hop variety, Kohatu contributes bags of tropical fruit, but with loads of lime notes, & pineapple hits. Seriously fruity, with sweet, juicy melon and stonefruit notes.","image_url":"https://images.punkapi.com/v2/39.png","abv":7.2,"ibu":70,"target_fg":1012,"target_og":1067,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":82.1,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":5.65,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.06,"unit":"kilograms"}}],"hops":[{"name":"Kohatu","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Kohatu","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Kohatu","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Kohatu","amount":{"value":250,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Tuna sushi roll with spicy mayonnaise sauce","Thai green curry","Pineapple upside down cake"],"brewers_tips":"New Zealand hops are in short supply - club together with other brewers to try and get hold of some, or ask your local brewery if you can buy small amounts from them.","contributed_by":"Sam Mason "},{"id":40,"name":"Hello My Name is Vladimir","tagline":"Limonnik Infused Imperial IPA (Not for Gays).","first_brewed":"01/2014","description":"A Limonnik-infused, triple dry- hopped double IPA. Dry berry tartness and intense citrus hop character meld with a dry bready malt base, boosted by a hint of alcohol warmth. This beer was brewed as a protest against the anti-LGBT legislation in Russia surrounding the Sochi Olympics.","image_url":"https://images.punkapi.com/v2/40.png","abv":8.2,"ibu":70,"target_fg":1013,"target_og":1076,"ebc":16,"srm":8,"ph":4.4,"attenuation_level":83,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Fruit in the boil, berries in the fermenter. Limonnik Berries: 2.5, Twist."},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":5.77,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.63,"unit":"kilograms"}}],"hops":[{"name":"Citra","amount":{"value":4,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Citra","amount":{"value":37.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Citra","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Blackberry Concentrate","amount":{"value":62.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Sour Cherry Puree","amount":{"value":250,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":112.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Mosaic","amount":{"value":200,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Centennial","amount":{"value":187.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Russian mini pork pies","Beef Stroganoff","Chocolate and fruit cake"],"brewers_tips":"If you can't get hold of Limonnik berries, rose hips make an accessible alternative!","contributed_by":"Ali Skinner "},{"id":41,"name":"AB:17","tagline":"Three Coffee Rye Imperial Porter.","first_brewed":"10/2014","description":"A triple whammy of coffee from HasBean gives our 17th Abstrakt concept beer an intense and roasty, dark mocha character. We brewed with espresso in the mash, cafetiere in the boil, and whole roast beans in the whirlpool and the fermenter.","image_url":"https://images.punkapi.com/v2/41.png","abv":10.7,"ibu":100,"target_fg":1025,"target_og":1105,"ebc":300,"srm":150,"ph":4.3,"attenuation_level":76.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Coffee: 25g at end, Coffee: 25g at end, Dark Muscavado Sugar: 250g at end"},"ingredients":{"malt":[{"name":"Pale Ale","amount":{"value":9,"unit":"kilograms"}},{"name":"Rye","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.88,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 1","amount":{"value":0.25,"unit":"kilograms"}}],"hops":[{"name":"CO2 Extract","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":50,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["12hr smoked brisket","Chocolate pistachio cakes","Dulche de leche"],"brewers_tips":"Use freshly ground coffee for the best aromatic hit.","contributed_by":"Sam Mason "},{"id":42,"name":"Hardcore IPA","tagline":"Explicit Imperial Ale. Citrusy. Resinous. Intense.","first_brewed":"12/2009","description":"Pounding a triple payload of the biggest North American hops humanity has devised, braced by a backbone of caramel malt, this beer is deep, astringent and resinous, pushing to the extremes of lupulin thresholds. There’s nothing inscrutable going on; no mystery in the backstory. It doesn’t seek to be understood. A beer incapable of empathy; only hop overload.","image_url":"https://images.punkapi.com/v2/42.png","abv":9.2,"ibu":125,"target_fg":1016,"target_og":1085,"ebc":40,"srm":20,"ph":4.4,"attenuation_level":81.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.4,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.29,"unit":"kilograms"}}],"hops":[{"name":"Columbus Extract","amount":{"value":30.8,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":19.2,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":19.2,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Centennial","amount":{"value":19.2,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":19.2,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Columbus","amount":{"value":19.2,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":19.2,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":19.2,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":115.4,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Columbus","amount":{"value":96.2,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Simcoe","amount":{"value":96.2,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Amarillo","amount":{"value":76.9,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Spicy wings with blue cheese dip","Pan seared scallops with a chilli sauce","Creamy chocolate and caramel cheesecake"],"brewers_tips":"There are so much hops in this beer it may break your gear! Watch out for the end of casting (or knockout for our American brethern), you don’t want to pull too much trub into the fermenter.","contributed_by":"Sam Mason "},{"id":43,"name":"American Wheat","tagline":"Hoppy American Wheat.","first_brewed":"07/2014","description":"A luscious blend of peach, blood orange and banana to make a suitably refreshing beverage that happily straddles the Atlantic.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.5,"ibu":17,"target_fg":1013,"target_og":1047,"ebc":10,"srm":5,"ph":5.3,"attenuation_level":72,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":64,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":2.13,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":2.5,"unit":"kilograms"}},{"name":"Pale Crystal","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Ahtanum","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Ahtanum","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1010 American Wheat™"},"food_pairing":["Strawberry and citrus salad","Fish corn tacos with pomegranate salsa","Summer berry fruit parfait"],"brewers_tips":"Using a starter to get your yeast as vibrant and healthy as possible will make all the difference here.","contributed_by":"Sam Mason "},{"id":44,"name":"Dog Wired (w/8 Wired)","tagline":"New Zealand Imperial Pilsner.","first_brewed":"06/2013","description":"Brewed in collaboration with Soren from New Zealand’s stellar 8-Wired brewery, this is an Imperial Pilsner featuring two of our favourite New Zealand hops: Nelson Sauvin and Motueka. Sitting at a dangerously drinkable 7.1% ABV there’s a touch of Munich malt which gives this beer that little extra caramel biscuit bite to compliment the lip smackingly tropical hops. Expect an all out NZ hoppy riot.","image_url":"https://images.punkapi.com/v2/44.png","abv":7.1,"ibu":65,"target_fg":1010,"target_og":1065,"ebc":13,"srm":6.5,"ph":4.4,"attenuation_level":85,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":64,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":9,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.7,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Acidulated Malt","amount":{"value":0.63,"unit":"kilograms"}}],"hops":[{"name":"Nelson Sauvin","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Motueka","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Nelson Sauvin","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Motueka","amount":{"value":10,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Nelson Sauvin","amount":{"value":20,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Motueka","amount":{"value":20,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Motueka","amount":{"value":100,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Nelson Sauvin","amount":{"value":87.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 2007 - Pilsen Lager™"},"food_pairing":["Spiced and blackened cajun chicken","Pork belly vindaloo","Rhubarb pie"],"brewers_tips":"Hold the mash for longer at 63-64°C to get more fermentability from the wort.","contributed_by":"Sam Mason "},{"id":45,"name":"The Physics","tagline":"Laid Back Amber Beer.","first_brewed":"04/2007","description":"A hoppy Amber Ale that won World's Best Amber Beer in the World Beer Awards 2007. Malt and hops are in perfect harmony in this incredibly balanced beer. Biscuity, bitter and packing a surprisingly hoppy punch, this beer ultimately morphed into 5AM Saint.","image_url":"https://images.punkapi.com/v2/45.png","abv":5,"ibu":47,"target_fg":1010,"target_og":1048.5,"ebc":65,"srm":32.5,"ph":4.4,"attenuation_level":79.4,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.06,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Crystal 120","amount":{"value":0.23,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.94,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Bramling Cross","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":50,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Barbecue pulled pork on sourdough bread","Roast turkey with a honey and herb marinade and roasted vegetables","Banana walnut loaf with chocolate chips"],"brewers_tips":"Keep the fermentation temperature as close to 19°C as possible. This will ensure the yeast creates a more neutral flavour profile, allowing the hops to really shine through.","contributed_by":"Sam Mason "},{"id":46,"name":"Anarchist Alchemist","tagline":"Triple Hopped Triple Ipa.","first_brewed":"03/2012","description":"About as far as you can push an IPA; Anarchist Alchemist packs in three times the malt and three of our favourite hops. Nelson Sauvin, Amarillo and Centennial bring a range of flavours, touching on tropical fruit, white grape, tangerine, grapefruit, pine, spiced orange... the list goes on!","image_url":"https://images.punkapi.com/v2/46.png","abv":16.5,"ibu":20.5,"target_fg":1000,"target_og":1112,"ebc":20,"srm":10,"ph":4.4,"attenuation_level":100,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":20,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":12.5,"unit":"kilograms"}}],"hops":[{"name":"Nelson Sauvin","amount":{"value":6.25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Nelson Sauvin","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Nelson Sauvin","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Amarillo","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Centennial","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Blue cheese & onion tart","Goan goat curry","Sugar-poached kumquat rice pudding"],"brewers_tips":"The biggest challenge with this beer is getting it to ferment out entirely. Hold mash temp at 65°C for 90 mins to ensure maximum fermentability. Use super high gravity yeast or champagne yeast to achieve the last few gravity points.","contributed_by":"Sam Mason "},{"id":47,"name":"AB:15","tagline":"Salted Caramel Popcorn Strong Ale.","first_brewed":"03/2013","description":"A salted caramel popcorn Imperial Ale. Bourbon and Rum barrel aged, this 12.8% ale has complex and twisting flavours. Bitter caramel, wood, smoke, spice, treacle and vanilla are all present and intertwine against a smooth and lightly chewy mouthfeel. The salted caramel popcorn lends subtle hints of a smoky brininess.","image_url":"https://images.punkapi.com/v2/47.png","abv":12.8,"ibu":50,"target_fg":1020,"target_og":1096,"ebc":111,"srm":55.5,"ph":4.4,"attenuation_level":79.17,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":68,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Adding popped popcorn into the mash, then barrel ageing in fresh bourbon barrels"},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":6.5625,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.3125,"unit":"kilograms"}},{"name":"Munich","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.3125,"unit":"kilograms"}},{"name":"Popcorn","amount":{"value":0.00625,"unit":"kilograms"}}],"hops":[{"name":"Sorachi Ace","amount":{"value":62.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Crispy bacon on flat bread","Glazed ham with crackling coating","Popcorn caramel and chocolate cake"],"brewers_tips":"By soaking some oak chips in bourbon, then steeping in the beer you not only get an authentic Bourbon taste - the beer will also gain ABV! Add salt to taste, too much will totally ruin the balance of the beer.","contributed_by":"Sam Mason "},{"id":48,"name":"Goldings - IPA Is Dead","tagline":"Single Hop India Pale Ale.","first_brewed":"02/2013","description":"This is East Kent Goldings re- invented and re-imagined and shows just what can be done with English hops if you use enough of them. In this amped up Goldings reincarnation expect to be slammed with floral lavender, a fruity riot of blackberries and spiced pears, bubblegum, plums and the illusion of thyme.","image_url":"https://images.punkapi.com/v2/48.png","abv":6.7,"ibu":70,"target_fg":1015,"target_og":1066,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":77.3,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":5,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Goldings","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Goldings","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Goldings","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Goldings","amount":{"value":125,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Rosemary and thyme marinated venison","Fish and chips","Lavender chocolate chip cookies"],"brewers_tips":"Take a read through each year’s hop harvest that is available. Some years are better than others.","contributed_by":"Matt Ball "},{"id":49,"name":"AB:14","tagline":"Oak-Aged Imperial Weizenbock.","first_brewed":"02/2013","description":"Think banoffee pie; loads of creamy sweet banana, and sticky warm toffee. This beer is super complex, and one for the sweet-toothed!","image_url":"https://images.punkapi.com/v2/49.png","abv":10,"ibu":30,"target_fg":1016,"target_og":1094,"ebc":20,"srm":10,"ph":4.4,"attenuation_level":83,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":120}],"fermentation":{"temp":{"value":23,"unit":"celsius"}},"twist":"Oak chips: 25g at end"},"ingredients":{"malt":[{"name":"Wheat","amount":{"value":5,"unit":"kilograms"}},{"name":"Extra Pale","amount":{"value":2,"unit":"kilograms"}},{"name":"Munich","amount":{"value":2,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":1.13,"unit":"kilograms"}}],"hops":[{"name":"Bramling Cross","amount":{"value":30,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Saaz","amount":{"value":15,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Saaz","amount":{"value":15,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 3638 - Bavarian Wheat™"},"food_pairing":["Sweet pork Chinese dumplings","Caramelised onion venison burger","Banoffee pie"],"brewers_tips":"Boil for even longer to get more caramelised flavours in the beer.","contributed_by":"Sam Mason "},{"id":50,"name":"Lost Dog (w/Lost Abbey)","tagline":"Rum-Aged Imperial Porter - Lost Abbey Collab.","first_brewed":"11/2011","description":"Our first beer aged in rum casks, Lost Dog saw us brew a collaboration imperial porter with our friends at Lost Abbey. The base beer was packed with toffee, chocolate and roasty notes, balanced with a subtle spicy hop character. The rum casks add a warming, spiced vanilla edge.","image_url":"https://images.punkapi.com/v2/50.png","abv":10,"ibu":35,"target_fg":1012,"target_og":1080,"ebc":80,"srm":40,"ph":4.4,"attenuation_level":85,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Aged in rum casks for 12 months"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.69,"unit":"kilograms"}},{"name":"Pale Chocolate","amount":{"value":0.23,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.7,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.35,"unit":"kilograms"}},{"name":"Oats","amount":{"value":0.47,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.35,"unit":"kilograms"}}],"hops":[{"name":"First Gold","amount":{"value":35,"unit":"grams"},"add":"start","attribute":"bitter"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Beef satay skewers","Venison & cranberry pie","Blackberry mocha gateaux"],"brewers_tips":"Ageing in barrels brings the ABV up. Recreate rum cask ageing by soaking oak chips in rum then adding to the maturing beer.","contributed_by":"Sam Mason "}] +""" + + static let multipleSecond = """ +[{"id":51,"name":"TM10","tagline":"Liquid Art.","first_brewed":"04/2010","description":"Brewed for the Tate Modern’s 10th Anniversary. A saison style beer brewed with ginger and orange peel. Very limited batch of 4000 cork and caged bottles with a silk screened label designed by Johanna Basford. Only available at the Tate Modern.","image_url":"https://images.punkapi.com/v2/51.png","abv":5.5,"ibu":20,"target_fg":1005,"target_og":1048,"ebc":14,"srm":7,"ph":4.2,"attenuation_level":89.6,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":63,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":22,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Pale Ale Malt","amount":{"value":5.3,"unit":"kilograms"}}],"hops":[{"name":"Bobek","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Bobek","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Bobek","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Ginger","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Orange Peel","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 3711 - French Saison™"},"food_pairing":["Tom yum soup","Andhra chicken pickle curry","Butterscotch tart"],"brewers_tips":"For a fresh and fiery hit, put some ginger into the cold conditioning phase as well.","contributed_by":"Sam Mason "},{"id":52,"name":"Paradox Islay","tagline":"Ubiquitous Imperial Stout.","first_brewed":"04/2007","description":"In 2006 James and Martin hijacked a beer dinner run by Michael Jackson, the acclaimed beer and whisky writer, and convinced him to taste one of their home brews. This was a defining moment in BrewDog prehistory, and that beer was the first incarnation of the ubiquitous Paradox. Aged in a variety of casks over the years, Paradox is dark, decadent and encapsulating. Can be enjoyed fresh; phenomenal when aged.","image_url":"https://images.punkapi.com/v2/52.png","abv":10,"ibu":55,"target_fg":1014,"target_og":1090,"ebc":300,"srm":152,"ph":4.4,"attenuation_level":84.4,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Try ageing on oak chips, infusing with rum raisins, or vanilla pods"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.5,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.55,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.33,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.35,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.55,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 1","amount":{"value":0.18,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.33,"unit":"kilograms"}}],"hops":[{"name":"Columbus","amount":{"value":75,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Saaz","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Ancho chilli beef taco","Chocolate gateaux","Rum poached pears with dark chocolate sauce"],"brewers_tips":"The beauty of this beer is in how brilliantly it lends itself to infusing or ageing. Experiment with different additions when the beer is ageing, taste it regularly to gauge its progress, and make sure you package it at its peak.","contributed_by":"Sam Mason "},{"id":53,"name":"Baby Dogma","tagline":"Session Scotch Ale.","first_brewed":"09/2013","description":"A baby Scotch ale with dry and toasty malt flavours and hints of smoke. Toffee, biscuit and fudge abound with a spicy bitterness from the pan-global hops.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.5,"ibu":35,"target_fg":1013,"target_og":1048,"ebc":40,"srm":20,"ph":4.4,"attenuation_level":72.9,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":66,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":1.75,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.48,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.56,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":0.56,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Weyermann Beech Smoked","amount":{"value":0.06,"unit":"kilograms"}}],"hops":[{"name":"First Gold","amount":{"value":18.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Hallertauer Mittelfrüh","amount":{"value":6,"unit":"grams"},"add":"start","attribute":"bitter"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["French onion soup","Braised pheasant","Caramel sauce and hot fudge"],"brewers_tips":"The addition of Weyermann Beech Smoked malt creates a beer with a delicate smoke character.","contributed_by":"Ali Skinner "},{"id":54,"name":"Albino Squid Assasin","tagline":"Red Rye IPA","first_brewed":"11/2015","description":"This tentacled terminator packs a punch - ten punches to be precise. Each hop addition adds to the intense layers of depth in this red rye IPA. Toasty caramel & cinder toffee from crystal malts, cacao richness from intensely roasted malt and the spiciness of rye. Zesty pithiness from Citra and the robust resin of Chinook. This small batch exclusive brew is up-front intensity matched with twisted complexity. The can features awesome custom art from Joe Wilson.","image_url":"https://images.punkapi.com/v2/54.png","abv":7.4,"ibu":65,"target_fg":1012,"target_og":1069,"ebc":60,"srm":30,"ph":4.2,"attenuation_level":82.6,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Pale Ale","amount":{"value":5,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 1","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Rye","amount":{"value":0.5,"unit":"kilograms"}}],"hops":[{"name":"Magnum","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Citra","amount":{"value":6.25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Chinook","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":18.75,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Chinook","amount":{"value":100,"unit":"grams"},"add":"fv","attribute":"aroma"},{"name":"Citra","amount":{"value":75,"unit":"grams"},"add":"fv","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Rocket and mozzarella salad with a cracked pepper dressing","Fried halibut with sweet potato fritters","Grapefruit and blood orange tart"],"brewers_tips":"20% specialty malts in this grist can create problems in the run off. Be careful not to pull the bed down onto the plates.","contributed_by":"Matt Ball "},{"id":55,"name":"Amarillo - IPA Is Dead","tagline":"Single Hop India Pale Ale.","first_brewed":"01/2013","description":"Citrus fruit. Lots of citrus fruit. Think blood orange, orange zest and grapefruit, tangerine and lemon; the fruit is balanced by floral notes in the most classic of new wave IPA hops. Amarillo adds a zesty, pithy character that sits beautifully alongside hints of toffee and honeycomb.","image_url":"https://images.punkapi.com/v2/55.png","abv":7.2,"ibu":70,"target_fg":1012,"target_og":1067,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":82.1,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.88,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.06,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Amarillo","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":250,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Bratwurst sausage with spicy mustard","Fried American bacon with chilli flakes added to the top","Dark chocolate chip cookies"],"brewers_tips":"Use the freshest hops for the most impact. It seems obvious but in a single hop beer, you want the hops to be at their best.","contributed_by":"Sam Mason "},{"id":56,"name":"Black Eyed King Imp","tagline":"Barrel-Aged Prototype Cocoa Psycho.","first_brewed":"11/2012","description":"An early Cocoa Psycho recipe that we loved, but didn't fit what we were looking for. We locked this chocolate coffee stout away in barrels for two years, imparting toasted marshmallow, spicy vanilla, molasses and boozy warmth.","image_url":"https://images.punkapi.com/v2/56.png","abv":9.5,"ibu":85,"target_fg":1022,"target_og":1095,"ebc":250,"srm":125,"ph":4.4,"attenuation_level":76.8,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":50}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":"Coffee Beans: 12.5g at end, Lactose: 125g"},"ingredients":{"malt":[{"name":"Extra Pale - Spring Blend","amount":{"value":6.25,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":1.56,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Brown","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Magnum","amount":{"value":62.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Beef chilli made with cocoa powder","Dark chocolate covered bacon","Rich espresso tiramisu"],"brewers_tips":"There is a huge amount of roasted malts in this grist. Be careful not to pulverise the malt into powder during the milling process.","contributed_by":"Sam Mason "},{"id":57,"name":"Prototype 27","tagline":"Vibrant Smoky Pink IPA.","first_brewed":"04/2010","description":"Hardcore IPA with raspberries aged in Caol Ila casks. Full-bodied and compelling, the robust malt base provides an initial layer of honey, cinnamon and biscuity malt sweetness. Soon the Scottish berries are in on the act, a dominating tug of war between sweet and tart with an overbearing zest. As the beer slips back across your tongue the hops demand and definitely get your attention. At 100 IBUs the bitterness smashes into the back of your throat as the resinous, spiced orange peel flavours add depth to the berry fruitiness.","image_url":"https://images.punkapi.com/v2/57.png","abv":9.2,"ibu":149,"target_fg":1014,"target_og":1083,"ebc":19.5,"srm":9.8,"ph":4.4,"attenuation_level":83,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Pale Ale Malt","amount":{"value":8.13,"unit":"kilograms"}},{"name":"Crystal Malt 150","amount":{"value":0.28,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.56,"unit":"kilograms"}}],"hops":[{"name":"Columbus","amount":{"value":50,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":50,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Centennial","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Columbus","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Strong blue cheese","Cranachan","Chicago style hot links"],"brewers_tips":"Soak some oak chips in Caol Ila whisky to get barrel character. Freeze raspberries before adding them to secondary.","contributed_by":"Sam Mason "},{"id":58,"name":"Coffee Imperial Stout","tagline":"Beats a Cup of Joe.","first_brewed":"11/2008","description":"This beer was released as both as \"Danish Beerhouse Coffee Imperial Stout\" and \"BrewDog Coffee Imperial Stout\". Deep, dark, roasted flavours make this a perfect Sunday brunch beer.","image_url":"https://images.punkapi.com/v2/58.png","abv":9,"ibu":65,"target_fg":1019,"target_og":1080,"ebc":97,"srm":49,"ph":4.4,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":64,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Coffee added after boil. Aged on French oak chips., Dark muscovado sugar: 312.5g for 20mins"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.5,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Roast Barley","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee","amount":{"value":9.4,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee","amount":{"value":9.4,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Gooey chocolate brownies","Chicken fried steak with cheesy mash","Spicy chicken empanadas"],"brewers_tips":"Grind the coffee as if making an espresso to really get the most out of it.","contributed_by":"Sam Mason "},{"id":59,"name":"Mandarina Bavaria - IPA Is Dead","tagline":"Single Hop India Pale Ale.","first_brewed":"03/2015","description":"From the central European plains of Germany, comes something very different. A blast of tangerine and orange, Mandarina Bavaria brings a highly distinctive backbone of flavour. This is down to its parent – Cascade – and a frankly enormous 70% myrcene oil content. If equate Germany solely with earthy, spicy Noble hops, Mandarina Bavaria will make you think again.","image_url":"https://images.punkapi.com/v2/59.png","abv":7.2,"ibu":100,"target_fg":1010,"target_og":1064,"ebc":12,"srm":6,"ph":4.4,"attenuation_level":84,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.39,"unit":"kilograms"}}],"hops":[{"name":"Mandarina Bavaria","amount":{"value":41.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Mandarina Bavaria","amount":{"value":41.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Mandarina Bavaria","amount":{"value":41.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Lavender and thyme roast beef","Spicy kung po chicken","Caramel and rose essence cheesecake"],"brewers_tips":"We've mentioned the importance of fresh hops previously but this one really demands that your hops are the absolute freshest.","contributed_by":"Sam Mason "},{"id":60,"name":"Dogma","tagline":"Revamped Wee Heavy. Luscious. Malty. Fruity.","first_brewed":"07/2013","description":"Brewed with over ten different types of malt, and blended together with Scottish heather honey, it is a pantheon to the gods of intricacy and nuance; a beer that celebratesa confluence of ideas. Complex, indulgent and encapsulating, Dogma gives more than a cursory nod to history, to make you ponder the very nature of beer itself.","image_url":"https://images.punkapi.com/v2/60.png","abv":7.5,"ibu":30,"target_fg":1023,"target_og":1080,"ebc":46,"srm":23,"ph":4.5,"attenuation_level":70,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":12,"unit":"celsius"}},"twist":"Heather Honey: 125g"},"ingredients":{"malt":[{"name":"Pale Ale","amount":{"value":3.5,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.75,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Smoked","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Brown","amount":{"value":0.25,"unit":"kilograms"}}],"hops":[{"name":"Saaz","amount":{"value":75,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"First Gold","amount":{"value":10,"unit":"grams"},"add":"start","attribute":"bitter"}],"yeast":"Wyeast 2007 - Pilsen Lager™"},"food_pairing":["Mature cheddar with red onion chutney","Honey glazed ham","Chocolate caramel drizzled sponge cake"],"brewers_tips":"There's a lot of specialty malt in the mash. Make sure you take the run off nice and steady – increase the flow too much and pull in the bed at your peril.","contributed_by":"Ali Skinner "},{"id":61,"name":"Magic Stone Dog (w/Magic Rock & Stone Brewing Co.)","tagline":"Session Farmhouse IPA - Stone / Magic Rock Collab.","first_brewed":"06/2014","description":"A session IPA brewed with a diverse grain bill, hopped with Simcoe and Amarillo and fermented with saison yeast, for an incredible level of depth in a low ABV beer. Spicy, fruity, complex, refreshing and dry.","image_url":"https://images.punkapi.com/v2/61.png","abv":4.6,"ibu":30,"target_fg":1008,"target_og":1043,"ebc":15,"srm":7.5,"ph":4.4,"attenuation_level":81.4,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":23,"unit":"celsius"}},"twist":"Cumin: 0.5g at end, Caraway: 1g at end, Peppercorns (Pink): 5g at end, Grains of Paradise: 5g at end"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":2.38,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.44,"unit":"kilograms"}},{"name":"Torrified Wheat","amount":{"value":0.44,"unit":"kilograms"}},{"name":"Rye","amount":{"value":0.19,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":0.44,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.19,"unit":"kilograms"}}],"hops":[{"name":"Simcoe","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 3711 - French Saison™"},"food_pairing":["Halibut with caper brown butter","Creamy gorgonzola and satsuma salad","Spicy Daal with garlic naan bread"],"brewers_tips":"Start the fermentation off at 20 ̊C and allow it to rise as high as 25 ̊C. This will increase the fruity character of the yeast.","contributed_by":"Sam Mason "},{"id":62,"name":"AB:08","tagline":"Deconstructed Blonde Imperial Stout.","first_brewed":"11/2011","description":"Flavours and aromas you'd expect from a Stout, but brewed without dark malts. The full mouthfeel comes courtesy of wheat and oats, while smoked malt and the twist additions add the complex flavours normally provided by highly kilned malts.","image_url":"https://images.punkapi.com/v2/62.png","abv":10.43,"ibu":65,"target_fg":1016,"target_og":1095,"ebc":23,"srm":11.5,"ph":4.4,"attenuation_level":83.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Cacao: 25g at FV, Coffee Beans: 37.5g at FV, Oak Chips: 5g at FV, Vanilla Pods: 10 split pods, Liquorice: 5g at FV"},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":9.25,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1.88,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.88,"unit":"kilograms"}},{"name":"Smoked Peaty","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"First Gold","amount":{"value":81.25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"First Gold","amount":{"value":62.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee Beans","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Caramelised scallops with burnt apple puree","Blackened Cajun chicken","Blondies with chocolate fudge sauce"],"brewers_tips":"Add all twist ingredients to Fermentation Vessel once fermentation is complete. Don’t be afraid to add a little at a time and taste as you go. During mashing in first start with pale malt. Afterwards mix all malts evenly. Go with flaked oats during second half of mashing in process.","contributed_by":"Sam Mason "},{"id":63,"name":"Sunk Punk","tagline":"Ocean Fermented Lager.","first_brewed":"09/2011","description":"It's rumoured just a drop can calm the fiercest of storms. A balance of sweet, salt and savoury, citrus, spruce and caramel. Fermented at the bottom of the North Sea, which just so happens to be the perfect temperature for lagers to ferment.","image_url":"https://images.punkapi.com/v2/63.png","abv":7.1,"ibu":68,"target_fg":1010,"target_og":1056,"ebc":14,"srm":7,"ph":4.4,"attenuation_level":82.1,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":10,"unit":"celsius"}},"twist":"Seabuckthorn: 25g at end, Sea Salt: 20g at middle, Rum: 25ml at end"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":5.21,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Ahtanum","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Chinook","amount":{"value":20,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Ahtanum","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Chinook","amount":{"value":30,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Ahtanum","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Nelson Sauvin","amount":{"value":140,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 2007 - Pilsen Lager™"},"food_pairing":["Salt baked cod with lemon and dill butter","Beef, oyster and ale pie","Apple and rosemary tart"],"brewers_tips":"Keep the fermentation temperature as steady as possible to allow the lager yeast to do its thing.","contributed_by":"Sam Mason "},{"id":64,"name":"Sub Hop","tagline":"Hopped-Up Imperial Pilsner.","first_brewed":"06/2014","description":"Brewed for the opening of our first bar in Italy, BrewDog Firenze. A mega-hoppy Imperial Pilsner, with toasty malt complexity and tropical New World hops.","image_url":"https://images.punkapi.com/v2/64.png","abv":8,"ibu":35,"target_fg":1016,"target_og":1077,"ebc":15,"srm":7.5,"ph":4.4,"attenuation_level":79.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":9,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.25,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Dextrose","amount":{"value":0.38,"unit":"kilograms"}}],"hops":[{"name":"Saaz","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Hallertauer Mittelfrüh","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Pacifica","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Pacific Jade","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Pacifica","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Pacific Jade","amount":{"value":75,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Pacifica","amount":{"value":37.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 2007- Pilsen Lager™"},"food_pairing":["Seared lemon and herb salmon","Crab linguine","Almond biscotti"],"brewers_tips":"Sit this beer aside for a month to allow it to mellow.","contributed_by":"Sam Mason "},{"id":65,"name":"Bracken's Porter","tagline":"A Tribute To Our Favourite 4 Pawed Friend.","first_brewed":"03/2013","description":"The beer was named Bracken’s Porter as a tribute to our favourite four pawed friend who sadly passed in 2013. Chocolately, robust, warming, laid back and lots of fun - there are plenty of similarities between the two. Bracken we miss you and we hope you like your beer. Long live the original BrewDog.","image_url":"https://images.punkapi.com/v2/keg.png","abv":5,"ibu":50,"target_fg":1010,"target_og":1049,"ebc":110,"srm":55,"ph":4.4,"attenuation_level":79,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":3.63,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.19,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Black Malt","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Vic Secret","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Bramling Cross","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"aroma"},{"name":"Challenger","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Grilled vegetable and chicken teriyaki skewers","Chilli covered burger (Sloppy Joe)","Candied bacon topped chocolate cheesecake"],"brewers_tips":"Try to replicate London’s highly carbonated water to really emphasise the dark malt profile.","contributed_by":"Sam Mason "},{"id":66,"name":"Tokyo Rising Sun - Lowland","tagline":"A Beautiful Accident.","first_brewed":"06/2009","description":"A forgotten gem in the deepest, darkest corner of the warehouse. Aged in a Lowland whisky cask resulting in decadent chocolate, toasted vanilla, indulgent spiced fruit, a mesmerizingly hypnotic mouthfeel and new layers that emerge on every sip.","image_url":"https://images.punkapi.com/v2/66.png","abv":13.2,"ibu":85,"target_fg":1023,"target_og":1125,"ebc":140,"srm":71,"ph":4.4,"attenuation_level":82.17,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Cranberry: 25g at end, Jasmine: 25g at end, Muscovado sugar: 300g at start, Oak chips soaked in lowland whisky: 15g at dry hop"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.6,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":1.75,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.5,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Chinook","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"WLP099 Super High Gravity Ale"},"food_pairing":["Duck liver paté","Mutton stew","Kirsch chocolate truffles"],"brewers_tips":"Leave on wood for as long as you dare. If possible forget about it for four years.","contributed_by":"Sam Mason "},{"id":67,"name":"Hunter Foundation Pale Ale","tagline":"American Pale Ale.","first_brewed":"05/2012","description":"This straight-up US style pale ale uses some of our favourite hops against a toasty malt base. We brewed this with Sir Tom Hunter at our Fraserburgh brewery - to add a charitable element to your own version, feel free to share this citrusy pale ale with your friends. Or don't, it's your choice.","image_url":"https://images.punkapi.com/v2/67.png","abv":5.4,"ibu":35,"target_fg":1008,"target_og":1050,"ebc":11.5,"srm":5.75,"ph":4.4,"attenuation_level":84,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":63,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":4.3,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.8,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":10,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":15,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":20,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Monterey Jack stuffed grilled jalepenos","Barbecue corn and steak fajita seasoned wrap","Cinnamon & white chocolate churro"],"brewers_tips":"To dry the beer out, mash at a slightly lower temp (62° - 63°C), this will increase the ratio of fermentable sugars in the beer.","contributed_by":"Sam Mason "},{"id":68,"name":"Hype","tagline":"New Zealand Pale Ale.","first_brewed":"08/2007","description":"A perfect pale ale showcase for the tropical profile of New Zealand hops and the intense citrus of US hops.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.1,"ibu":65,"target_fg":1010,"target_og":1042,"ebc":17,"srm":8.5,"ph":4.4,"attenuation_level":76.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":4.02,"unit":"kilograms"}}],"hops":[{"name":"Nelson Sauvin","amount":{"value":2,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Nelson Sauvin","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":2.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Quince cheese","Shredded chicken and mango salsa taquitos","Poached pear"],"brewers_tips":"After the beer has fermented, leave it to rest for 2 – 3 days at the lowest temperature possible (ideally 0 – 2'C). This will allow the flavours to marry together, and will transform it into a balanced and amazing beer.","contributed_by":"Sam Mason "},{"id":69,"name":"AB:16","tagline":"Coffee-Infused Belgian Quad.","first_brewed":"02/2014","description":"On the nose, clove and nutmeg, cafe au lait, subtle dark fruit notes, and hints of candied lemon peel. On the palate, smooth & fruity espresso, milk chocolate, and warm brandy-soaked currants are in the middle of a high-class dance-off against the spicy and peppery Belgian character. The overall impression evokes malt loaf or ginger cake.","image_url":"https://images.punkapi.com/v2/69.png","abv":10.6,"ibu":55,"target_fg":1012,"target_og":1090,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":86.7,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Coffee Beans: 250g FV. Raisins: 90g at end. Dark Sugar:140g at end."},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.75,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Waimea","amount":{"value":15,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Saaz","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Fuggles","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"}],"yeast":"Wyeast 3787 - Trappist High Gravity™"},"food_pairing":["Roasted duck","Gorgonzola and rye nut bread with smoked honey ham","Raspberry coffee cheesecake"],"brewers_tips":"For the traditional cellering, age this beer in vessel or bottle for 2 - 3 months at cellar temperature.","contributed_by":"Ali Skinner "},{"id":70,"name":"Sunmaid Stout","tagline":"Rum & Raisin Imperial Stout.","first_brewed":"12/2011","description":"Brewed by Chris Sartori from Stone Brewing Company in 2010. A dark chocolate stout with dried dark fruit finish. Simcoe provides bitterness with subtle fruity supporting notes, contrasting the chocolate and coffee-laden malt profile. The finish is warming with vanilla and rich dark fruit depth.","image_url":"https://images.punkapi.com/v2/keg.png","abv":10.2,"ibu":50,"target_fg":1102,"target_og":1026,"ebc":197,"srm":100,"ph":4.4,"attenuation_level":74.5,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":55}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Age in whisky casks with rum soaked raisins"},"ingredients":{"malt":[{"name":"Pale Ale - Tipple","amount":{"value":10,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.94,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":0.94,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.56,"unit":"kilograms"}}],"hops":[{"name":"Simcoe","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Challenger","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Lapin aux pruneaux (braised rabbit with prunes)","Gouda cheese","Dark chocolate truffles"],"brewers_tips":"Take small volume of wort out of the run off and steep the raisins in it, then crush them up. This will help to release the dark fruit aromas into the wort.","contributed_by":"Sam Mason "},{"id":71,"name":"Pale - Russian Doll","tagline":"Nesting Hop Bomb.","first_brewed":"08/2014","description":"The levels of hops vary throughout the range. We love hops, so all four beers are big, bitter badasses, but by tweaking the amount of each hop used later in the boil and during dry- hopping, we can balance the malty backbone with some unexpected flavours. Simcoe is used in the whirlpool for all four beers, and yet still lends different characters to each.","image_url":"https://images.punkapi.com/v2/71.png","abv":4,"ibu":35,"target_fg":1010,"target_og":1041,"ebc":45,"srm":22.5,"ph":5.2,"attenuation_level":75.6,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":3.63,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Cascade","amount":{"value":7.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Citra","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":17.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":62.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Cascade","amount":{"value":62.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Centennial","amount":{"value":62.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Citra","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Roast chicken with vegetables and wild rice","Fresh pico de gallo with corn tortilla","Carrot cake"],"brewers_tips":"Create balance through experimentation with the hop amounts and malt backbone.","contributed_by":"Sam Mason "},{"id":72,"name":"Whisky Sour - B-Sides","tagline":"Pilot Brew - Deconstructed Whisky Sour.","first_brewed":"03/2015","description":"Deconstructed whisky sour, reconstructed as a beer.","image_url":"https://images.punkapi.com/v2/keg.png","abv":7,"ibu":20,"target_fg":1021,"target_og":1081,"ebc":12,"srm":6,"ph":3.2,"attenuation_level":74,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":60,"unit":"celsius"},"duration":10},{"temp":{"value":65,"unit":"celsius"},"duration":30},{"temp":{"value":72,"unit":"celsius"},"duration":10},{"temp":{"value":78,"unit":"celsius"},"duration":5}],"fermentation":{"temp":{"value":null,"unit":"celsius"}},"twist":"Kettle Soured"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.88,"unit":"kilograms"}},{"name":"Acidulated Malt","amount":{"value":1.88,"unit":"kilograms"}},{"name":"Wheat Malt","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Rye Malt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Special W","amount":{"value":0.05,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":8.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Citra","amount":{"value":8.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":8.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":1.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Citra","amount":{"value":1.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Simcoe","amount":{"value":1.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Potted fresh & smoked salmon","Spiced nut loaf","Lemon poppyseed donuts"],"brewers_tips":"Lemon poppyseed donuts.","contributed_by":"Sam Mason "},{"id":73,"name":"Black Eyed King Imp - Vietnamese Coffee Edition","tagline":"Vietnamese Coffee Edition.","first_brewed":"12/2014","description":"This is the Vietnamese Coffee Edition. At 12.7% ABV, Black Eyed King Imp is a super intense and twistedly complex brew, with intense notes of sweet vanilla, rich espresso, smooth molasses and bitter chocolate barely contained by the whatever container it's in.","image_url":"https://images.punkapi.com/v2/73.png","abv":12.7,"ibu":85,"target_fg":1038,"target_og":1113.5,"ebc":250,"srm":125,"ph":5.2,"attenuation_level":76.8,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":50}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":"Coffee Beans: 12.5g at end, Lactose: 125g at FV, Bourbon barrel aged"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.25,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Cara","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":1.5625,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Brown","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.3125,"unit":"kilograms"}}],"hops":[{"name":"Magnum","amount":{"value":62.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"bitter"},{"name":"First Gold","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"aroma / bitter"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Bacon sandwich with brown sauce","20hr smoked brisket","Chocolate fudge ice cream"],"brewers_tips":"Buying top notch coffee beans make a huge difference here. Give them a very course grind to get the most out of them.","contributed_by":"Sam Mason "},{"id":74,"name":"Eurotrash","tagline":"Belgian Blonde.","first_brewed":"10/2009","description":"Trashy Blonde with a Belgian Twist. Clove oil, red apples and a drier mouthfeel set this beer apart from its older sister.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.1,"ibu":52,"target_fg":1010,"target_og":1041,"ebc":17,"srm":8.5,"ph":5.2,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":66,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Fermented with Belgian yeast for signature character"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":3.25,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.38,"unit":"kilograms"}}],"hops":[{"name":"Simcoe","amount":{"value":5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":6.3,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":2.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Amarillo","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Motueka","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Motueka","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Amarillo","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Motueka","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 3522 - Belgian Ardennes™"},"food_pairing":["Grilled fish salad","Angelfood cake","Pad Thai"],"brewers_tips":"Don't be scared to let the fermentation temperature climb up another couple of degrees to really emphasize the Belgian character.","contributed_by":"Sam Mason "},{"id":75,"name":"Never Mind The Anabolics","tagline":"Performance-Enhancing India Pale Ale.","first_brewed":"06/2012","description":"Never Mind the Anabolics, a 6.5% India Pale Ale brewed with copious amounts of performance-enhancing natural ingredients. Brewed to commemorate the 2012 Olympics and its merry marketing bandwagon.","image_url":"https://images.punkapi.com/v2/75.png","abv":6.5,"ibu":35,"target_fg":1012,"target_og":1050,"ebc":23,"srm":11.5,"ph":4.4,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":68,"unit":"celsius"},"duration":30}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":"Lycii Berries: 7.5g at end, Ginseng: 5.625g at end, Guarana: 25g at end, Kolabu: 25g at end, Gingko: 6.25g at end, Matcha Tea: 12.5g at end, Maca Powder: 16.25g at end"},"ingredients":{"malt":[{"name":"Extra Pale - Spring Blend","amount":{"value":4.38,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Motueka","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Motueka","amount":{"value":18.75,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Grilled chicken salad with bacon and avocado","Red pepper houmous and flat bread","Matcha green tea cake"],"brewers_tips":"Mix the powders into a paste before adding to the wort kettle. This will prevent the powders from balling up and not bringing the full flavour effect.","contributed_by":"Sam Mason "}] +""" +} diff --git a/Example/Tests/Tests.swift b/Example/Tests/Tests.swift deleted file mode 100644 index 26fbadd..0000000 --- a/Example/Tests/Tests.swift +++ /dev/null @@ -1,28 +0,0 @@ -import XCTest -import PunkAPI - -class Tests: XCTestCase { - - override func setUp() { - super.setUp() - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() - } - - func testExample() { - // This is an example of a functional test case. - XCTAssert(true, "Pass") - } - - func testPerformanceExample() { - // This is an example of a performance test case. - self.measure() { - // Put the code you want to measure the time of here. - } - } - -} From 6863ea9acdaa5188ac1baae5677fee824ce813a8 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Wed, 20 Feb 2019 21:37:37 +0100 Subject: [PATCH 05/37] Feat: add beer mocks --- Content/Beer.swift | 30 ++++++++++++++-------------- Example/PunkAPI/ViewController.swift | 2 +- Example/Tests/BeerParsingTests.swift | 4 ++++ Example/Tests/BeerStubs.swift | 6 +++++- PunkAPI/Classes/PunkAPI.swift | 4 +--- 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/Content/Beer.swift b/Content/Beer.swift index 0828895..2d90edb 100644 --- a/Content/Beer.swift +++ b/Content/Beer.swift @@ -10,25 +10,25 @@ import Foundation public struct Beer: Codable { var id: Int - var name: String - var tagline: String - var firstBrewed: String - var description: String - var imageUrl: String + var name: String? + var tagline: String? + var firstBrewed: String? + var description: String? + var imageUrl: String? - var abv: Float - var ibu: Float + var abv: Float? + var ibu: Float? - var targetFg: Float - var targetOg: Float + var targetFg: Float? + var targetOg: Float? - var ebc: Float - var srm: Float - var ph: Float + var ebc: Float? + var srm: Float? + var ph: Float? - var attenuationLevel: Float - var volume: Volume - var boilVolume: Volume + var attenuationLevel: Float? + var volume: Volume? + var boilVolume: Volume? // var method: Method } diff --git a/Example/PunkAPI/ViewController.swift b/Example/PunkAPI/ViewController.swift index b96e1eb..3a532ee 100644 --- a/Example/PunkAPI/ViewController.swift +++ b/Example/PunkAPI/ViewController.swift @@ -14,7 +14,7 @@ class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - PunkAPI().get(BeerRequest(id: 1), completion: { beers in + PunkAPI().get(BeerRequest(id: 6), completion: { beers in print(beers) }) } diff --git a/Example/Tests/BeerParsingTests.swift b/Example/Tests/BeerParsingTests.swift index 75d3655..3a89eb5 100644 --- a/Example/Tests/BeerParsingTests.swift +++ b/Example/Tests/BeerParsingTests.swift @@ -49,6 +49,10 @@ class BeerParsingTests: XCTestCase { self.decodeBeers(BeerStub.fifth) } + func testSixth() { + self.decodeBeers(BeerStub.sixth) + } + func testMultipleFirst() { self.decodeBeers(BeerStub.multipleFirst) } diff --git a/Example/Tests/BeerStubs.swift b/Example/Tests/BeerStubs.swift index 7315848..9155c58 100644 --- a/Example/Tests/BeerStubs.swift +++ b/Example/Tests/BeerStubs.swift @@ -29,6 +29,10 @@ struct BeerStub { static let fifth = """ [{"id":5,"name":"Avery Brown Dredge","tagline":"Bloggers' Imperial Pilsner.","first_brewed":"02/2011","description":"An Imperial Pilsner in collaboration with beer writers. Tradition. Homage. Revolution. We wanted to showcase the awesome backbone of the Czech brewing tradition, the noble Saaz hop, and also tip our hats to the modern beers that rock our world, and the people who make them.","image_url":"https://images.punkapi.com/v2/5.png","abv":7.2,"ibu":59,"target_fg":1027,"target_og":1069,"ebc":10,"srm":5,"ph":4.4,"attenuation_level":67,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":66,"unit":"celsius"},"duration":70}],"fermentation":{"temp":{"value":10,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Lager Malt","amount":{"value":6.63,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.38,"unit":"kilograms"}}],"hops":[{"name":"Saaz","amount":{"value":60,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Saaz","amount":{"value":60,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Saaz","amount":{"value":60,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast Pilsner Lager 2007™"},"food_pairing":["Vietnamese squid salad","Chargrilled corn on the cob with paprika butter","Strawberry and rhubarb pie"],"brewers_tips":"Make sure you have a big enough yeast starter to ferment through the OG and lager successfully.","contributed_by":"Sam Mason "}] +""" + + static let sixth = """ +[{"id":58,"name":"Coffee Imperial Stout","tagline":"Beats a Cup of Joe.","first_brewed":"11/2008","description":"This beer was released as both as Danish Beerhouse Coffee Imperial Stout and BrewDog Coffee Imperial Stout. Deep, dark, roasted flavours make this a perfect Sunday brunch beer.","image_url":"https://images.punkapi.com/v2/58.png","abv":9,"ibu":65,"target_fg":1019,"target_og":1080,"ebc":97,"srm":49,"ph":4.4,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":64,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Coffee added after boil. Aged on French oak chips., Dark muscovado sugar: 312.5g for 20mins"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.5,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Roast Barley","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee","amount":{"value":9.4,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee","amount":{"value":9.4,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Gooey chocolate brownies","Chicken fried steak with cheesy mash","Spicy chicken empanadas"],"brewers_tips":"Grind the coffee as if making an espresso to really get the most out of it.","contributed_by":"Sam Mason "}] """ static let multipleFirst = """ @@ -36,6 +40,6 @@ struct BeerStub { """ static let multipleSecond = """ -[{"id":51,"name":"TM10","tagline":"Liquid Art.","first_brewed":"04/2010","description":"Brewed for the Tate Modern’s 10th Anniversary. A saison style beer brewed with ginger and orange peel. Very limited batch of 4000 cork and caged bottles with a silk screened label designed by Johanna Basford. Only available at the Tate Modern.","image_url":"https://images.punkapi.com/v2/51.png","abv":5.5,"ibu":20,"target_fg":1005,"target_og":1048,"ebc":14,"srm":7,"ph":4.2,"attenuation_level":89.6,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":63,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":22,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Pale Ale Malt","amount":{"value":5.3,"unit":"kilograms"}}],"hops":[{"name":"Bobek","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Bobek","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Bobek","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Ginger","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Orange Peel","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 3711 - French Saison™"},"food_pairing":["Tom yum soup","Andhra chicken pickle curry","Butterscotch tart"],"brewers_tips":"For a fresh and fiery hit, put some ginger into the cold conditioning phase as well.","contributed_by":"Sam Mason "},{"id":52,"name":"Paradox Islay","tagline":"Ubiquitous Imperial Stout.","first_brewed":"04/2007","description":"In 2006 James and Martin hijacked a beer dinner run by Michael Jackson, the acclaimed beer and whisky writer, and convinced him to taste one of their home brews. This was a defining moment in BrewDog prehistory, and that beer was the first incarnation of the ubiquitous Paradox. Aged in a variety of casks over the years, Paradox is dark, decadent and encapsulating. Can be enjoyed fresh; phenomenal when aged.","image_url":"https://images.punkapi.com/v2/52.png","abv":10,"ibu":55,"target_fg":1014,"target_og":1090,"ebc":300,"srm":152,"ph":4.4,"attenuation_level":84.4,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Try ageing on oak chips, infusing with rum raisins, or vanilla pods"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.5,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.55,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.33,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.35,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.55,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 1","amount":{"value":0.18,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.33,"unit":"kilograms"}}],"hops":[{"name":"Columbus","amount":{"value":75,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Saaz","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Ancho chilli beef taco","Chocolate gateaux","Rum poached pears with dark chocolate sauce"],"brewers_tips":"The beauty of this beer is in how brilliantly it lends itself to infusing or ageing. Experiment with different additions when the beer is ageing, taste it regularly to gauge its progress, and make sure you package it at its peak.","contributed_by":"Sam Mason "},{"id":53,"name":"Baby Dogma","tagline":"Session Scotch Ale.","first_brewed":"09/2013","description":"A baby Scotch ale with dry and toasty malt flavours and hints of smoke. Toffee, biscuit and fudge abound with a spicy bitterness from the pan-global hops.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.5,"ibu":35,"target_fg":1013,"target_og":1048,"ebc":40,"srm":20,"ph":4.4,"attenuation_level":72.9,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":66,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":1.75,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.48,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.56,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":0.56,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Weyermann Beech Smoked","amount":{"value":0.06,"unit":"kilograms"}}],"hops":[{"name":"First Gold","amount":{"value":18.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Hallertauer Mittelfrüh","amount":{"value":6,"unit":"grams"},"add":"start","attribute":"bitter"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["French onion soup","Braised pheasant","Caramel sauce and hot fudge"],"brewers_tips":"The addition of Weyermann Beech Smoked malt creates a beer with a delicate smoke character.","contributed_by":"Ali Skinner "},{"id":54,"name":"Albino Squid Assasin","tagline":"Red Rye IPA","first_brewed":"11/2015","description":"This tentacled terminator packs a punch - ten punches to be precise. Each hop addition adds to the intense layers of depth in this red rye IPA. Toasty caramel & cinder toffee from crystal malts, cacao richness from intensely roasted malt and the spiciness of rye. Zesty pithiness from Citra and the robust resin of Chinook. This small batch exclusive brew is up-front intensity matched with twisted complexity. The can features awesome custom art from Joe Wilson.","image_url":"https://images.punkapi.com/v2/54.png","abv":7.4,"ibu":65,"target_fg":1012,"target_og":1069,"ebc":60,"srm":30,"ph":4.2,"attenuation_level":82.6,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Pale Ale","amount":{"value":5,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 1","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Rye","amount":{"value":0.5,"unit":"kilograms"}}],"hops":[{"name":"Magnum","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Citra","amount":{"value":6.25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Chinook","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":18.75,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Chinook","amount":{"value":100,"unit":"grams"},"add":"fv","attribute":"aroma"},{"name":"Citra","amount":{"value":75,"unit":"grams"},"add":"fv","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Rocket and mozzarella salad with a cracked pepper dressing","Fried halibut with sweet potato fritters","Grapefruit and blood orange tart"],"brewers_tips":"20% specialty malts in this grist can create problems in the run off. Be careful not to pull the bed down onto the plates.","contributed_by":"Matt Ball "},{"id":55,"name":"Amarillo - IPA Is Dead","tagline":"Single Hop India Pale Ale.","first_brewed":"01/2013","description":"Citrus fruit. Lots of citrus fruit. Think blood orange, orange zest and grapefruit, tangerine and lemon; the fruit is balanced by floral notes in the most classic of new wave IPA hops. Amarillo adds a zesty, pithy character that sits beautifully alongside hints of toffee and honeycomb.","image_url":"https://images.punkapi.com/v2/55.png","abv":7.2,"ibu":70,"target_fg":1012,"target_og":1067,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":82.1,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.88,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.06,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Amarillo","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":250,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Bratwurst sausage with spicy mustard","Fried American bacon with chilli flakes added to the top","Dark chocolate chip cookies"],"brewers_tips":"Use the freshest hops for the most impact. It seems obvious but in a single hop beer, you want the hops to be at their best.","contributed_by":"Sam Mason "},{"id":56,"name":"Black Eyed King Imp","tagline":"Barrel-Aged Prototype Cocoa Psycho.","first_brewed":"11/2012","description":"An early Cocoa Psycho recipe that we loved, but didn't fit what we were looking for. We locked this chocolate coffee stout away in barrels for two years, imparting toasted marshmallow, spicy vanilla, molasses and boozy warmth.","image_url":"https://images.punkapi.com/v2/56.png","abv":9.5,"ibu":85,"target_fg":1022,"target_og":1095,"ebc":250,"srm":125,"ph":4.4,"attenuation_level":76.8,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":50}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":"Coffee Beans: 12.5g at end, Lactose: 125g"},"ingredients":{"malt":[{"name":"Extra Pale - Spring Blend","amount":{"value":6.25,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":1.56,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Brown","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Magnum","amount":{"value":62.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Beef chilli made with cocoa powder","Dark chocolate covered bacon","Rich espresso tiramisu"],"brewers_tips":"There is a huge amount of roasted malts in this grist. Be careful not to pulverise the malt into powder during the milling process.","contributed_by":"Sam Mason "},{"id":57,"name":"Prototype 27","tagline":"Vibrant Smoky Pink IPA.","first_brewed":"04/2010","description":"Hardcore IPA with raspberries aged in Caol Ila casks. Full-bodied and compelling, the robust malt base provides an initial layer of honey, cinnamon and biscuity malt sweetness. Soon the Scottish berries are in on the act, a dominating tug of war between sweet and tart with an overbearing zest. As the beer slips back across your tongue the hops demand and definitely get your attention. At 100 IBUs the bitterness smashes into the back of your throat as the resinous, spiced orange peel flavours add depth to the berry fruitiness.","image_url":"https://images.punkapi.com/v2/57.png","abv":9.2,"ibu":149,"target_fg":1014,"target_og":1083,"ebc":19.5,"srm":9.8,"ph":4.4,"attenuation_level":83,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Pale Ale Malt","amount":{"value":8.13,"unit":"kilograms"}},{"name":"Crystal Malt 150","amount":{"value":0.28,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.56,"unit":"kilograms"}}],"hops":[{"name":"Columbus","amount":{"value":50,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":50,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Centennial","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Columbus","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Strong blue cheese","Cranachan","Chicago style hot links"],"brewers_tips":"Soak some oak chips in Caol Ila whisky to get barrel character. Freeze raspberries before adding them to secondary.","contributed_by":"Sam Mason "},{"id":58,"name":"Coffee Imperial Stout","tagline":"Beats a Cup of Joe.","first_brewed":"11/2008","description":"This beer was released as both as \"Danish Beerhouse Coffee Imperial Stout\" and \"BrewDog Coffee Imperial Stout\". Deep, dark, roasted flavours make this a perfect Sunday brunch beer.","image_url":"https://images.punkapi.com/v2/58.png","abv":9,"ibu":65,"target_fg":1019,"target_og":1080,"ebc":97,"srm":49,"ph":4.4,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":64,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Coffee added after boil. Aged on French oak chips., Dark muscovado sugar: 312.5g for 20mins"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.5,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Roast Barley","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee","amount":{"value":9.4,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee","amount":{"value":9.4,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Gooey chocolate brownies","Chicken fried steak with cheesy mash","Spicy chicken empanadas"],"brewers_tips":"Grind the coffee as if making an espresso to really get the most out of it.","contributed_by":"Sam Mason "},{"id":59,"name":"Mandarina Bavaria - IPA Is Dead","tagline":"Single Hop India Pale Ale.","first_brewed":"03/2015","description":"From the central European plains of Germany, comes something very different. A blast of tangerine and orange, Mandarina Bavaria brings a highly distinctive backbone of flavour. This is down to its parent – Cascade – and a frankly enormous 70% myrcene oil content. If equate Germany solely with earthy, spicy Noble hops, Mandarina Bavaria will make you think again.","image_url":"https://images.punkapi.com/v2/59.png","abv":7.2,"ibu":100,"target_fg":1010,"target_og":1064,"ebc":12,"srm":6,"ph":4.4,"attenuation_level":84,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.39,"unit":"kilograms"}}],"hops":[{"name":"Mandarina Bavaria","amount":{"value":41.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Mandarina Bavaria","amount":{"value":41.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Mandarina Bavaria","amount":{"value":41.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Lavender and thyme roast beef","Spicy kung po chicken","Caramel and rose essence cheesecake"],"brewers_tips":"We've mentioned the importance of fresh hops previously but this one really demands that your hops are the absolute freshest.","contributed_by":"Sam Mason "},{"id":60,"name":"Dogma","tagline":"Revamped Wee Heavy. Luscious. Malty. Fruity.","first_brewed":"07/2013","description":"Brewed with over ten different types of malt, and blended together with Scottish heather honey, it is a pantheon to the gods of intricacy and nuance; a beer that celebratesa confluence of ideas. Complex, indulgent and encapsulating, Dogma gives more than a cursory nod to history, to make you ponder the very nature of beer itself.","image_url":"https://images.punkapi.com/v2/60.png","abv":7.5,"ibu":30,"target_fg":1023,"target_og":1080,"ebc":46,"srm":23,"ph":4.5,"attenuation_level":70,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":12,"unit":"celsius"}},"twist":"Heather Honey: 125g"},"ingredients":{"malt":[{"name":"Pale Ale","amount":{"value":3.5,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.75,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Smoked","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Brown","amount":{"value":0.25,"unit":"kilograms"}}],"hops":[{"name":"Saaz","amount":{"value":75,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"First Gold","amount":{"value":10,"unit":"grams"},"add":"start","attribute":"bitter"}],"yeast":"Wyeast 2007 - Pilsen Lager™"},"food_pairing":["Mature cheddar with red onion chutney","Honey glazed ham","Chocolate caramel drizzled sponge cake"],"brewers_tips":"There's a lot of specialty malt in the mash. Make sure you take the run off nice and steady – increase the flow too much and pull in the bed at your peril.","contributed_by":"Ali Skinner "},{"id":61,"name":"Magic Stone Dog (w/Magic Rock & Stone Brewing Co.)","tagline":"Session Farmhouse IPA - Stone / Magic Rock Collab.","first_brewed":"06/2014","description":"A session IPA brewed with a diverse grain bill, hopped with Simcoe and Amarillo and fermented with saison yeast, for an incredible level of depth in a low ABV beer. Spicy, fruity, complex, refreshing and dry.","image_url":"https://images.punkapi.com/v2/61.png","abv":4.6,"ibu":30,"target_fg":1008,"target_og":1043,"ebc":15,"srm":7.5,"ph":4.4,"attenuation_level":81.4,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":23,"unit":"celsius"}},"twist":"Cumin: 0.5g at end, Caraway: 1g at end, Peppercorns (Pink): 5g at end, Grains of Paradise: 5g at end"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":2.38,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.44,"unit":"kilograms"}},{"name":"Torrified Wheat","amount":{"value":0.44,"unit":"kilograms"}},{"name":"Rye","amount":{"value":0.19,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":0.44,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.19,"unit":"kilograms"}}],"hops":[{"name":"Simcoe","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 3711 - French Saison™"},"food_pairing":["Halibut with caper brown butter","Creamy gorgonzola and satsuma salad","Spicy Daal with garlic naan bread"],"brewers_tips":"Start the fermentation off at 20 ̊C and allow it to rise as high as 25 ̊C. This will increase the fruity character of the yeast.","contributed_by":"Sam Mason "},{"id":62,"name":"AB:08","tagline":"Deconstructed Blonde Imperial Stout.","first_brewed":"11/2011","description":"Flavours and aromas you'd expect from a Stout, but brewed without dark malts. The full mouthfeel comes courtesy of wheat and oats, while smoked malt and the twist additions add the complex flavours normally provided by highly kilned malts.","image_url":"https://images.punkapi.com/v2/62.png","abv":10.43,"ibu":65,"target_fg":1016,"target_og":1095,"ebc":23,"srm":11.5,"ph":4.4,"attenuation_level":83.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Cacao: 25g at FV, Coffee Beans: 37.5g at FV, Oak Chips: 5g at FV, Vanilla Pods: 10 split pods, Liquorice: 5g at FV"},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":9.25,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1.88,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.88,"unit":"kilograms"}},{"name":"Smoked Peaty","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"First Gold","amount":{"value":81.25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"First Gold","amount":{"value":62.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee Beans","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Caramelised scallops with burnt apple puree","Blackened Cajun chicken","Blondies with chocolate fudge sauce"],"brewers_tips":"Add all twist ingredients to Fermentation Vessel once fermentation is complete. Don’t be afraid to add a little at a time and taste as you go. During mashing in first start with pale malt. Afterwards mix all malts evenly. Go with flaked oats during second half of mashing in process.","contributed_by":"Sam Mason "},{"id":63,"name":"Sunk Punk","tagline":"Ocean Fermented Lager.","first_brewed":"09/2011","description":"It's rumoured just a drop can calm the fiercest of storms. A balance of sweet, salt and savoury, citrus, spruce and caramel. Fermented at the bottom of the North Sea, which just so happens to be the perfect temperature for lagers to ferment.","image_url":"https://images.punkapi.com/v2/63.png","abv":7.1,"ibu":68,"target_fg":1010,"target_og":1056,"ebc":14,"srm":7,"ph":4.4,"attenuation_level":82.1,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":10,"unit":"celsius"}},"twist":"Seabuckthorn: 25g at end, Sea Salt: 20g at middle, Rum: 25ml at end"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":5.21,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Ahtanum","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Chinook","amount":{"value":20,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Ahtanum","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Chinook","amount":{"value":30,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Ahtanum","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Nelson Sauvin","amount":{"value":140,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 2007 - Pilsen Lager™"},"food_pairing":["Salt baked cod with lemon and dill butter","Beef, oyster and ale pie","Apple and rosemary tart"],"brewers_tips":"Keep the fermentation temperature as steady as possible to allow the lager yeast to do its thing.","contributed_by":"Sam Mason "},{"id":64,"name":"Sub Hop","tagline":"Hopped-Up Imperial Pilsner.","first_brewed":"06/2014","description":"Brewed for the opening of our first bar in Italy, BrewDog Firenze. A mega-hoppy Imperial Pilsner, with toasty malt complexity and tropical New World hops.","image_url":"https://images.punkapi.com/v2/64.png","abv":8,"ibu":35,"target_fg":1016,"target_og":1077,"ebc":15,"srm":7.5,"ph":4.4,"attenuation_level":79.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":9,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.25,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Dextrose","amount":{"value":0.38,"unit":"kilograms"}}],"hops":[{"name":"Saaz","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Hallertauer Mittelfrüh","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Pacifica","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Pacific Jade","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Pacifica","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Pacific Jade","amount":{"value":75,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Pacifica","amount":{"value":37.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 2007- Pilsen Lager™"},"food_pairing":["Seared lemon and herb salmon","Crab linguine","Almond biscotti"],"brewers_tips":"Sit this beer aside for a month to allow it to mellow.","contributed_by":"Sam Mason "},{"id":65,"name":"Bracken's Porter","tagline":"A Tribute To Our Favourite 4 Pawed Friend.","first_brewed":"03/2013","description":"The beer was named Bracken’s Porter as a tribute to our favourite four pawed friend who sadly passed in 2013. Chocolately, robust, warming, laid back and lots of fun - there are plenty of similarities between the two. Bracken we miss you and we hope you like your beer. Long live the original BrewDog.","image_url":"https://images.punkapi.com/v2/keg.png","abv":5,"ibu":50,"target_fg":1010,"target_og":1049,"ebc":110,"srm":55,"ph":4.4,"attenuation_level":79,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":3.63,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.19,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Black Malt","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Vic Secret","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Bramling Cross","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"aroma"},{"name":"Challenger","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Grilled vegetable and chicken teriyaki skewers","Chilli covered burger (Sloppy Joe)","Candied bacon topped chocolate cheesecake"],"brewers_tips":"Try to replicate London’s highly carbonated water to really emphasise the dark malt profile.","contributed_by":"Sam Mason "},{"id":66,"name":"Tokyo Rising Sun - Lowland","tagline":"A Beautiful Accident.","first_brewed":"06/2009","description":"A forgotten gem in the deepest, darkest corner of the warehouse. Aged in a Lowland whisky cask resulting in decadent chocolate, toasted vanilla, indulgent spiced fruit, a mesmerizingly hypnotic mouthfeel and new layers that emerge on every sip.","image_url":"https://images.punkapi.com/v2/66.png","abv":13.2,"ibu":85,"target_fg":1023,"target_og":1125,"ebc":140,"srm":71,"ph":4.4,"attenuation_level":82.17,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Cranberry: 25g at end, Jasmine: 25g at end, Muscovado sugar: 300g at start, Oak chips soaked in lowland whisky: 15g at dry hop"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.6,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":1.75,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.5,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Chinook","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"WLP099 Super High Gravity Ale"},"food_pairing":["Duck liver paté","Mutton stew","Kirsch chocolate truffles"],"brewers_tips":"Leave on wood for as long as you dare. If possible forget about it for four years.","contributed_by":"Sam Mason "},{"id":67,"name":"Hunter Foundation Pale Ale","tagline":"American Pale Ale.","first_brewed":"05/2012","description":"This straight-up US style pale ale uses some of our favourite hops against a toasty malt base. We brewed this with Sir Tom Hunter at our Fraserburgh brewery - to add a charitable element to your own version, feel free to share this citrusy pale ale with your friends. Or don't, it's your choice.","image_url":"https://images.punkapi.com/v2/67.png","abv":5.4,"ibu":35,"target_fg":1008,"target_og":1050,"ebc":11.5,"srm":5.75,"ph":4.4,"attenuation_level":84,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":63,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":4.3,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.8,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":10,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":15,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":20,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Monterey Jack stuffed grilled jalepenos","Barbecue corn and steak fajita seasoned wrap","Cinnamon & white chocolate churro"],"brewers_tips":"To dry the beer out, mash at a slightly lower temp (62° - 63°C), this will increase the ratio of fermentable sugars in the beer.","contributed_by":"Sam Mason "},{"id":68,"name":"Hype","tagline":"New Zealand Pale Ale.","first_brewed":"08/2007","description":"A perfect pale ale showcase for the tropical profile of New Zealand hops and the intense citrus of US hops.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.1,"ibu":65,"target_fg":1010,"target_og":1042,"ebc":17,"srm":8.5,"ph":4.4,"attenuation_level":76.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":4.02,"unit":"kilograms"}}],"hops":[{"name":"Nelson Sauvin","amount":{"value":2,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Nelson Sauvin","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":2.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Quince cheese","Shredded chicken and mango salsa taquitos","Poached pear"],"brewers_tips":"After the beer has fermented, leave it to rest for 2 – 3 days at the lowest temperature possible (ideally 0 – 2'C). This will allow the flavours to marry together, and will transform it into a balanced and amazing beer.","contributed_by":"Sam Mason "},{"id":69,"name":"AB:16","tagline":"Coffee-Infused Belgian Quad.","first_brewed":"02/2014","description":"On the nose, clove and nutmeg, cafe au lait, subtle dark fruit notes, and hints of candied lemon peel. On the palate, smooth & fruity espresso, milk chocolate, and warm brandy-soaked currants are in the middle of a high-class dance-off against the spicy and peppery Belgian character. The overall impression evokes malt loaf or ginger cake.","image_url":"https://images.punkapi.com/v2/69.png","abv":10.6,"ibu":55,"target_fg":1012,"target_og":1090,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":86.7,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Coffee Beans: 250g FV. Raisins: 90g at end. Dark Sugar:140g at end."},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.75,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Waimea","amount":{"value":15,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Saaz","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Fuggles","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"}],"yeast":"Wyeast 3787 - Trappist High Gravity™"},"food_pairing":["Roasted duck","Gorgonzola and rye nut bread with smoked honey ham","Raspberry coffee cheesecake"],"brewers_tips":"For the traditional cellering, age this beer in vessel or bottle for 2 - 3 months at cellar temperature.","contributed_by":"Ali Skinner "},{"id":70,"name":"Sunmaid Stout","tagline":"Rum & Raisin Imperial Stout.","first_brewed":"12/2011","description":"Brewed by Chris Sartori from Stone Brewing Company in 2010. A dark chocolate stout with dried dark fruit finish. Simcoe provides bitterness with subtle fruity supporting notes, contrasting the chocolate and coffee-laden malt profile. The finish is warming with vanilla and rich dark fruit depth.","image_url":"https://images.punkapi.com/v2/keg.png","abv":10.2,"ibu":50,"target_fg":1102,"target_og":1026,"ebc":197,"srm":100,"ph":4.4,"attenuation_level":74.5,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":55}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Age in whisky casks with rum soaked raisins"},"ingredients":{"malt":[{"name":"Pale Ale - Tipple","amount":{"value":10,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.94,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":0.94,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.56,"unit":"kilograms"}}],"hops":[{"name":"Simcoe","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Challenger","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Lapin aux pruneaux (braised rabbit with prunes)","Gouda cheese","Dark chocolate truffles"],"brewers_tips":"Take small volume of wort out of the run off and steep the raisins in it, then crush them up. This will help to release the dark fruit aromas into the wort.","contributed_by":"Sam Mason "},{"id":71,"name":"Pale - Russian Doll","tagline":"Nesting Hop Bomb.","first_brewed":"08/2014","description":"The levels of hops vary throughout the range. We love hops, so all four beers are big, bitter badasses, but by tweaking the amount of each hop used later in the boil and during dry- hopping, we can balance the malty backbone with some unexpected flavours. Simcoe is used in the whirlpool for all four beers, and yet still lends different characters to each.","image_url":"https://images.punkapi.com/v2/71.png","abv":4,"ibu":35,"target_fg":1010,"target_og":1041,"ebc":45,"srm":22.5,"ph":5.2,"attenuation_level":75.6,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":3.63,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Cascade","amount":{"value":7.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Citra","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":17.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":62.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Cascade","amount":{"value":62.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Centennial","amount":{"value":62.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Citra","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Roast chicken with vegetables and wild rice","Fresh pico de gallo with corn tortilla","Carrot cake"],"brewers_tips":"Create balance through experimentation with the hop amounts and malt backbone.","contributed_by":"Sam Mason "},{"id":72,"name":"Whisky Sour - B-Sides","tagline":"Pilot Brew - Deconstructed Whisky Sour.","first_brewed":"03/2015","description":"Deconstructed whisky sour, reconstructed as a beer.","image_url":"https://images.punkapi.com/v2/keg.png","abv":7,"ibu":20,"target_fg":1021,"target_og":1081,"ebc":12,"srm":6,"ph":3.2,"attenuation_level":74,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":60,"unit":"celsius"},"duration":10},{"temp":{"value":65,"unit":"celsius"},"duration":30},{"temp":{"value":72,"unit":"celsius"},"duration":10},{"temp":{"value":78,"unit":"celsius"},"duration":5}],"fermentation":{"temp":{"value":null,"unit":"celsius"}},"twist":"Kettle Soured"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.88,"unit":"kilograms"}},{"name":"Acidulated Malt","amount":{"value":1.88,"unit":"kilograms"}},{"name":"Wheat Malt","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Rye Malt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Special W","amount":{"value":0.05,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":8.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Citra","amount":{"value":8.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":8.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":1.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Citra","amount":{"value":1.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Simcoe","amount":{"value":1.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Potted fresh & smoked salmon","Spiced nut loaf","Lemon poppyseed donuts"],"brewers_tips":"Lemon poppyseed donuts.","contributed_by":"Sam Mason "},{"id":73,"name":"Black Eyed King Imp - Vietnamese Coffee Edition","tagline":"Vietnamese Coffee Edition.","first_brewed":"12/2014","description":"This is the Vietnamese Coffee Edition. At 12.7% ABV, Black Eyed King Imp is a super intense and twistedly complex brew, with intense notes of sweet vanilla, rich espresso, smooth molasses and bitter chocolate barely contained by the whatever container it's in.","image_url":"https://images.punkapi.com/v2/73.png","abv":12.7,"ibu":85,"target_fg":1038,"target_og":1113.5,"ebc":250,"srm":125,"ph":5.2,"attenuation_level":76.8,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":50}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":"Coffee Beans: 12.5g at end, Lactose: 125g at FV, Bourbon barrel aged"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.25,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Cara","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":1.5625,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Brown","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.3125,"unit":"kilograms"}}],"hops":[{"name":"Magnum","amount":{"value":62.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"bitter"},{"name":"First Gold","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"aroma / bitter"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Bacon sandwich with brown sauce","20hr smoked brisket","Chocolate fudge ice cream"],"brewers_tips":"Buying top notch coffee beans make a huge difference here. Give them a very course grind to get the most out of them.","contributed_by":"Sam Mason "},{"id":74,"name":"Eurotrash","tagline":"Belgian Blonde.","first_brewed":"10/2009","description":"Trashy Blonde with a Belgian Twist. Clove oil, red apples and a drier mouthfeel set this beer apart from its older sister.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.1,"ibu":52,"target_fg":1010,"target_og":1041,"ebc":17,"srm":8.5,"ph":5.2,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":66,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Fermented with Belgian yeast for signature character"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":3.25,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.38,"unit":"kilograms"}}],"hops":[{"name":"Simcoe","amount":{"value":5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":6.3,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":2.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Amarillo","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Motueka","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Motueka","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Amarillo","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Motueka","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 3522 - Belgian Ardennes™"},"food_pairing":["Grilled fish salad","Angelfood cake","Pad Thai"],"brewers_tips":"Don't be scared to let the fermentation temperature climb up another couple of degrees to really emphasize the Belgian character.","contributed_by":"Sam Mason "},{"id":75,"name":"Never Mind The Anabolics","tagline":"Performance-Enhancing India Pale Ale.","first_brewed":"06/2012","description":"Never Mind the Anabolics, a 6.5% India Pale Ale brewed with copious amounts of performance-enhancing natural ingredients. Brewed to commemorate the 2012 Olympics and its merry marketing bandwagon.","image_url":"https://images.punkapi.com/v2/75.png","abv":6.5,"ibu":35,"target_fg":1012,"target_og":1050,"ebc":23,"srm":11.5,"ph":4.4,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":68,"unit":"celsius"},"duration":30}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":"Lycii Berries: 7.5g at end, Ginseng: 5.625g at end, Guarana: 25g at end, Kolabu: 25g at end, Gingko: 6.25g at end, Matcha Tea: 12.5g at end, Maca Powder: 16.25g at end"},"ingredients":{"malt":[{"name":"Extra Pale - Spring Blend","amount":{"value":4.38,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Motueka","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Motueka","amount":{"value":18.75,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Grilled chicken salad with bacon and avocado","Red pepper houmous and flat bread","Matcha green tea cake"],"brewers_tips":"Mix the powders into a paste before adding to the wort kettle. This will prevent the powders from balling up and not bringing the full flavour effect.","contributed_by":"Sam Mason "}] +[{"id":51,"name":"TM10","tagline":"Liquid Art.","first_brewed":"04/2010","description":"Brewed for the Tate Modern’s 10th Anniversary. A saison style beer brewed with ginger and orange peel. Very limited batch of 4000 cork and caged bottles with a silk screened label designed by Johanna Basford. Only available at the Tate Modern.","image_url":"https://images.punkapi.com/v2/51.png","abv":5.5,"ibu":20,"target_fg":1005,"target_og":1048,"ebc":14,"srm":7,"ph":4.2,"attenuation_level":89.6,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":63,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":22,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Pale Ale Malt","amount":{"value":5.3,"unit":"kilograms"}}],"hops":[{"name":"Bobek","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Bobek","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Bobek","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Ginger","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Orange Peel","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 3711 - French Saison™"},"food_pairing":["Tom yum soup","Andhra chicken pickle curry","Butterscotch tart"],"brewers_tips":"For a fresh and fiery hit, put some ginger into the cold conditioning phase as well.","contributed_by":"Sam Mason "},{"id":52,"name":"Paradox Islay","tagline":"Ubiquitous Imperial Stout.","first_brewed":"04/2007","description":"In 2006 James and Martin hijacked a beer dinner run by Michael Jackson, the acclaimed beer and whisky writer, and convinced him to taste one of their home brews. This was a defining moment in BrewDog prehistory, and that beer was the first incarnation of the ubiquitous Paradox. Aged in a variety of casks over the years, Paradox is dark, decadent and encapsulating. Can be enjoyed fresh; phenomenal when aged.","image_url":"https://images.punkapi.com/v2/52.png","abv":10,"ibu":55,"target_fg":1014,"target_og":1090,"ebc":300,"srm":152,"ph":4.4,"attenuation_level":84.4,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Try ageing on oak chips, infusing with rum raisins, or vanilla pods"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.5,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.55,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.33,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.35,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.55,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 1","amount":{"value":0.18,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.33,"unit":"kilograms"}}],"hops":[{"name":"Columbus","amount":{"value":75,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Saaz","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Ancho chilli beef taco","Chocolate gateaux","Rum poached pears with dark chocolate sauce"],"brewers_tips":"The beauty of this beer is in how brilliantly it lends itself to infusing or ageing. Experiment with different additions when the beer is ageing, taste it regularly to gauge its progress, and make sure you package it at its peak.","contributed_by":"Sam Mason "},{"id":53,"name":"Baby Dogma","tagline":"Session Scotch Ale.","first_brewed":"09/2013","description":"A baby Scotch ale with dry and toasty malt flavours and hints of smoke. Toffee, biscuit and fudge abound with a spicy bitterness from the pan-global hops.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.5,"ibu":35,"target_fg":1013,"target_og":1048,"ebc":40,"srm":20,"ph":4.4,"attenuation_level":72.9,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":66,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":1.75,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.48,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.56,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":0.56,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Weyermann Beech Smoked","amount":{"value":0.06,"unit":"kilograms"}}],"hops":[{"name":"First Gold","amount":{"value":18.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Hallertauer Mittelfrüh","amount":{"value":6,"unit":"grams"},"add":"start","attribute":"bitter"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["French onion soup","Braised pheasant","Caramel sauce and hot fudge"],"brewers_tips":"The addition of Weyermann Beech Smoked malt creates a beer with a delicate smoke character.","contributed_by":"Ali Skinner "},{"id":54,"name":"Albino Squid Assasin","tagline":"Red Rye IPA","first_brewed":"11/2015","description":"This tentacled terminator packs a punch - ten punches to be precise. Each hop addition adds to the intense layers of depth in this red rye IPA. Toasty caramel & cinder toffee from crystal malts, cacao richness from intensely roasted malt and the spiciness of rye. Zesty pithiness from Citra and the robust resin of Chinook. This small batch exclusive brew is up-front intensity matched with twisted complexity. The can features awesome custom art from Joe Wilson.","image_url":"https://images.punkapi.com/v2/54.png","abv":7.4,"ibu":65,"target_fg":1012,"target_og":1069,"ebc":60,"srm":30,"ph":4.2,"attenuation_level":82.6,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Pale Ale","amount":{"value":5,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.13,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 1","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Rye","amount":{"value":0.5,"unit":"kilograms"}}],"hops":[{"name":"Magnum","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Citra","amount":{"value":6.25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Chinook","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":18.75,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Chinook","amount":{"value":100,"unit":"grams"},"add":"fv","attribute":"aroma"},{"name":"Citra","amount":{"value":75,"unit":"grams"},"add":"fv","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Rocket and mozzarella salad with a cracked pepper dressing","Fried halibut with sweet potato fritters","Grapefruit and blood orange tart"],"brewers_tips":"20% specialty malts in this grist can create problems in the run off. Be careful not to pull the bed down onto the plates.","contributed_by":"Matt Ball "},{"id":55,"name":"Amarillo - IPA Is Dead","tagline":"Single Hop India Pale Ale.","first_brewed":"01/2013","description":"Citrus fruit. Lots of citrus fruit. Think blood orange, orange zest and grapefruit, tangerine and lemon; the fruit is balanced by floral notes in the most classic of new wave IPA hops. Amarillo adds a zesty, pithy character that sits beautifully alongside hints of toffee and honeycomb.","image_url":"https://images.punkapi.com/v2/55.png","abv":7.2,"ibu":70,"target_fg":1012,"target_og":1067,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":82.1,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":4.88,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.06,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Amarillo","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":250,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Bratwurst sausage with spicy mustard","Fried American bacon with chilli flakes added to the top","Dark chocolate chip cookies"],"brewers_tips":"Use the freshest hops for the most impact. It seems obvious but in a single hop beer, you want the hops to be at their best.","contributed_by":"Sam Mason "},{"id":56,"name":"Black Eyed King Imp","tagline":"Barrel-Aged Prototype Cocoa Psycho.","first_brewed":"11/2012","description":"An early Cocoa Psycho recipe that we loved, but didn't fit what we were looking for. We locked this chocolate coffee stout away in barrels for two years, imparting toasted marshmallow, spicy vanilla, molasses and boozy warmth.","image_url":"https://images.punkapi.com/v2/56.png","abv":9.5,"ibu":85,"target_fg":1022,"target_og":1095,"ebc":250,"srm":125,"ph":4.4,"attenuation_level":76.8,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":50}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":"Coffee Beans: 12.5g at end, Lactose: 125g"},"ingredients":{"malt":[{"name":"Extra Pale - Spring Blend","amount":{"value":6.25,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":1.56,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Brown","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Magnum","amount":{"value":62.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Beef chilli made with cocoa powder","Dark chocolate covered bacon","Rich espresso tiramisu"],"brewers_tips":"There is a huge amount of roasted malts in this grist. Be careful not to pulverise the malt into powder during the milling process.","contributed_by":"Sam Mason "},{"id":57,"name":"Prototype 27","tagline":"Vibrant Smoky Pink IPA.","first_brewed":"04/2010","description":"Hardcore IPA with raspberries aged in Caol Ila casks. Full-bodied and compelling, the robust malt base provides an initial layer of honey, cinnamon and biscuity malt sweetness. Soon the Scottish berries are in on the act, a dominating tug of war between sweet and tart with an overbearing zest. As the beer slips back across your tongue the hops demand and definitely get your attention. At 100 IBUs the bitterness smashes into the back of your throat as the resinous, spiced orange peel flavours add depth to the berry fruitiness.","image_url":"https://images.punkapi.com/v2/57.png","abv":9.2,"ibu":149,"target_fg":1014,"target_og":1083,"ebc":19.5,"srm":9.8,"ph":4.4,"attenuation_level":83,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Pale Ale Malt","amount":{"value":8.13,"unit":"kilograms"}},{"name":"Crystal Malt 150","amount":{"value":0.28,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.56,"unit":"kilograms"}}],"hops":[{"name":"Columbus","amount":{"value":50,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":50,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Columbus","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Centennial","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Columbus","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Centennial","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":37.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Strong blue cheese","Cranachan","Chicago style hot links"],"brewers_tips":"Soak some oak chips in Caol Ila whisky to get barrel character. Freeze raspberries before adding them to secondary.","contributed_by":"Sam Mason "},{"id":58,"name":"Coffee Imperial Stout","tagline":"Beats a Cup of Joe.","first_brewed":"11/2008","description":"This beer was released as both as Danish Beerhouse Coffee Imperial Stout and BrewDog Coffee Imperial Stout. Deep, dark, roasted flavours make this a perfect Sunday brunch beer.","image_url":"https://images.punkapi.com/v2/58.png","abv":9,"ibu":65,"target_fg":1019,"target_og":1080,"ebc":97,"srm":49,"ph":4.4,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":64,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Coffee added after boil. Aged on French oak chips., Dark muscovado sugar: 312.5g for 20mins"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.5,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Roast Barley","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee","amount":{"value":9.4,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee","amount":{"value":9.4,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Gooey chocolate brownies","Chicken fried steak with cheesy mash","Spicy chicken empanadas"],"brewers_tips":"Grind the coffee as if making an espresso to really get the most out of it.","contributed_by":"Sam Mason "},{"id":59,"name":"Mandarina Bavaria - IPA Is Dead","tagline":"Single Hop India Pale Ale.","first_brewed":"03/2015","description":"From the central European plains of Germany, comes something very different. A blast of tangerine and orange, Mandarina Bavaria brings a highly distinctive backbone of flavour. This is down to its parent – Cascade – and a frankly enormous 70% myrcene oil content. If equate Germany solely with earthy, spicy Noble hops, Mandarina Bavaria will make you think again.","image_url":"https://images.punkapi.com/v2/59.png","abv":7.2,"ibu":100,"target_fg":1010,"target_og":1064,"ebc":12,"srm":6,"ph":4.4,"attenuation_level":84,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.39,"unit":"kilograms"}}],"hops":[{"name":"Mandarina Bavaria","amount":{"value":41.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Mandarina Bavaria","amount":{"value":41.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Mandarina Bavaria","amount":{"value":41.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Lavender and thyme roast beef","Spicy kung po chicken","Caramel and rose essence cheesecake"],"brewers_tips":"We've mentioned the importance of fresh hops previously but this one really demands that your hops are the absolute freshest.","contributed_by":"Sam Mason "},{"id":60,"name":"Dogma","tagline":"Revamped Wee Heavy. Luscious. Malty. Fruity.","first_brewed":"07/2013","description":"Brewed with over ten different types of malt, and blended together with Scottish heather honey, it is a pantheon to the gods of intricacy and nuance; a beer that celebratesa confluence of ideas. Complex, indulgent and encapsulating, Dogma gives more than a cursory nod to history, to make you ponder the very nature of beer itself.","image_url":"https://images.punkapi.com/v2/60.png","abv":7.5,"ibu":30,"target_fg":1023,"target_og":1080,"ebc":46,"srm":23,"ph":4.5,"attenuation_level":70,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":12,"unit":"celsius"}},"twist":"Heather Honey: 125g"},"ingredients":{"malt":[{"name":"Pale Ale","amount":{"value":3.5,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.75,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Smoked","amount":{"value":0.06,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Brown","amount":{"value":0.25,"unit":"kilograms"}}],"hops":[{"name":"Saaz","amount":{"value":75,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"First Gold","amount":{"value":10,"unit":"grams"},"add":"start","attribute":"bitter"}],"yeast":"Wyeast 2007 - Pilsen Lager™"},"food_pairing":["Mature cheddar with red onion chutney","Honey glazed ham","Chocolate caramel drizzled sponge cake"],"brewers_tips":"There's a lot of specialty malt in the mash. Make sure you take the run off nice and steady – increase the flow too much and pull in the bed at your peril.","contributed_by":"Ali Skinner "},{"id":61,"name":"Magic Stone Dog (w/Magic Rock & Stone Brewing Co.)","tagline":"Session Farmhouse IPA - Stone / Magic Rock Collab.","first_brewed":"06/2014","description":"A session IPA brewed with a diverse grain bill, hopped with Simcoe and Amarillo and fermented with saison yeast, for an incredible level of depth in a low ABV beer. Spicy, fruity, complex, refreshing and dry.","image_url":"https://images.punkapi.com/v2/61.png","abv":4.6,"ibu":30,"target_fg":1008,"target_og":1043,"ebc":15,"srm":7.5,"ph":4.4,"attenuation_level":81.4,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":23,"unit":"celsius"}},"twist":"Cumin: 0.5g at end, Caraway: 1g at end, Peppercorns (Pink): 5g at end, Grains of Paradise: 5g at end"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":2.38,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.44,"unit":"kilograms"}},{"name":"Torrified Wheat","amount":{"value":0.44,"unit":"kilograms"}},{"name":"Rye","amount":{"value":0.19,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":0.44,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.19,"unit":"kilograms"}}],"hops":[{"name":"Simcoe","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 3711 - French Saison™"},"food_pairing":["Halibut with caper brown butter","Creamy gorgonzola and satsuma salad","Spicy Daal with garlic naan bread"],"brewers_tips":"Start the fermentation off at 20 ̊C and allow it to rise as high as 25 ̊C. This will increase the fruity character of the yeast.","contributed_by":"Sam Mason "},{"id":62,"name":"AB:08","tagline":"Deconstructed Blonde Imperial Stout.","first_brewed":"11/2011","description":"Flavours and aromas you'd expect from a Stout, but brewed without dark malts. The full mouthfeel comes courtesy of wheat and oats, while smoked malt and the twist additions add the complex flavours normally provided by highly kilned malts.","image_url":"https://images.punkapi.com/v2/62.png","abv":10.43,"ibu":65,"target_fg":1016,"target_og":1095,"ebc":23,"srm":11.5,"ph":4.4,"attenuation_level":83.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Cacao: 25g at FV, Coffee Beans: 37.5g at FV, Oak Chips: 5g at FV, Vanilla Pods: 10 split pods, Liquorice: 5g at FV"},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":9.25,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1.88,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.88,"unit":"kilograms"}},{"name":"Smoked Peaty","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"First Gold","amount":{"value":81.25,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"First Gold","amount":{"value":62.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Coffee Beans","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Caramelised scallops with burnt apple puree","Blackened Cajun chicken","Blondies with chocolate fudge sauce"],"brewers_tips":"Add all twist ingredients to Fermentation Vessel once fermentation is complete. Don’t be afraid to add a little at a time and taste as you go. During mashing in first start with pale malt. Afterwards mix all malts evenly. Go with flaked oats during second half of mashing in process.","contributed_by":"Sam Mason "},{"id":63,"name":"Sunk Punk","tagline":"Ocean Fermented Lager.","first_brewed":"09/2011","description":"It's rumoured just a drop can calm the fiercest of storms. A balance of sweet, salt and savoury, citrus, spruce and caramel. Fermented at the bottom of the North Sea, which just so happens to be the perfect temperature for lagers to ferment.","image_url":"https://images.punkapi.com/v2/63.png","abv":7.1,"ibu":68,"target_fg":1010,"target_og":1056,"ebc":14,"srm":7,"ph":4.4,"attenuation_level":82.1,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":10,"unit":"celsius"}},"twist":"Seabuckthorn: 25g at end, Sea Salt: 20g at middle, Rum: 25ml at end"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":5.21,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":20,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Ahtanum","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Chinook","amount":{"value":20,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Ahtanum","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Chinook","amount":{"value":30,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Ahtanum","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Nelson Sauvin","amount":{"value":140,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 2007 - Pilsen Lager™"},"food_pairing":["Salt baked cod with lemon and dill butter","Beef, oyster and ale pie","Apple and rosemary tart"],"brewers_tips":"Keep the fermentation temperature as steady as possible to allow the lager yeast to do its thing.","contributed_by":"Sam Mason "},{"id":64,"name":"Sub Hop","tagline":"Hopped-Up Imperial Pilsner.","first_brewed":"06/2014","description":"Brewed for the opening of our first bar in Italy, BrewDog Firenze. A mega-hoppy Imperial Pilsner, with toasty malt complexity and tropical New World hops.","image_url":"https://images.punkapi.com/v2/64.png","abv":8,"ibu":35,"target_fg":1016,"target_og":1077,"ebc":15,"srm":7.5,"ph":4.4,"attenuation_level":79.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":9,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.25,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Dextrose","amount":{"value":0.38,"unit":"kilograms"}}],"hops":[{"name":"Saaz","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Hallertauer Mittelfrüh","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Pacifica","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Pacific Jade","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Pacifica","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Pacific Jade","amount":{"value":75,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Pacifica","amount":{"value":37.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 2007- Pilsen Lager™"},"food_pairing":["Seared lemon and herb salmon","Crab linguine","Almond biscotti"],"brewers_tips":"Sit this beer aside for a month to allow it to mellow.","contributed_by":"Sam Mason "},{"id":65,"name":"Bracken's Porter","tagline":"A Tribute To Our Favourite 4 Pawed Friend.","first_brewed":"03/2013","description":"The beer was named Bracken’s Porter as a tribute to our favourite four pawed friend who sadly passed in 2013. Chocolately, robust, warming, laid back and lots of fun - there are plenty of similarities between the two. Bracken we miss you and we hope you like your beer. Long live the original BrewDog.","image_url":"https://images.punkapi.com/v2/keg.png","abv":5,"ibu":50,"target_fg":1010,"target_og":1049,"ebc":110,"srm":55,"ph":4.4,"attenuation_level":79,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":3.63,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.19,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.31,"unit":"kilograms"}},{"name":"Black Malt","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Vic Secret","amount":{"value":12.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Bramling Cross","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"aroma"},{"name":"Challenger","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Grilled vegetable and chicken teriyaki skewers","Chilli covered burger (Sloppy Joe)","Candied bacon topped chocolate cheesecake"],"brewers_tips":"Try to replicate London’s highly carbonated water to really emphasise the dark malt profile.","contributed_by":"Sam Mason "},{"id":66,"name":"Tokyo Rising Sun - Lowland","tagline":"A Beautiful Accident.","first_brewed":"06/2009","description":"A forgotten gem in the deepest, darkest corner of the warehouse. Aged in a Lowland whisky cask resulting in decadent chocolate, toasted vanilla, indulgent spiced fruit, a mesmerizingly hypnotic mouthfeel and new layers that emerge on every sip.","image_url":"https://images.punkapi.com/v2/66.png","abv":13.2,"ibu":85,"target_fg":1023,"target_og":1125,"ebc":140,"srm":71,"ph":4.4,"attenuation_level":82.17,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":null}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Cranberry: 25g at end, Jasmine: 25g at end, Muscovado sugar: 300g at start, Oak chips soaked in lowland whisky: 15g at dry hop"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.6,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":1.75,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.5,"unit":"kilograms"}}],"hops":[{"name":"Chinook","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Chinook","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Galena","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"First Gold","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Chinook","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"WLP099 Super High Gravity Ale"},"food_pairing":["Duck liver paté","Mutton stew","Kirsch chocolate truffles"],"brewers_tips":"Leave on wood for as long as you dare. If possible forget about it for four years.","contributed_by":"Sam Mason "},{"id":67,"name":"Hunter Foundation Pale Ale","tagline":"American Pale Ale.","first_brewed":"05/2012","description":"This straight-up US style pale ale uses some of our favourite hops against a toasty malt base. We brewed this with Sir Tom Hunter at our Fraserburgh brewery - to add a charitable element to your own version, feel free to share this citrusy pale ale with your friends. Or don't, it's your choice.","image_url":"https://images.punkapi.com/v2/67.png","abv":5.4,"ibu":35,"target_fg":1008,"target_og":1050,"ebc":11.5,"srm":5.75,"ph":4.4,"attenuation_level":84,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":63,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":4.3,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.8,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":10,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":15,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":20,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Monterey Jack stuffed grilled jalepenos","Barbecue corn and steak fajita seasoned wrap","Cinnamon & white chocolate churro"],"brewers_tips":"To dry the beer out, mash at a slightly lower temp (62° - 63°C), this will increase the ratio of fermentable sugars in the beer.","contributed_by":"Sam Mason "},{"id":68,"name":"Hype","tagline":"New Zealand Pale Ale.","first_brewed":"08/2007","description":"A perfect pale ale showcase for the tropical profile of New Zealand hops and the intense citrus of US hops.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.1,"ibu":65,"target_fg":1010,"target_og":1042,"ebc":17,"srm":8.5,"ph":4.4,"attenuation_level":76.2,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Maris Otter Extra Pale","amount":{"value":4.02,"unit":"kilograms"}}],"hops":[{"name":"Nelson Sauvin","amount":{"value":2,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Nelson Sauvin","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":2.5,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Quince cheese","Shredded chicken and mango salsa taquitos","Poached pear"],"brewers_tips":"After the beer has fermented, leave it to rest for 2 – 3 days at the lowest temperature possible (ideally 0 – 2'C). This will allow the flavours to marry together, and will transform it into a balanced and amazing beer.","contributed_by":"Sam Mason "},{"id":69,"name":"AB:16","tagline":"Coffee-Infused Belgian Quad.","first_brewed":"02/2014","description":"On the nose, clove and nutmeg, cafe au lait, subtle dark fruit notes, and hints of candied lemon peel. On the palate, smooth & fruity espresso, milk chocolate, and warm brandy-soaked currants are in the middle of a high-class dance-off against the spicy and peppery Belgian character. The overall impression evokes malt loaf or ginger cake.","image_url":"https://images.punkapi.com/v2/69.png","abv":10.6,"ibu":55,"target_fg":1012,"target_og":1090,"ebc":30,"srm":15,"ph":4.4,"attenuation_level":86.7,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Coffee Beans: 250g FV. Raisins: 90g at end. Dark Sugar:140g at end."},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":7.75,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.5,"unit":"kilograms"}},{"name":"Crystal 150","amount":{"value":0.38,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Waimea","amount":{"value":15,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Saaz","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Fuggles","amount":{"value":12.5,"unit":"grams"},"add":"middle","attribute":"flavour"}],"yeast":"Wyeast 3787 - Trappist High Gravity™"},"food_pairing":["Roasted duck","Gorgonzola and rye nut bread with smoked honey ham","Raspberry coffee cheesecake"],"brewers_tips":"For the traditional cellering, age this beer in vessel or bottle for 2 - 3 months at cellar temperature.","contributed_by":"Ali Skinner "},{"id":70,"name":"Sunmaid Stout","tagline":"Rum & Raisin Imperial Stout.","first_brewed":"12/2011","description":"Brewed by Chris Sartori from Stone Brewing Company in 2010. A dark chocolate stout with dried dark fruit finish. Simcoe provides bitterness with subtle fruity supporting notes, contrasting the chocolate and coffee-laden malt profile. The finish is warming with vanilla and rich dark fruit depth.","image_url":"https://images.punkapi.com/v2/keg.png","abv":10.2,"ibu":50,"target_fg":1102,"target_og":1026,"ebc":197,"srm":100,"ph":4.4,"attenuation_level":74.5,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":55}],"fermentation":{"temp":{"value":21,"unit":"celsius"}},"twist":"Age in whisky casks with rum soaked raisins"},"ingredients":{"malt":[{"name":"Pale Ale - Tipple","amount":{"value":10,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Carafa Special Malt Type 3","amount":{"value":0.94,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":0.94,"unit":"kilograms"}},{"name":"Flaked Oats","amount":{"value":1.56,"unit":"kilograms"}}],"hops":[{"name":"Simcoe","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Challenger","amount":{"value":25,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Lapin aux pruneaux (braised rabbit with prunes)","Gouda cheese","Dark chocolate truffles"],"brewers_tips":"Take small volume of wort out of the run off and steep the raisins in it, then crush them up. This will help to release the dark fruit aromas into the wort.","contributed_by":"Sam Mason "},{"id":71,"name":"Pale - Russian Doll","tagline":"Nesting Hop Bomb.","first_brewed":"08/2014","description":"The levels of hops vary throughout the range. We love hops, so all four beers are big, bitter badasses, but by tweaking the amount of each hop used later in the boil and during dry- hopping, we can balance the malty backbone with some unexpected flavours. Simcoe is used in the whirlpool for all four beers, and yet still lends different characters to each.","image_url":"https://images.punkapi.com/v2/71.png","abv":4,"ibu":35,"target_fg":1010,"target_og":1041,"ebc":45,"srm":22.5,"ph":5.2,"attenuation_level":75.6,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":75}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":null},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":3.63,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.13,"unit":"kilograms"}}],"hops":[{"name":"Cascade","amount":{"value":7.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Centennial","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Citra","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":17.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":62.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Cascade","amount":{"value":62.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Centennial","amount":{"value":62.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Citra","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Roast chicken with vegetables and wild rice","Fresh pico de gallo with corn tortilla","Carrot cake"],"brewers_tips":"Create balance through experimentation with the hop amounts and malt backbone.","contributed_by":"Sam Mason "},{"id":72,"name":"Whisky Sour - B-Sides","tagline":"Pilot Brew - Deconstructed Whisky Sour.","first_brewed":"03/2015","description":"Deconstructed whisky sour, reconstructed as a beer.","image_url":"https://images.punkapi.com/v2/keg.png","abv":7,"ibu":20,"target_fg":1021,"target_og":1081,"ebc":12,"srm":6,"ph":3.2,"attenuation_level":74,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":60,"unit":"celsius"},"duration":10},{"temp":{"value":65,"unit":"celsius"},"duration":30},{"temp":{"value":72,"unit":"celsius"},"duration":10},{"temp":{"value":78,"unit":"celsius"},"duration":5}],"fermentation":{"temp":{"value":null,"unit":"celsius"}},"twist":"Kettle Soured"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.88,"unit":"kilograms"}},{"name":"Acidulated Malt","amount":{"value":1.88,"unit":"kilograms"}},{"name":"Wheat Malt","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Rye Malt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Special W","amount":{"value":0.05,"unit":"kilograms"}}],"hops":[{"name":"Amarillo","amount":{"value":8.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Citra","amount":{"value":8.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":8.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Citra","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":1.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Citra","amount":{"value":1.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Simcoe","amount":{"value":1.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Potted fresh & smoked salmon","Spiced nut loaf","Lemon poppyseed donuts"],"brewers_tips":"Lemon poppyseed donuts.","contributed_by":"Sam Mason "},{"id":73,"name":"Black Eyed King Imp - Vietnamese Coffee Edition","tagline":"Vietnamese Coffee Edition.","first_brewed":"12/2014","description":"This is the Vietnamese Coffee Edition. At 12.7% ABV, Black Eyed King Imp is a super intense and twistedly complex brew, with intense notes of sweet vanilla, rich espresso, smooth molasses and bitter chocolate barely contained by the whatever container it's in.","image_url":"https://images.punkapi.com/v2/73.png","abv":12.7,"ibu":85,"target_fg":1038,"target_og":1113.5,"ebc":250,"srm":125,"ph":5.2,"attenuation_level":76.8,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":65,"unit":"celsius"},"duration":50}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":"Coffee Beans: 12.5g at end, Lactose: 125g at FV, Bourbon barrel aged"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":6.25,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Cara","amount":{"value":1.25,"unit":"kilograms"}},{"name":"Crystal","amount":{"value":1.5625,"unit":"kilograms"}},{"name":"Dark Crystal","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Amber","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Brown","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Chocolate","amount":{"value":0.625,"unit":"kilograms"}},{"name":"Roasted Barley","amount":{"value":0.3125,"unit":"kilograms"}}],"hops":[{"name":"Magnum","amount":{"value":62.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Willamette","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"bitter"},{"name":"First Gold","amount":{"value":31.25,"unit":"grams"},"add":"end","attribute":"aroma / bitter"}],"yeast":"Wyeast 1272 - American Ale II™"},"food_pairing":["Bacon sandwich with brown sauce","20hr smoked brisket","Chocolate fudge ice cream"],"brewers_tips":"Buying top notch coffee beans make a huge difference here. Give them a very course grind to get the most out of them.","contributed_by":"Sam Mason "},{"id":74,"name":"Eurotrash","tagline":"Belgian Blonde.","first_brewed":"10/2009","description":"Trashy Blonde with a Belgian Twist. Clove oil, red apples and a drier mouthfeel set this beer apart from its older sister.","image_url":"https://images.punkapi.com/v2/keg.png","abv":4.1,"ibu":52,"target_fg":1010,"target_og":1041,"ebc":17,"srm":8.5,"ph":5.2,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":66,"unit":"celsius"},"duration":90}],"fermentation":{"temp":{"value":19,"unit":"celsius"}},"twist":"Fermented with Belgian yeast for signature character"},"ingredients":{"malt":[{"name":"Extra Pale","amount":{"value":3.25,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.25,"unit":"kilograms"}},{"name":"Munich","amount":{"value":0.38,"unit":"kilograms"}}],"hops":[{"name":"Simcoe","amount":{"value":5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Amarillo","amount":{"value":6.3,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Simcoe","amount":{"value":2.5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Amarillo","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Motueka","amount":{"value":5,"unit":"grams"},"add":"middle","attribute":"flavour"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Amarillo","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Motueka","amount":{"value":12.5,"unit":"grams"},"add":"end","attribute":"flavour"},{"name":"Simcoe","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Amarillo","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"},{"name":"Motueka","amount":{"value":12.5,"unit":"grams"},"add":"dry hop","attribute":"aroma"}],"yeast":"Wyeast 3522 - Belgian Ardennes™"},"food_pairing":["Grilled fish salad","Angelfood cake","Pad Thai"],"brewers_tips":"Don't be scared to let the fermentation temperature climb up another couple of degrees to really emphasize the Belgian character.","contributed_by":"Sam Mason "},{"id":75,"name":"Never Mind The Anabolics","tagline":"Performance-Enhancing India Pale Ale.","first_brewed":"06/2012","description":"Never Mind the Anabolics, a 6.5% India Pale Ale brewed with copious amounts of performance-enhancing natural ingredients. Brewed to commemorate the 2012 Olympics and its merry marketing bandwagon.","image_url":"https://images.punkapi.com/v2/75.png","abv":6.5,"ibu":35,"target_fg":1012,"target_og":1050,"ebc":23,"srm":11.5,"ph":4.4,"attenuation_level":76,"volume":{"value":20,"unit":"liters"},"boil_volume":{"value":25,"unit":"liters"},"method":{"mash_temp":[{"temp":{"value":68,"unit":"celsius"},"duration":30}],"fermentation":{"temp":{"value":18,"unit":"celsius"}},"twist":"Lycii Berries: 7.5g at end, Ginseng: 5.625g at end, Guarana: 25g at end, Kolabu: 25g at end, Gingko: 6.25g at end, Matcha Tea: 12.5g at end, Maca Powder: 16.25g at end"},"ingredients":{"malt":[{"name":"Extra Pale - Spring Blend","amount":{"value":4.38,"unit":"kilograms"}},{"name":"Wheat","amount":{"value":0.63,"unit":"kilograms"}},{"name":"Caramalt","amount":{"value":0.31,"unit":"kilograms"}}],"hops":[{"name":"Motueka","amount":{"value":37.5,"unit":"grams"},"add":"start","attribute":"bitter"},{"name":"Motueka","amount":{"value":18.75,"unit":"grams"},"add":"end","attribute":"flavour"}],"yeast":"Wyeast 1056 - American Ale™"},"food_pairing":["Grilled chicken salad with bacon and avocado","Red pepper houmous and flat bread","Matcha green tea cake"],"brewers_tips":"Mix the powders into a paste before adding to the wort kettle. This will prevent the powders from balling up and not bringing the full flavour effect.","contributed_by":"Sam Mason "}] """ } diff --git a/PunkAPI/Classes/PunkAPI.swift b/PunkAPI/Classes/PunkAPI.swift index 71fa077..fff79e4 100644 --- a/PunkAPI/Classes/PunkAPI.swift +++ b/PunkAPI/Classes/PunkAPI.swift @@ -30,9 +30,7 @@ public class PunkAPI { } self.configuration.session.dataTask(with: url) { (result: Result<[Beer]>) in - queue.async { - completion(result) - } + queue.async { completion(result) } }.resume() } } From 51c0c2f317f72f8f2515b774ca928ecdb9c8ca5e Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Thu, 21 Feb 2019 17:05:32 +0100 Subject: [PATCH 06/37] Feat: add parameters to Beer model --- Content/Beer.swift | 53 +++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/Content/Beer.swift b/Content/Beer.swift index 2d90edb..b152bd4 100644 --- a/Content/Beer.swift +++ b/Content/Beer.swift @@ -29,32 +29,45 @@ public struct Beer: Codable { var attenuationLevel: Float? var volume: Volume? var boilVolume: Volume? -// var method: Method + var method: Method? + var ingredients: Recipe? + var foodPairing: [String] + var brewersTips: String? + var contributedBy: String? } -extension Beer { +struct Volume: Codable { + var value: Float + var unit: String +} + +struct Recipe: Codable { - struct Volume: Codable { - - var value: Float - var unit: String + struct Ingredient: Codable { + var name: String + var amount: Quantity? } + + var malt: [Ingredient] + var hops: [Ingredient] + var yeast: String? +} + +struct Method: Codable { - struct Temperature: Codable { - - var value: Float - var unit: String - } - struct Method { - - var mashTemp: [Step] - var fermentation: Temperature - - struct Step { - var temp: Temperature - var duration: Float? - } + + struct Step: Codable { + var temp: Quantity? + var duration: Float? } + + var mashTemp: [Step]? + var fermentation: Quantity? + var twist: String? } +struct Quantity: Codable { + var value: Float? + var unit: String? +} From f2e1a84e8860a341f43d3aeddc517944f10299c2 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Thu, 21 Feb 2019 17:06:01 +0100 Subject: [PATCH 07/37] Feat: add CI configuration --- .travis.yml | 18 ++++++------------ Gemfile | 5 +++++ 2 files changed, 11 insertions(+), 12 deletions(-) create mode 100644 Gemfile diff --git a/.travis.yml b/.travis.yml index b3ae6c9..ed2de48 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,8 @@ -# references: -# * https://www.objc.io/issues/6-build-tools/travis-ci/ -# * https://github.com/supermarin/xcpretty#usage - -osx_image: xcode7.3 language: objective-c -# cache: cocoapods -# podfile: Example/Podfile -# before_install: -# - gem install cocoapods # Since Travis is not always on latest version -# - pod install --project-directory=Example +osx_image: xcode10 +before_install: +- gem update fastlane --no-ri --no-rdoc --no-document +- gem update cocoapods --no-ri --no-rdoc --no-document script: -- set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/PunkAPI.xcworkspace -scheme PunkAPI-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty -- pod lib lint +- cd Example/ +- fastlane ci diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..85ba602 --- /dev/null +++ b/Gemfile @@ -0,0 +1,5 @@ +source "https://rubygems.org" + +gem "fastlane" +gem "cocoapods" +gem "slather" From f4b71d416eefa60d2c41e8f3c6dd1e568fea0f0b Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Thu, 21 Feb 2019 17:16:45 +0100 Subject: [PATCH 08/37] Feat: configure fastlane --- Example/fastlane/Appfile | 0 Example/fastlane/Fastfile | 73 ++++++++++++++++++++++++++++++++++++++ Example/fastlane/README.md | 54 ++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 Example/fastlane/Appfile create mode 100644 Example/fastlane/Fastfile create mode 100644 Example/fastlane/README.md diff --git a/Example/fastlane/Appfile b/Example/fastlane/Appfile new file mode 100644 index 0000000..e69de29 diff --git a/Example/fastlane/Fastfile b/Example/fastlane/Fastfile new file mode 100644 index 0000000..916e89f --- /dev/null +++ b/Example/fastlane/Fastfile @@ -0,0 +1,73 @@ +# This file contains the fastlane.tools configuration +# You can find the documentation at https://docs.fastlane.tools +# +# For a list of all available actions, check out +# +# https://docs.fastlane.tools/actions +# +# For a list of all available plugins, check out +# +# https://docs.fastlane.tools/plugins/available-plugins +# + +update_fastlane + +default_platform(:ios) + +platform :ios do + + desc "Default CI lane" + lane :ci do + lint + pod_lint + test + coverage + end + + desc "SwiftLint linting" + lane :lint do + swiftlint( + mode: :lint, + ignore_exit_status: false + ) + end + + desc "Pod lib lint" + lane :pod_lint do + Dir.chdir("../..") do + sh("pod lib lint") + end + end + + desc "Runs all the tests" + lane :test do + scan( + scheme: "PunkAPI-Example", + device: "iPhone XS", + code_coverage: true + ) + end + + desc "Slather sends coverage to Coveralls" + lane :coverage do + slather( + travis: true, + workspace: "PunkAPI.xcworkspace", + proj: "PunkAPI.xcodeproj", + scheme: "PunkAPI-Example", + binary_basename: "PunkAPI", + source_directory: "../PunkAPI", + simple_output: true, + coveralls: true + ) + end + + desc "Clean environment after all operations" + lane :clean do + clean_build_artifacts + end + + after_all do |lane| + clean + end +end diff --git a/Example/fastlane/README.md b/Example/fastlane/README.md new file mode 100644 index 0000000..e9d099b --- /dev/null +++ b/Example/fastlane/README.md @@ -0,0 +1,54 @@ +fastlane documentation +================ +# Installation + +Make sure you have the latest version of the Xcode command line tools installed: + +``` +xcode-select --install +``` + +Install _fastlane_ using +``` +[sudo] gem install fastlane -NV +``` +or alternatively using `brew cask install fastlane` + +# Available Actions +## iOS +### ios ci +``` +fastlane ios ci +``` +Default CI lane +### ios lint +``` +fastlane ios lint +``` +SwiftLint linting +### ios pod_lint +``` +fastlane ios pod_lint +``` +Pod lib lint +### ios test +``` +fastlane ios test +``` +Runs all the tests +### ios coverage +``` +fastlane ios coverage +``` +Slather sends coverage to Coveralls +### ios clean +``` +fastlane ios clean +``` +Clean environment after all operations + +---- + +This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run. +More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). +The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). From 457342bbdfda135e147dffc7d0a80b53f5d48221 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Thu, 21 Feb 2019 17:22:54 +0100 Subject: [PATCH 09/37] fix: remove lint lanes --- Example/fastlane/Fastfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Example/fastlane/Fastfile b/Example/fastlane/Fastfile index 916e89f..2d6970f 100644 --- a/Example/fastlane/Fastfile +++ b/Example/fastlane/Fastfile @@ -18,8 +18,6 @@ platform :ios do desc "Default CI lane" lane :ci do - lint - pod_lint test coverage end From 130e839d9971fa7c56ea33825eca4bf8b5ed287e Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Thu, 21 Feb 2019 22:24:12 +0100 Subject: [PATCH 10/37] Fix: target configuration --- Example/Pods/Pods.xcodeproj/project.pbxproj | 3 ++- .../xcschemes/PunkAPI-Example.xcscheme | 11 ++++++++ Example/PunkAPI/ViewController.swift | 2 -- Example/fastlane/report.xml | 25 +++++++++++++++++++ .../Classes/Content}/Beer.swift | 0 5 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 Example/fastlane/report.xml rename {Content => PunkAPI/Classes/Content}/Beer.swift (100%) diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 635d910..7c1f9b3 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -207,7 +207,8 @@ children = ( 9767CBEF221977D300E684C4 /* Beer.swift */, ); - path = Content; + name = Content; + path = PunkAPI/Classes/Content; sourceTree = ""; }; 9BFECB8663CD309F9214B4311C96BCB5 /* Pods-PunkAPI_Example */ = { diff --git a/Example/PunkAPI.xcodeproj/xcshareddata/xcschemes/PunkAPI-Example.xcscheme b/Example/PunkAPI.xcodeproj/xcshareddata/xcschemes/PunkAPI-Example.xcscheme index 0dfe2e8..c7c42dd 100644 --- a/Example/PunkAPI.xcodeproj/xcshareddata/xcschemes/PunkAPI-Example.xcscheme +++ b/Example/PunkAPI.xcodeproj/xcshareddata/xcschemes/PunkAPI-Example.xcscheme @@ -40,7 +40,18 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + codeCoverageEnabled = "YES" + onlyGenerateCoverageForSpecifiedTargets = "YES" shouldUseLaunchSchemeArgsEnv = "YES"> + + + + diff --git a/Example/PunkAPI/ViewController.swift b/Example/PunkAPI/ViewController.swift index b662cf9..6b51f7d 100644 --- a/Example/PunkAPI/ViewController.swift +++ b/Example/PunkAPI/ViewController.swift @@ -18,6 +18,4 @@ class ViewController: UIViewController { print(beers) }) } - } - diff --git a/Example/fastlane/report.xml b/Example/fastlane/report.xml new file mode 100644 index 0000000..4edc239 --- /dev/null +++ b/Example/fastlane/report.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Content/Beer.swift b/PunkAPI/Classes/Content/Beer.swift similarity index 100% rename from Content/Beer.swift rename to PunkAPI/Classes/Content/Beer.swift From 27911c944d6892aea9ee71ac0a752ba7d145745e Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Thu, 21 Feb 2019 22:33:22 +0100 Subject: [PATCH 11/37] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cc0f28c..8da3267 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # PunkAPI [![CI Status](https://img.shields.io/travis/acct=/PunkAPI.svg?style=flat)](https://travis-ci.org/acct=/PunkAPI) -[![Version](https://img.shields.io/cocoapods/v/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) +[![Coverage Status](https://coveralls.io/repos/github/Oni-zerone/PunkAPI/badge.svg?branch=develop)](https://coveralls.io/github/Oni-zerone/PunkAPI?branch=develop)[![Version](https://img.shields.io/cocoapods/v/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) [![License](https://img.shields.io/cocoapods/l/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) [![Platform](https://img.shields.io/cocoapods/p/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) From 5fbd15711fd8a3c8851981f7ca09e4ed1218ed88 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Thu, 21 Feb 2019 22:33:55 +0100 Subject: [PATCH 12/37] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8da3267..23f217b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # PunkAPI [![CI Status](https://img.shields.io/travis/acct=/PunkAPI.svg?style=flat)](https://travis-ci.org/acct=/PunkAPI) -[![Coverage Status](https://coveralls.io/repos/github/Oni-zerone/PunkAPI/badge.svg?branch=develop)](https://coveralls.io/github/Oni-zerone/PunkAPI?branch=develop)[![Version](https://img.shields.io/cocoapods/v/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) +[![Coverage Status](https://coveralls.io/repos/github/Oni-zerone/PunkAPI/badge.svg?branch=develop)](https://coveralls.io/github/Oni-zerone/PunkAPI?branch=develop)[![Version](https://img.shields.io/cocoapods/v/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) [![License](https://img.shields.io/cocoapods/l/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) [![Platform](https://img.shields.io/cocoapods/p/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) From a276d624bf741e08d3655517727d104b315e3a86 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Fri, 22 Feb 2019 07:15:29 +0100 Subject: [PATCH 13/37] feat: Split representation --- Example/Pods/Pods.xcodeproj/project.pbxproj | 20 ++++++++++++ Example/PunkAPI/ViewController.swift | 6 ++-- PunkAPI/Classes/Content/Beer.swift | 36 --------------------- PunkAPI/Classes/Content/Method.swift | 20 ++++++++++++ PunkAPI/Classes/Content/Quantity.swift | 19 +++++++++++ PunkAPI/Classes/Content/Recipe.swift | 20 ++++++++++++ 6 files changed, 82 insertions(+), 39 deletions(-) create mode 100644 PunkAPI/Classes/Content/Method.swift create mode 100644 PunkAPI/Classes/Content/Quantity.swift create mode 100644 PunkAPI/Classes/Content/Recipe.swift diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 7c1f9b3..a99d3e5 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -18,6 +18,9 @@ 9767CBF0221977D300E684C4 /* Beer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBEF221977D300E684C4 /* Beer.swift */; }; 9767CBF22219795E00E684C4 /* BeerRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF12219795E00E684C4 /* BeerRequest.swift */; }; 9767CBF422197DCC00E684C4 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF322197DCC00E684C4 /* Errors.swift */; }; + 9767CBFE221FC9F900E684C4 /* Quantity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBFD221FC9F900E684C4 /* Quantity.swift */; }; + 9767CBFF221FC9FE00E684C4 /* Recipe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBFB221FC9A700E684C4 /* Recipe.swift */; }; + 9767CC01221FCA2A00E684C4 /* Method.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC00221FCA2A00E684C4 /* Method.swift */; }; 9DEE51DC320AFD89F8CCE79E659D0E92 /* Pods-PunkAPI_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; AD6B8F0860FB91889F808D08F168E096 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBF879A7A0C8CE59F1DD2A17BB11873 /* Request.swift */; }; B0D852DC953C7A0E2C1CB872F9E315BB /* Pods-PunkAPI_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */; }; @@ -67,6 +70,9 @@ 9767CBEF221977D300E684C4 /* Beer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Beer.swift; sourceTree = ""; }; 9767CBF12219795E00E684C4 /* BeerRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerRequest.swift; sourceTree = ""; }; 9767CBF322197DCC00E684C4 /* Errors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Errors.swift; path = PunkAPI/Classes/Errors.swift; sourceTree = ""; }; + 9767CBFB221FC9A700E684C4 /* Recipe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Recipe.swift; sourceTree = ""; }; + 9767CBFD221FC9F900E684C4 /* Quantity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Quantity.swift; sourceTree = ""; }; + 9767CC00221FCA2A00E684C4 /* Method.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Method.swift; sourceTree = ""; }; 9D14926C4AE138B3C55CE27E18BE194D /* Pods-PunkAPI_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Tests.modulemap"; sourceTree = ""; }; 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Example-dummy.m"; sourceTree = ""; }; @@ -206,6 +212,9 @@ isa = PBXGroup; children = ( 9767CBEF221977D300E684C4 /* Beer.swift */, + 9767CBFB221FC9A700E684C4 /* Recipe.swift */, + 9767CBFD221FC9F900E684C4 /* Quantity.swift */, + 9767CC00221FCA2A00E684C4 /* Method.swift */, ); name = Content; path = PunkAPI/Classes/Content; @@ -361,6 +370,9 @@ 104A4972E6668483EF3BA6EE08D840AF = { LastSwiftMigration = 1010; }; + C1DB41E820BFF9D57C1A713EEC3A7C98 = { + LastSwiftMigration = 1010; + }; }; }; buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; @@ -430,11 +442,14 @@ FB6E32A7831DCA2AE93BD8C3F87FA8E3 /* Configuration.swift in Sources */, 9767CBEA2219744000E684C4 /* Result.swift in Sources */, 3D7A5283D0833518F12109285F42CDD6 /* PunkAPI-dummy.m in Sources */, + 9767CBFE221FC9F900E684C4 /* Quantity.swift in Sources */, 9767CBF22219795E00E684C4 /* BeerRequest.swift in Sources */, DB20D4F60BC185671791B119F6F2629E /* PunkAPI.swift in Sources */, 9767CBF0221977D300E684C4 /* Beer.swift in Sources */, 9767CBF422197DCC00E684C4 /* Errors.swift in Sources */, AD6B8F0860FB91889F808D08F168E096 /* Request.swift in Sources */, + 9767CBFF221FC9FE00E684C4 /* Recipe.swift in Sources */, + 9767CC01221FCA2A00E684C4 /* Method.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -526,6 +541,7 @@ baseConfigurationReference = A5D146483FC9684CF2C15F85C081EF35 /* Pods-PunkAPI_Example.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -548,6 +564,7 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -752,6 +769,7 @@ baseConfigurationReference = E816F7DA6C1CBE532E1590E0F05B9532 /* Pods-PunkAPI_Example.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -774,6 +792,8 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; diff --git a/Example/PunkAPI/ViewController.swift b/Example/PunkAPI/ViewController.swift index 1de4130..e4ebd95 100644 --- a/Example/PunkAPI/ViewController.swift +++ b/Example/PunkAPI/ViewController.swift @@ -14,8 +14,8 @@ class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - PunkAPI().get(BeerRequest(id: 6), completion: { beers in - print(beers) - }) +// PunkAPI().get(BeerRequest(id: 6), completion: { beers in +// print(beers) +// }) } } diff --git a/PunkAPI/Classes/Content/Beer.swift b/PunkAPI/Classes/Content/Beer.swift index 9ef3379..6b646d1 100644 --- a/PunkAPI/Classes/Content/Beer.swift +++ b/PunkAPI/Classes/Content/Beer.swift @@ -35,39 +35,3 @@ public struct Beer: Codable { var brewersTips: String? var contributedBy: String? } - -struct Volume: Codable { - var value: Float? - var unit: String? -} - -struct Recipe: Codable { - - struct Ingredient: Codable { - var name: String? - var amount: Quantity? - } - - var malt: [Ingredient] - var hops: [Ingredient] - var yeast: String? -} - -struct Method: Codable { - - - - struct Step: Codable { - var temp: Quantity? - var duration: Float? - } - - var mashTemp: [Step]? - var fermentation: Quantity? - var twist: String? -} - -struct Quantity: Codable { - var value: Float? - var unit: String? -} diff --git a/PunkAPI/Classes/Content/Method.swift b/PunkAPI/Classes/Content/Method.swift new file mode 100644 index 0000000..ef49899 --- /dev/null +++ b/PunkAPI/Classes/Content/Method.swift @@ -0,0 +1,20 @@ +// +// Method.swift +// PunkAPI +// +// Created by Andrea Altea on 22/02/2019. +// + +import Foundation + +public struct Method: Codable { + + struct Step: Codable { + var temp: Quantity? + var duration: Float? + } + + var mashTemp: [Step]? + var fermentation: Quantity? + var twist: String? +} diff --git a/PunkAPI/Classes/Content/Quantity.swift b/PunkAPI/Classes/Content/Quantity.swift new file mode 100644 index 0000000..7cce0e3 --- /dev/null +++ b/PunkAPI/Classes/Content/Quantity.swift @@ -0,0 +1,19 @@ +// +// Quantity.swift +// PunkAPI +// +// Created by Andrea Altea on 22/02/2019. +// + +import Foundation + +public struct Quantity: Codable { + var value: Float? + var unit: String? +} + +public typealias Temperature = Quantity + +public typealias Mass = Quantity + +public typealias Volume = Quantity diff --git a/PunkAPI/Classes/Content/Recipe.swift b/PunkAPI/Classes/Content/Recipe.swift new file mode 100644 index 0000000..19a00d8 --- /dev/null +++ b/PunkAPI/Classes/Content/Recipe.swift @@ -0,0 +1,20 @@ +// +// Recipe.swift +// Pods-PunkAPI_Example +// +// Created by Andrea Altea on 22/02/2019. +// + +import Foundation + +public struct Recipe: Codable { + + public struct Ingredient: Codable { + var name: String? + var amount: Quantity? + } + + var malt: [Ingredient] + var hops: [Ingredient] + var yeast: String? +} From 8ffc617cb4e2194e9ca7634786f116ddce8548a9 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Fri, 22 Feb 2019 08:18:05 +0100 Subject: [PATCH 14/37] Feat: use typealias instead of generic Quantity --- PunkAPI/Classes/Content/Method.swift | 4 ++-- PunkAPI/Classes/Content/Recipe.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PunkAPI/Classes/Content/Method.swift b/PunkAPI/Classes/Content/Method.swift index ef49899..bcee6d9 100644 --- a/PunkAPI/Classes/Content/Method.swift +++ b/PunkAPI/Classes/Content/Method.swift @@ -10,11 +10,11 @@ import Foundation public struct Method: Codable { struct Step: Codable { - var temp: Quantity? + var temp: Temperature? var duration: Float? } var mashTemp: [Step]? - var fermentation: Quantity? + var fermentation: Temperature? var twist: String? } diff --git a/PunkAPI/Classes/Content/Recipe.swift b/PunkAPI/Classes/Content/Recipe.swift index 19a00d8..7110736 100644 --- a/PunkAPI/Classes/Content/Recipe.swift +++ b/PunkAPI/Classes/Content/Recipe.swift @@ -11,7 +11,7 @@ public struct Recipe: Codable { public struct Ingredient: Codable { var name: String? - var amount: Quantity? + var amount: Mass? } var malt: [Ingredient] From 33ca04a6c35404d1882e52109de3d321c37b29fe Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sat, 23 Feb 2019 12:42:44 +0100 Subject: [PATCH 15/37] chore: update parsing tests --- Example/Pods/Pods.xcodeproj/project.pbxproj | 312 ++++++++++---------- Example/Tests/BeerParsingTests.swift | 7 +- 2 files changed, 151 insertions(+), 168 deletions(-) diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index a99d3e5..7967b7e 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -8,24 +8,24 @@ /* Begin PBXBuildFile section */ 1DEF7BF616CC3F2EF46A7F9E5514F9AC /* Pods-PunkAPI_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E9F6D3BEDEF11CDF5DC7C24AEF5989 /* Pods-PunkAPI_Tests-dummy.m */; }; - 3D7A5283D0833518F12109285F42CDD6 /* PunkAPI-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DB27FF57BF224EBB035E6BD38B873FD /* PunkAPI-dummy.m */; }; + 3AF70E263893077BB94A1C3F36DCC044 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49FB5023B50B37DFC2215303164C7685 /* Errors.swift */; }; 4DE6F5415AA32E45E1A1B40AA8194B63 /* Pods-PunkAPI_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E322AC54183F0711E107C333BF42C3CF /* Pods-PunkAPI_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4F478C6F6571A694E377026C7020B987 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */; }; 5563E1330468FB6D76F769A6697DF682 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */; }; + 5ABF50E02687C014E47088344889FC06 /* Beer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 541ACAD8BAF53EB42A722470D92D1723 /* Beer.swift */; }; + 6017B5D2AAB067785D0E2EE754D97A17 /* Recipe.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE9253651B7E158F09FC4029478AD23A /* Recipe.swift */; }; + 80B5BF4A54A873CBBDE11FD50E93473F /* BeerRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 494668F6F12367A934530175780F1FB4 /* BeerRequest.swift */; }; 861F0ED5029160D63BEA52EEDC4F5B2D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */; }; - 94ACB62152B83DE972430EAA4B24D449 /* PunkAPI-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E72CC1703129F4F85A80F609B175F2AA /* PunkAPI-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9767CBEA2219744000E684C4 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBE92219744000E684C4 /* Result.swift */; }; - 9767CBF0221977D300E684C4 /* Beer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBEF221977D300E684C4 /* Beer.swift */; }; - 9767CBF22219795E00E684C4 /* BeerRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF12219795E00E684C4 /* BeerRequest.swift */; }; - 9767CBF422197DCC00E684C4 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF322197DCC00E684C4 /* Errors.swift */; }; - 9767CBFE221FC9F900E684C4 /* Quantity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBFD221FC9F900E684C4 /* Quantity.swift */; }; - 9767CBFF221FC9FE00E684C4 /* Recipe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBFB221FC9A700E684C4 /* Recipe.swift */; }; - 9767CC01221FCA2A00E684C4 /* Method.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC00221FCA2A00E684C4 /* Method.swift */; }; + 89899DFDA224AF6393CF9985FF2AE13E /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = F184F71C3E715F7CB4001C228E19BEBB /* Request.swift */; }; + 8CA330EBFA4F61AE26881286B24648A7 /* Method.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FCD590B492E88AEC8C08B25E45BCFA7 /* Method.swift */; }; + 90001FCA9653A9974B648EAF681F4DD4 /* PunkAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = A96C503FD3BF058AD217F43E4A5954BB /* PunkAPI.swift */; }; + 94ACB62152B83DE972430EAA4B24D449 /* PunkAPI-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E7002BDD7866D71B1BE5B92068B1D65E /* PunkAPI-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9DEE51DC320AFD89F8CCE79E659D0E92 /* Pods-PunkAPI_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AD6B8F0860FB91889F808D08F168E096 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBF879A7A0C8CE59F1DD2A17BB11873 /* Request.swift */; }; + A1658BA79EB16D586EE25257AD1D8ED6 /* PunkAPI-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = ED357DDF7318810430C08E0AD4316358 /* PunkAPI-dummy.m */; }; + A3F6E06BFFDEF9DAD8325928091F4B00 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BAFF56967C81FF81A5FE0A0F4AC9EFC /* Result.swift */; }; B0D852DC953C7A0E2C1CB872F9E315BB /* Pods-PunkAPI_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */; }; - DB20D4F60BC185671791B119F6F2629E /* PunkAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C8708EEF51A0078E3211F1AA5F78C06 /* PunkAPI.swift */; }; - FB6E32A7831DCA2AE93BD8C3F87FA8E3 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AD5D712F315E66077D59EE9C31CF689 /* Configuration.swift */; }; + C0BB3FEC5BB8EF2E7C42FD464D459623 /* Quantity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A9D4151E2B98C6AEE60102C96A95D43 /* Quantity.swift */; }; + D8CFB7B7D1AAC97CCB20D1DD5C56FB9B /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD1936865DE99565E7C6A3CA8A62046 /* Configuration.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -48,47 +48,47 @@ /* Begin PBXFileReference section */ 06BAF05CBDEA8E295E4784A5A5D4506C /* Pods-PunkAPI_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PunkAPI_Tests-acknowledgements.plist"; sourceTree = ""; }; 08865B1A9072612C58080056C52A36BE /* Pods-PunkAPI_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Example.modulemap"; sourceTree = ""; }; - 0AD5D712F315E66077D59EE9C31CF689 /* Configuration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Configuration.swift; path = PunkAPI/Classes/Configuration.swift; sourceTree = ""; }; - 1A11ED2EBFB85AEE905043364BD068DB /* PunkAPI.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PunkAPI.xcconfig; sourceTree = ""; }; - 1AFB7D35FB6048047A48B079FB616B3E /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; - 2293F81F3EBE30B333C3070B12ABBF5B /* PunkAPI.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = PunkAPI.modulemap; sourceTree = ""; }; + 1A9D4151E2B98C6AEE60102C96A95D43 /* Quantity.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Quantity.swift; sourceTree = ""; }; + 1AE9EEDB05092385E557ED3979AAEBC1 /* PunkAPI.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PunkAPI.xcconfig; sourceTree = ""; }; + 1BAFF56967C81FF81A5FE0A0F4AC9EFC /* Result.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = ""; }; + 2B6E62A798BEE3FE5AE9D84C877FD756 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 2EC29BADC6D4B129C97F077B8D1AAD24 /* Pods-PunkAPI_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Example-frameworks.sh"; sourceTree = ""; }; 34E9F6D3BEDEF11CDF5DC7C24AEF5989 /* Pods-PunkAPI_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Tests-dummy.m"; sourceTree = ""; }; - 3CA7DD0E0D9E3D052F0DA83C7B3B79FC /* Pods_PunkAPI_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3CA7DD0E0D9E3D052F0DA83C7B3B79FC /* Pods_PunkAPI_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PunkAPI_Tests.framework; path = "Pods-PunkAPI_Tests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3DD1936865DE99565E7C6A3CA8A62046 /* Configuration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Configuration.swift; path = PunkAPI/Classes/Configuration.swift; sourceTree = ""; }; + 3F4208A029892D178EE8F5C95D6D79EB /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; + 3FCD590B492E88AEC8C08B25E45BCFA7 /* Method.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Method.swift; sourceTree = ""; }; 492C127C07A0D9D778B3D645FCDED6AC /* Pods-PunkAPI_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Tests.release.xcconfig"; sourceTree = ""; }; - 5C8708EEF51A0078E3211F1AA5F78C06 /* PunkAPI.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PunkAPI.swift; path = PunkAPI/Classes/PunkAPI.swift; sourceTree = ""; }; + 494668F6F12367A934530175780F1FB4 /* BeerRequest.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BeerRequest.swift; sourceTree = ""; }; + 49FB5023B50B37DFC2215303164C7685 /* Errors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Errors.swift; path = PunkAPI/Classes/Errors.swift; sourceTree = ""; }; + 541ACAD8BAF53EB42A722470D92D1723 /* Beer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Beer.swift; sourceTree = ""; }; + 54767361581B8332A2D7629F5E98048E /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; 608E9332AF8468043B49B03317025805 /* Pods-PunkAPI_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Tests-frameworks.sh"; sourceTree = ""; }; 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PunkAPI_Example-umbrella.h"; sourceTree = ""; }; 6EDD1194CE9C142C26AD6C6803C306E4 /* Pods-PunkAPI_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Tests.debug.xcconfig"; sourceTree = ""; }; 7F7764549D1799C2D5D6A7B2D65E3550 /* Pods-PunkAPI_Example-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Example-resources.sh"; sourceTree = ""; }; 8342B62283B06E1CA90A14E1BCB6D62B /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 8458C84A594F726E1A8DB6294F78DB73 /* Pods-PunkAPI_Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Tests-resources.sh"; sourceTree = ""; }; - 8DB27FF57BF224EBB035E6BD38B873FD /* PunkAPI-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PunkAPI-dummy.m"; sourceTree = ""; }; + 864A4FE64365AC74BB9E53A4618E5F55 /* PunkAPI.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; path = PunkAPI.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 92229C81AD3A318707A49C8449AEB2F5 /* Pods-PunkAPI_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PunkAPI_Example-acknowledgements.plist"; sourceTree = ""; }; - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 9767CBE92219744000E684C4 /* Result.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Result.swift; path = PunkAPI/Classes/Request/Result.swift; sourceTree = ""; }; - 9767CBEF221977D300E684C4 /* Beer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Beer.swift; sourceTree = ""; }; - 9767CBF12219795E00E684C4 /* BeerRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerRequest.swift; sourceTree = ""; }; - 9767CBF322197DCC00E684C4 /* Errors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Errors.swift; path = PunkAPI/Classes/Errors.swift; sourceTree = ""; }; - 9767CBFB221FC9A700E684C4 /* Recipe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Recipe.swift; sourceTree = ""; }; - 9767CBFD221FC9F900E684C4 /* Quantity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Quantity.swift; sourceTree = ""; }; - 9767CC00221FCA2A00E684C4 /* Method.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Method.swift; sourceTree = ""; }; + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 9D14926C4AE138B3C55CE27E18BE194D /* Pods-PunkAPI_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Tests.modulemap"; sourceTree = ""; }; - 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PunkAPI_Example.framework; path = "Pods-PunkAPI_Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Example-dummy.m"; sourceTree = ""; }; A5D146483FC9684CF2C15F85C081EF35 /* Pods-PunkAPI_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Example.release.xcconfig"; sourceTree = ""; }; - BAFFC5AEB631CBE680C80CE0652ADBE2 /* PunkAPI-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PunkAPI-prefix.pch"; sourceTree = ""; }; - BBBF879A7A0C8CE59F1DD2A17BB11873 /* Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = ""; }; + A96C503FD3BF058AD217F43E4A5954BB /* PunkAPI.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PunkAPI.swift; path = PunkAPI/Classes/PunkAPI.swift; sourceTree = ""; }; + CE9253651B7E158F09FC4029478AD23A /* Recipe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Recipe.swift; sourceTree = ""; }; + CFBB1E2E92ABC5FA4F246BD9E188EBB3 /* PunkAPI.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = PunkAPI.modulemap; sourceTree = ""; }; D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - DEDE7F6F743486EEE8CDF26C3F19CF0F /* PunkAPI.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; path = PunkAPI.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; E322AC54183F0711E107C333BF42C3CF /* Pods-PunkAPI_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PunkAPI_Tests-umbrella.h"; sourceTree = ""; }; + E7002BDD7866D71B1BE5B92068B1D65E /* PunkAPI-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PunkAPI-umbrella.h"; sourceTree = ""; }; E722B264627A535D845CCF418E225784 /* Pods-PunkAPI_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PunkAPI_Tests-acknowledgements.markdown"; sourceTree = ""; }; - E72CC1703129F4F85A80F609B175F2AA /* PunkAPI-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PunkAPI-umbrella.h"; sourceTree = ""; }; E816F7DA6C1CBE532E1590E0F05B9532 /* Pods-PunkAPI_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Example.debug.xcconfig"; sourceTree = ""; }; - E874B75DA5C3ABAE4B0B94E8DB6C6045 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; EAE741F8D3D7DED0544AD07D421892ED /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - F03BE7FD6C231D53225FB54CC54F7FC1 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - FA66D5ED6E33AA7DD32A8C962841F3B0 /* PunkAPI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PunkAPI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + ED0E564BBBF9D91E8AA8F76C0E47F9C9 /* PunkAPI-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PunkAPI-prefix.pch"; sourceTree = ""; }; + ED357DDF7318810430C08E0AD4316358 /* PunkAPI-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PunkAPI-dummy.m"; sourceTree = ""; }; + F184F71C3E715F7CB4001C228E19BEBB /* Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = ""; }; + FA66D5ED6E33AA7DD32A8C962841F3B0 /* PunkAPI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = PunkAPI.framework; path = PunkAPI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; FB1D3C212D7A0519F22CF554E249675E /* Pods-PunkAPI_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PunkAPI_Example-acknowledgements.markdown"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -120,26 +120,20 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 44D5347904CF754D6785B84253F2574A /* iOS */ = { + 3C48D264DEAC135E647F4628351B96D3 /* Development Pods */ = { isa = PBXGroup; children = ( - D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */, + B18B6D748213693EB25E110701CCA43E /* PunkAPI */, ); - name = iOS; + name = "Development Pods"; sourceTree = ""; }; - 4922267629DB1812F5525CC2246D2338 /* Support Files */ = { + 44D5347904CF754D6785B84253F2574A /* iOS */ = { isa = PBXGroup; children = ( - F03BE7FD6C231D53225FB54CC54F7FC1 /* Info.plist */, - 2293F81F3EBE30B333C3070B12ABBF5B /* PunkAPI.modulemap */, - 1A11ED2EBFB85AEE905043364BD068DB /* PunkAPI.xcconfig */, - 8DB27FF57BF224EBB035E6BD38B873FD /* PunkAPI-dummy.m */, - BAFFC5AEB631CBE680C80CE0652ADBE2 /* PunkAPI-prefix.pch */, - E72CC1703129F4F85A80F609B175F2AA /* PunkAPI-umbrella.h */, + D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */, ); - name = "Support Files"; - path = "Example/Pods/Target Support Files/PunkAPI"; + name = iOS; sourceTree = ""; }; 5E6C37C04887F82A8C550F9B76E5B746 /* Targets Support Files */ = { @@ -151,16 +145,6 @@ name = "Targets Support Files"; sourceTree = ""; }; - 6719D069938A455DA268A952D46C9D57 /* Request */ = { - isa = PBXGroup; - children = ( - BBBF879A7A0C8CE59F1DD2A17BB11873 /* Request.swift */, - 9767CBF12219795E00E684C4 /* BeerRequest.swift */, - ); - name = Request; - path = PunkAPI/Classes/Request; - sourceTree = ""; - }; 6C92B5E2C39B71B9A3D59EB753CF598A /* Products */ = { isa = PBXGroup; children = ( @@ -171,50 +155,38 @@ name = Products; sourceTree = ""; }; - 7DB346D0F39D3F0E887471402A8071AB = { + 6FCCF155F5EBF133E1D6AAA9C42FCD87 /* Support Files */ = { isa = PBXGroup; children = ( - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, - B4EA824994F2844B351D845077BAB557 /* Development Pods */, - BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */, - 6C92B5E2C39B71B9A3D59EB753CF598A /* Products */, - 5E6C37C04887F82A8C550F9B76E5B746 /* Targets Support Files */, - ); - sourceTree = ""; - }; - 7F3D670CFD2E3B9BFC42CB165C936B98 /* Pod */ = { - isa = PBXGroup; - children = ( - 1AFB7D35FB6048047A48B079FB616B3E /* LICENSE */, - DEDE7F6F743486EEE8CDF26C3F19CF0F /* PunkAPI.podspec */, - E874B75DA5C3ABAE4B0B94E8DB6C6045 /* README.md */, + 2B6E62A798BEE3FE5AE9D84C877FD756 /* Info.plist */, + CFBB1E2E92ABC5FA4F246BD9E188EBB3 /* PunkAPI.modulemap */, + 1AE9EEDB05092385E557ED3979AAEBC1 /* PunkAPI.xcconfig */, + ED357DDF7318810430C08E0AD4316358 /* PunkAPI-dummy.m */, + ED0E564BBBF9D91E8AA8F76C0E47F9C9 /* PunkAPI-prefix.pch */, + E7002BDD7866D71B1BE5B92068B1D65E /* PunkAPI-umbrella.h */, ); - name = Pod; + name = "Support Files"; + path = "Example/Pods/Target Support Files/PunkAPI"; sourceTree = ""; }; - 890261190D25DC439794AA100CC2F689 /* PunkAPI */ = { + 7DB346D0F39D3F0E887471402A8071AB = { isa = PBXGroup; children = ( - 9767CBF322197DCC00E684C4 /* Errors.swift */, - 9767CBE92219744000E684C4 /* Result.swift */, - 0AD5D712F315E66077D59EE9C31CF689 /* Configuration.swift */, - 5C8708EEF51A0078E3211F1AA5F78C06 /* PunkAPI.swift */, - 9767CBEE2219756C00E684C4 /* Content */, - 7F3D670CFD2E3B9BFC42CB165C936B98 /* Pod */, - 6719D069938A455DA268A952D46C9D57 /* Request */, - 4922267629DB1812F5525CC2246D2338 /* Support Files */, + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, + 3C48D264DEAC135E647F4628351B96D3 /* Development Pods */, + BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */, + 6C92B5E2C39B71B9A3D59EB753CF598A /* Products */, + 5E6C37C04887F82A8C550F9B76E5B746 /* Targets Support Files */, ); - name = PunkAPI; - path = ../..; sourceTree = ""; }; - 9767CBEE2219756C00E684C4 /* Content */ = { + 90DDE1C48D67E6010A82C6341C9BA92D /* Content */ = { isa = PBXGroup; children = ( - 9767CBEF221977D300E684C4 /* Beer.swift */, - 9767CBFB221FC9A700E684C4 /* Recipe.swift */, - 9767CBFD221FC9F900E684C4 /* Quantity.swift */, - 9767CC00221FCA2A00E684C4 /* Method.swift */, + 541ACAD8BAF53EB42A722470D92D1723 /* Beer.swift */, + 3FCD590B492E88AEC8C08B25E45BCFA7 /* Method.swift */, + 1A9D4151E2B98C6AEE60102C96A95D43 /* Quantity.swift */, + CE9253651B7E158F09FC4029478AD23A /* Recipe.swift */, ); name = Content; path = PunkAPI/Classes/Content; @@ -238,6 +210,21 @@ path = "Target Support Files/Pods-PunkAPI_Example"; sourceTree = ""; }; + B18B6D748213693EB25E110701CCA43E /* PunkAPI */ = { + isa = PBXGroup; + children = ( + 3DD1936865DE99565E7C6A3CA8A62046 /* Configuration.swift */, + 49FB5023B50B37DFC2215303164C7685 /* Errors.swift */, + A96C503FD3BF058AD217F43E4A5954BB /* PunkAPI.swift */, + 90DDE1C48D67E6010A82C6341C9BA92D /* Content */, + F3C407FDC658F8445BE7AB2FF5F32CB6 /* Pod */, + EE14703CB73E7B607CA53D2EC58437E4 /* Request */, + 6FCCF155F5EBF133E1D6AAA9C42FCD87 /* Support Files */, + ); + name = PunkAPI; + path = ../..; + sourceTree = ""; + }; B2D5CC793D96E6B1A0442EA2481F7DF2 /* Pods-PunkAPI_Tests */ = { isa = PBXGroup; children = ( @@ -256,20 +243,33 @@ path = "Target Support Files/Pods-PunkAPI_Tests"; sourceTree = ""; }; - B4EA824994F2844B351D845077BAB557 /* Development Pods */ = { + BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */ = { isa = PBXGroup; children = ( - 890261190D25DC439794AA100CC2F689 /* PunkAPI */, + 44D5347904CF754D6785B84253F2574A /* iOS */, ); - name = "Development Pods"; + name = Frameworks; sourceTree = ""; }; - BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */ = { + EE14703CB73E7B607CA53D2EC58437E4 /* Request */ = { isa = PBXGroup; children = ( - 44D5347904CF754D6785B84253F2574A /* iOS */, + 494668F6F12367A934530175780F1FB4 /* BeerRequest.swift */, + F184F71C3E715F7CB4001C228E19BEBB /* Request.swift */, + 1BAFF56967C81FF81A5FE0A0F4AC9EFC /* Result.swift */, ); - name = Frameworks; + name = Request; + path = PunkAPI/Classes/Request; + sourceTree = ""; + }; + F3C407FDC658F8445BE7AB2FF5F32CB6 /* Pod */ = { + isa = PBXGroup; + children = ( + 54767361581B8332A2D7629F5E98048E /* LICENSE */, + 864A4FE64365AC74BB9E53A4618E5F55 /* PunkAPI.podspec */, + 3F4208A029892D178EE8F5C95D6D79EB /* README.md */, + ); + name = Pod; sourceTree = ""; }; /* End PBXGroup section */ @@ -307,7 +307,7 @@ buildConfigurationList = C5CFB8D87EAAD43FF2A708011ADF9DF5 /* Build configuration list for PBXNativeTarget "PunkAPI" */; buildPhases = ( 6BAF60135FDFD6B381631C7BED9969B3 /* Headers */, - FE130DA14D328C73F836837F31FCCCEC /* Sources */, + 20F3A7AEDB67EAE35B24D16B388F9A4B /* Sources */, 64469F9A8CDA0C6CFDD8BA665E002A2F /* Frameworks */, 971F83F24AFBDD4CF88BD6ED289EEB1C /* Resources */, ); @@ -366,14 +366,6 @@ attributes = { LastSwiftUpdateCheck = 0930; LastUpgradeCheck = 0930; - TargetAttributes = { - 104A4972E6668483EF3BA6EE08D840AF = { - LastSwiftMigration = 1010; - }; - C1DB41E820BFF9D57C1A713EEC3A7C98 = { - LastSwiftMigration = 1010; - }; - }; }; buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; @@ -419,37 +411,37 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 7D76001470C4ECFAD45A4E50C07DF2B8 /* Sources */ = { + 20F3A7AEDB67EAE35B24D16B388F9A4B /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1DEF7BF616CC3F2EF46A7F9E5514F9AC /* Pods-PunkAPI_Tests-dummy.m in Sources */, + 5ABF50E02687C014E47088344889FC06 /* Beer.swift in Sources */, + 80B5BF4A54A873CBBDE11FD50E93473F /* BeerRequest.swift in Sources */, + D8CFB7B7D1AAC97CCB20D1DD5C56FB9B /* Configuration.swift in Sources */, + 3AF70E263893077BB94A1C3F36DCC044 /* Errors.swift in Sources */, + 8CA330EBFA4F61AE26881286B24648A7 /* Method.swift in Sources */, + A1658BA79EB16D586EE25257AD1D8ED6 /* PunkAPI-dummy.m in Sources */, + 90001FCA9653A9974B648EAF681F4DD4 /* PunkAPI.swift in Sources */, + C0BB3FEC5BB8EF2E7C42FD464D459623 /* Quantity.swift in Sources */, + 6017B5D2AAB067785D0E2EE754D97A17 /* Recipe.swift in Sources */, + 89899DFDA224AF6393CF9985FF2AE13E /* Request.swift in Sources */, + A3F6E06BFFDEF9DAD8325928091F4B00 /* Result.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - AEF952ACEC65192DB68BBAE0B794131A /* Sources */ = { + 7D76001470C4ECFAD45A4E50C07DF2B8 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - B0D852DC953C7A0E2C1CB872F9E315BB /* Pods-PunkAPI_Example-dummy.m in Sources */, + 1DEF7BF616CC3F2EF46A7F9E5514F9AC /* Pods-PunkAPI_Tests-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - FE130DA14D328C73F836837F31FCCCEC /* Sources */ = { + AEF952ACEC65192DB68BBAE0B794131A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - FB6E32A7831DCA2AE93BD8C3F87FA8E3 /* Configuration.swift in Sources */, - 9767CBEA2219744000E684C4 /* Result.swift in Sources */, - 3D7A5283D0833518F12109285F42CDD6 /* PunkAPI-dummy.m in Sources */, - 9767CBFE221FC9F900E684C4 /* Quantity.swift in Sources */, - 9767CBF22219795E00E684C4 /* BeerRequest.swift in Sources */, - DB20D4F60BC185671791B119F6F2629E /* PunkAPI.swift in Sources */, - 9767CBF0221977D300E684C4 /* Beer.swift in Sources */, - 9767CBF422197DCC00E684C4 /* Errors.swift in Sources */, - AD6B8F0860FB91889F808D08F168E096 /* Request.swift in Sources */, - 9767CBFF221FC9FE00E684C4 /* Recipe.swift in Sources */, - 9767CC01221FCA2A00E684C4 /* Method.swift in Sources */, + B0D852DC953C7A0E2C1CB872F9E315BB /* Pods-PunkAPI_Example-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -471,38 +463,6 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 0A32C10549B40B79BD750860BACF73EA /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1A11ED2EBFB85AEE905043364BD068DB /* PunkAPI.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/PunkAPI/PunkAPI-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/PunkAPI/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/PunkAPI/PunkAPI.modulemap"; - PRODUCT_MODULE_NAME = PunkAPI; - PRODUCT_NAME = PunkAPI; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 4.2; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; 403B3CA7AD0B06503DC7AB172EBAC118 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 6EDD1194CE9C142C26AD6C6803C306E4 /* Pods-PunkAPI_Tests.debug.xcconfig */; @@ -541,7 +501,6 @@ baseConfigurationReference = A5D146483FC9684CF2C15F85C081EF35 /* Pods-PunkAPI_Example.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -564,7 +523,6 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -693,15 +651,16 @@ MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; STRIP_INSTALLED_PRODUCT = NO; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 4.2; SYMROOT = "${SRCROOT}/../build"; }; name = Release; }; - 9289467C07440D2A81F24C3126E8A2CD /* Debug */ = { + 7CC3C9EDFC11B302ABDBAC490D072DF4 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 1A11ED2EBFB85AEE905043364BD068DB /* PunkAPI.xcconfig */; + baseConfigurationReference = 1AE9EEDB05092385E557ED3979AAEBC1 /* PunkAPI.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -730,6 +689,38 @@ }; name = Debug; }; + C4C31973A271F96E49F93F0B1190E36C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1AE9EEDB05092385E557ED3979AAEBC1 /* PunkAPI.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/PunkAPI/PunkAPI-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/PunkAPI/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/PunkAPI/PunkAPI.modulemap"; + PRODUCT_MODULE_NAME = PunkAPI; + PRODUCT_NAME = PunkAPI; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; CEA1F7ADD2A14B78BDC2402ECBA8804F /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 492C127C07A0D9D778B3D645FCDED6AC /* Pods-PunkAPI_Tests.release.xcconfig */; @@ -769,7 +760,6 @@ baseConfigurationReference = E816F7DA6C1CBE532E1590E0F05B9532 /* Pods-PunkAPI_Example.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -792,8 +782,6 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -833,8 +821,8 @@ C5CFB8D87EAAD43FF2A708011ADF9DF5 /* Build configuration list for PBXNativeTarget "PunkAPI" */ = { isa = XCConfigurationList; buildConfigurations = ( - 9289467C07440D2A81F24C3126E8A2CD /* Debug */, - 0A32C10549B40B79BD750860BACF73EA /* Release */, + 7CC3C9EDFC11B302ABDBAC490D072DF4 /* Debug */, + C4C31973A271F96E49F93F0B1190E36C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Example/Tests/BeerParsingTests.swift b/Example/Tests/BeerParsingTests.swift index 3a89eb5..780c947 100644 --- a/Example/Tests/BeerParsingTests.swift +++ b/Example/Tests/BeerParsingTests.swift @@ -7,7 +7,7 @@ // import XCTest -import PunkAPI +@testable import PunkAPI class BeerParsingTests: XCTestCase { @@ -25,27 +25,22 @@ class BeerParsingTests: XCTestCase { } func testFirst() { - self.decodeBeers(BeerStub.first) } func testSecond() { - self.decodeBeers(BeerStub.second) } func testThird() { - self.decodeBeers(BeerStub.third) } func testFourth() { - self.decodeBeers(BeerStub.fourth) } func testFifth() { - self.decodeBeers(BeerStub.fifth) } From 90dfc40d98e77019a83207a35f0eb3618eaddef3 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sat, 23 Feb 2019 12:43:10 +0100 Subject: [PATCH 16/37] feat: update podspec and try fix the coverage problem --- .../Pods/Local Podspecs/PunkAPI.podspec.json | 13 ++++++------ Example/Pods/Pods.xcodeproj/project.pbxproj | 17 +++++++-------- Example/PunkAPI.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/WorkspaceSettings.xcsettings | 5 +++++ Example/fastlane/Fastfile | 2 +- Example/fastlane/report.xml | 8 +++---- PunkAPI.podspec | 21 +++++++------------ 7 files changed, 33 insertions(+), 35 deletions(-) create mode 100644 Example/PunkAPI.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/Example/Pods/Local Podspecs/PunkAPI.podspec.json b/Example/Pods/Local Podspecs/PunkAPI.podspec.json index 7597051..73a02ef 100644 --- a/Example/Pods/Local Podspecs/PunkAPI.podspec.json +++ b/Example/Pods/Local Podspecs/PunkAPI.podspec.json @@ -1,22 +1,23 @@ { "name": "PunkAPI", "version": "0.1.0", - "summary": "A short description of PunkAPI.", - "description": "TODO: Add long description of the pod here.", - "homepage": "https://github.com/acct=/PunkAPI", + "summary": "A little swift wrapper for PunkAPI by @samjbmason", + "description": "\"Have you ever wanted to search through Brewdog's expansive back catalogue of beer in a programmatic way? Maybe build a tool that pairs beer with food, or search beers with an abv of more than 4%? Well now your prayers have been answered!\"", + "homepage": "https://github.com/Oni-zerone/PunkAPI", "license": { "type": "MIT", "file": "LICENSE" }, "authors": { - "acct=": "oni.zerone@gmail.com" + "Andrea Altea": "oni.zerone@gmail.com" }, "source": { - "git": "https://github.com/acct=/PunkAPI.git", + "git": "https://github.com/Oni-zerone/PunkAPI.git", "tag": "0.1.0" }, + "social_media_url": "https://twitter.com/Oni_zerone", "platforms": { - "ios": "8.0" + "ios": "10.0" }, "source_files": "PunkAPI/Classes/**/*" } diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 7967b7e..7e38ada 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -54,26 +54,26 @@ 2B6E62A798BEE3FE5AE9D84C877FD756 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 2EC29BADC6D4B129C97F077B8D1AAD24 /* Pods-PunkAPI_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Example-frameworks.sh"; sourceTree = ""; }; 34E9F6D3BEDEF11CDF5DC7C24AEF5989 /* Pods-PunkAPI_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Tests-dummy.m"; sourceTree = ""; }; - 3CA7DD0E0D9E3D052F0DA83C7B3B79FC /* Pods_PunkAPI_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PunkAPI_Tests.framework; path = "Pods-PunkAPI_Tests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3CA7DD0E0D9E3D052F0DA83C7B3B79FC /* Pods_PunkAPI_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3DD1936865DE99565E7C6A3CA8A62046 /* Configuration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Configuration.swift; path = PunkAPI/Classes/Configuration.swift; sourceTree = ""; }; - 3F4208A029892D178EE8F5C95D6D79EB /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; + 3F4208A029892D178EE8F5C95D6D79EB /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 3FCD590B492E88AEC8C08B25E45BCFA7 /* Method.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Method.swift; sourceTree = ""; }; 492C127C07A0D9D778B3D645FCDED6AC /* Pods-PunkAPI_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Tests.release.xcconfig"; sourceTree = ""; }; 494668F6F12367A934530175780F1FB4 /* BeerRequest.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BeerRequest.swift; sourceTree = ""; }; 49FB5023B50B37DFC2215303164C7685 /* Errors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Errors.swift; path = PunkAPI/Classes/Errors.swift; sourceTree = ""; }; 541ACAD8BAF53EB42A722470D92D1723 /* Beer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Beer.swift; sourceTree = ""; }; - 54767361581B8332A2D7629F5E98048E /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; + 54767361581B8332A2D7629F5E98048E /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 608E9332AF8468043B49B03317025805 /* Pods-PunkAPI_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Tests-frameworks.sh"; sourceTree = ""; }; 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PunkAPI_Example-umbrella.h"; sourceTree = ""; }; 6EDD1194CE9C142C26AD6C6803C306E4 /* Pods-PunkAPI_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Tests.debug.xcconfig"; sourceTree = ""; }; 7F7764549D1799C2D5D6A7B2D65E3550 /* Pods-PunkAPI_Example-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Example-resources.sh"; sourceTree = ""; }; 8342B62283B06E1CA90A14E1BCB6D62B /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 8458C84A594F726E1A8DB6294F78DB73 /* Pods-PunkAPI_Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Tests-resources.sh"; sourceTree = ""; }; - 864A4FE64365AC74BB9E53A4618E5F55 /* PunkAPI.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; path = PunkAPI.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 864A4FE64365AC74BB9E53A4618E5F55 /* PunkAPI.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; path = PunkAPI.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 92229C81AD3A318707A49C8449AEB2F5 /* Pods-PunkAPI_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PunkAPI_Example-acknowledgements.plist"; sourceTree = ""; }; - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 9D14926C4AE138B3C55CE27E18BE194D /* Pods-PunkAPI_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Tests.modulemap"; sourceTree = ""; }; - 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PunkAPI_Example.framework; path = "Pods-PunkAPI_Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Example-dummy.m"; sourceTree = ""; }; A5D146483FC9684CF2C15F85C081EF35 /* Pods-PunkAPI_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Example.release.xcconfig"; sourceTree = ""; }; A96C503FD3BF058AD217F43E4A5954BB /* PunkAPI.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PunkAPI.swift; path = PunkAPI/Classes/PunkAPI.swift; sourceTree = ""; }; @@ -88,7 +88,7 @@ ED0E564BBBF9D91E8AA8F76C0E47F9C9 /* PunkAPI-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PunkAPI-prefix.pch"; sourceTree = ""; }; ED357DDF7318810430C08E0AD4316358 /* PunkAPI-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PunkAPI-dummy.m"; sourceTree = ""; }; F184F71C3E715F7CB4001C228E19BEBB /* Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = ""; }; - FA66D5ED6E33AA7DD32A8C962841F3B0 /* PunkAPI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = PunkAPI.framework; path = PunkAPI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FA66D5ED6E33AA7DD32A8C962841F3B0 /* PunkAPI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PunkAPI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; FB1D3C212D7A0519F22CF554E249675E /* Pods-PunkAPI_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PunkAPI_Example-acknowledgements.markdown"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -651,8 +651,7 @@ MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; STRIP_INSTALLED_PRODUCT = NO; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 4.2; SYMROOT = "${SRCROOT}/../build"; }; diff --git a/Example/PunkAPI.xcodeproj/project.pbxproj b/Example/PunkAPI.xcodeproj/project.pbxproj index df22b5f..67c7927 100644 --- a/Example/PunkAPI.xcodeproj/project.pbxproj +++ b/Example/PunkAPI.xcodeproj/project.pbxproj @@ -30,7 +30,7 @@ /* Begin PBXFileReference section */ 00C6BA9ADC6CC9CF141BE6E8 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CA29904BB7426E73CC31E50 /* PunkAPI.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = PunkAPI.podspec; path = ../PunkAPI.podspec; sourceTree = ""; }; + 0CA29904BB7426E73CC31E50 /* PunkAPI.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = PunkAPI.podspec; path = ../PunkAPI.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 19516DEBCED4A6F0ADCEC345 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 46341D8F014E1940E53D4F02 /* Pods_PunkAPI_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACD01AFB9204008FA782 /* PunkAPI_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PunkAPI_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; diff --git a/Example/PunkAPI.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Example/PunkAPI.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..0c67376 --- /dev/null +++ b/Example/PunkAPI.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,5 @@ + + + + + diff --git a/Example/fastlane/Fastfile b/Example/fastlane/Fastfile index 2d6970f..368968b 100644 --- a/Example/fastlane/Fastfile +++ b/Example/fastlane/Fastfile @@ -54,7 +54,7 @@ platform :ios do proj: "PunkAPI.xcodeproj", scheme: "PunkAPI-Example", binary_basename: "PunkAPI", - source_directory: "../PunkAPI", + source_directory: "../PunkAPI/*", simple_output: true, coveralls: true ) diff --git a/Example/fastlane/report.xml b/Example/fastlane/report.xml index 4edc239..cbcccbe 100644 --- a/Example/fastlane/report.xml +++ b/Example/fastlane/report.xml @@ -5,19 +5,19 @@ - + - + - + - + diff --git a/PunkAPI.podspec b/PunkAPI.podspec index a698767..3025aa7 100644 --- a/PunkAPI.podspec +++ b/PunkAPI.podspec @@ -9,26 +9,19 @@ Pod::Spec.new do |s| s.name = 'PunkAPI' s.version = '0.1.0' - s.summary = 'A short description of PunkAPI.' - -# This description is used to generate tags and improve search results. -# * Think: What does it do? Why did you write it? What is the focus? -# * Try to keep it short, snappy and to the point. -# * Write the description between the DESC delimiters below. -# * Finally, don't worry about the indent, CocoaPods strips it! + s.summary = 'A little swift wrapper for PunkAPI by @samjbmason' s.description = <<-DESC -TODO: Add long description of the pod here. + "Have you ever wanted to search through Brewdog's expansive back catalogue of beer in a programmatic way? Maybe build a tool that pairs beer with food, or search beers with an abv of more than 4%? Well now your prayers have been answered!" DESC - s.homepage = 'https://github.com/acct=/PunkAPI' - # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' + s.homepage = 'https://github.com/Oni-zerone/PunkAPI' s.license = { :type => 'MIT', :file => 'LICENSE' } - s.author = { 'acct=' => 'oni.zerone@gmail.com' } - s.source = { :git => 'https://github.com/acct=/PunkAPI.git', :tag => s.version.to_s } - # s.social_media_url = 'https://twitter.com/' + s.author = { 'Andrea Altea' => 'oni.zerone@gmail.com' } + s.source = { :git => 'https://github.com/Oni-zerone/PunkAPI.git', :tag => s.version.to_s } + s.social_media_url = 'https://twitter.com/Oni_zerone' - s.ios.deployment_target = '8.0' + s.ios.deployment_target = '10.0' s.source_files = 'PunkAPI/Classes/**/*' From df27f710be14737ac9c231826d86e9aca15f91f7 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sat, 23 Feb 2019 13:12:41 +0100 Subject: [PATCH 17/37] Feat: prepare example app --- Example/PunkAPI/Base.lproj/Main.storyboard | 31 ++++++++++++++-- Example/PunkAPI/ViewController.swift | 22 ++++++++++-- PunkAPI/Classes/Content/Beer.swift | 42 +++++++++++----------- PunkAPI/Classes/Content/Method.swift | 12 +++---- PunkAPI/Classes/Content/Quantity.swift | 4 +-- PunkAPI/Classes/Content/Recipe.swift | 10 +++--- PunkAPI/Classes/Request/BeerRequest.swift | 3 +- PunkAPI/Classes/Request/Request.swift | 1 - 8 files changed, 83 insertions(+), 42 deletions(-) diff --git a/Example/PunkAPI/Base.lproj/Main.storyboard b/Example/PunkAPI/Base.lproj/Main.storyboard index 5cd6b8d..39512a4 100644 --- a/Example/PunkAPI/Base.lproj/Main.storyboard +++ b/Example/PunkAPI/Base.lproj/Main.storyboard @@ -1,11 +1,11 @@ - + - + @@ -20,11 +20,38 @@ + + + + + + + + + + + + + + + + diff --git a/Example/PunkAPI/ViewController.swift b/Example/PunkAPI/ViewController.swift index e4ebd95..33896fa 100644 --- a/Example/PunkAPI/ViewController.swift +++ b/Example/PunkAPI/ViewController.swift @@ -11,11 +11,27 @@ import PunkAPI class ViewController: UIViewController { + @IBOutlet weak var label: UILabel! + override func viewDidLoad() { super.viewDidLoad() -// PunkAPI().get(BeerRequest(id: 6), completion: { beers in -// print(beers) -// }) + } + + + @IBAction func loadBeerAction(_ sender: Any) { + + PunkAPI().get(BeerRequest(id: 6), queue: .main) { [weak self] beersResult in + + guard let strongSelf = self else { return } + switch beersResult { + + case .success(let beers): + strongSelf.label.text = beers.first?.name ?? "Not Found" + + case .failure(let error): + strongSelf.label.text = error.localizedDescription + } + } } } diff --git a/PunkAPI/Classes/Content/Beer.swift b/PunkAPI/Classes/Content/Beer.swift index 6b646d1..ff47cbc 100644 --- a/PunkAPI/Classes/Content/Beer.swift +++ b/PunkAPI/Classes/Content/Beer.swift @@ -9,29 +9,29 @@ import Foundation public struct Beer: Codable { - var id: Int - var name: String? - var tagline: String? - var firstBrewed: String? - var description: String? - var imageUrl: String? + public var id: Int + public var name: String? + public var tagline: String? + public var firstBrewed: String? + public var description: String? + public var imageUrl: String? - var abv: Float? - var ibu: Float? + public var abv: Float? + public var ibu: Float? - var targetFg: Float? - var targetOg: Float? + public var targetFg: Float? + public var targetOg: Float? - var ebc: Float? - var srm: Float? - var ph: Float? + public var ebc: Float? + public var srm: Float? + public var ph: Float? - var attenuationLevel: Float? - var volume: Volume? - var boilVolume: Volume? - var method: Method? - var ingredients: Recipe? - var foodPairing: [String] - var brewersTips: String? - var contributedBy: String? + public var attenuationLevel: Float? + public var volume: Volume? + public var boilVolume: Volume? + public var method: Method? + public var ingredients: Recipe? + public var foodPairing: [String] + public var brewersTips: String? + public var contributedBy: String? } diff --git a/PunkAPI/Classes/Content/Method.swift b/PunkAPI/Classes/Content/Method.swift index bcee6d9..115e75c 100644 --- a/PunkAPI/Classes/Content/Method.swift +++ b/PunkAPI/Classes/Content/Method.swift @@ -9,12 +9,12 @@ import Foundation public struct Method: Codable { - struct Step: Codable { - var temp: Temperature? - var duration: Float? + public struct Step: Codable { + public var temp: Temperature? + public var duration: Float? } - var mashTemp: [Step]? - var fermentation: Temperature? - var twist: String? + public var mashTemp: [Step]? + public var fermentation: Temperature? + public var twist: String? } diff --git a/PunkAPI/Classes/Content/Quantity.swift b/PunkAPI/Classes/Content/Quantity.swift index 7cce0e3..7aeaefc 100644 --- a/PunkAPI/Classes/Content/Quantity.swift +++ b/PunkAPI/Classes/Content/Quantity.swift @@ -8,8 +8,8 @@ import Foundation public struct Quantity: Codable { - var value: Float? - var unit: String? + public var value: Float? + public var unit: String? } public typealias Temperature = Quantity diff --git a/PunkAPI/Classes/Content/Recipe.swift b/PunkAPI/Classes/Content/Recipe.swift index 7110736..1b525fc 100644 --- a/PunkAPI/Classes/Content/Recipe.swift +++ b/PunkAPI/Classes/Content/Recipe.swift @@ -10,11 +10,11 @@ import Foundation public struct Recipe: Codable { public struct Ingredient: Codable { - var name: String? - var amount: Mass? + public var name: String? + public var amount: Mass? } - var malt: [Ingredient] - var hops: [Ingredient] - var yeast: String? + public var malt: [Ingredient] + public var hops: [Ingredient] + public var yeast: String? } diff --git a/PunkAPI/Classes/Request/BeerRequest.swift b/PunkAPI/Classes/Request/BeerRequest.swift index 914ac4b..2cad065 100644 --- a/PunkAPI/Classes/Request/BeerRequest.swift +++ b/PunkAPI/Classes/Request/BeerRequest.swift @@ -9,14 +9,13 @@ import Foundation public struct BeerRequest: Request { - var id: Int + public var id: Int public var path: String { return "beers/\(self.id)" } public init(id: Int) { - self.id = id } } diff --git a/PunkAPI/Classes/Request/Request.swift b/PunkAPI/Classes/Request/Request.swift index b29ea0c..960b91a 100644 --- a/PunkAPI/Classes/Request/Request.swift +++ b/PunkAPI/Classes/Request/Request.swift @@ -10,5 +10,4 @@ import Foundation public protocol Request { var path: String { get } - } From 869744767f2abf18522143294b14f95d0f59b64b Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sun, 24 Feb 2019 12:43:05 +0100 Subject: [PATCH 18/37] Feat: reorganize Request parsing --- Example/Pods/Pods.xcodeproj/project.pbxproj | 22 +++++-- Example/PunkAPI.xcodeproj/project.pbxproj | 12 ++++ Example/Tests/URLBuildTests.swift | 57 +++++++++++++++++++ PunkAPI/Classes/Configuration.swift | 12 +++- PunkAPI/Classes/PunkAPI.swift | 12 +--- PunkAPI/Classes/Request/Request.swift | 9 +++ PunkAPI/Classes/Request/URLBuilder.swift | 19 +++++++ {PunkAPI/Classes => Results}/Errors.swift | 3 +- .../Classes/Request => Results}/Result.swift | 0 9 files changed, 128 insertions(+), 18 deletions(-) create mode 100644 Example/Tests/URLBuildTests.swift create mode 100644 PunkAPI/Classes/Request/URLBuilder.swift rename {PunkAPI/Classes => Results}/Errors.swift (80%) rename {PunkAPI/Classes/Request => Results}/Result.swift (100%) diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 7e38ada..0d93688 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -20,6 +20,7 @@ 8CA330EBFA4F61AE26881286B24648A7 /* Method.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FCD590B492E88AEC8C08B25E45BCFA7 /* Method.swift */; }; 90001FCA9653A9974B648EAF681F4DD4 /* PunkAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = A96C503FD3BF058AD217F43E4A5954BB /* PunkAPI.swift */; }; 94ACB62152B83DE972430EAA4B24D449 /* PunkAPI-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E7002BDD7866D71B1BE5B92068B1D65E /* PunkAPI-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9767CC062222B1BB00E684C4 /* URLBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC052222B1BB00E684C4 /* URLBuilder.swift */; }; 9DEE51DC320AFD89F8CCE79E659D0E92 /* Pods-PunkAPI_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; A1658BA79EB16D586EE25257AD1D8ED6 /* PunkAPI-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = ED357DDF7318810430C08E0AD4316358 /* PunkAPI-dummy.m */; }; A3F6E06BFFDEF9DAD8325928091F4B00 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BAFF56967C81FF81A5FE0A0F4AC9EFC /* Result.swift */; }; @@ -60,7 +61,7 @@ 3FCD590B492E88AEC8C08B25E45BCFA7 /* Method.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Method.swift; sourceTree = ""; }; 492C127C07A0D9D778B3D645FCDED6AC /* Pods-PunkAPI_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Tests.release.xcconfig"; sourceTree = ""; }; 494668F6F12367A934530175780F1FB4 /* BeerRequest.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BeerRequest.swift; sourceTree = ""; }; - 49FB5023B50B37DFC2215303164C7685 /* Errors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Errors.swift; path = PunkAPI/Classes/Errors.swift; sourceTree = ""; }; + 49FB5023B50B37DFC2215303164C7685 /* Errors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; }; 541ACAD8BAF53EB42A722470D92D1723 /* Beer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Beer.swift; sourceTree = ""; }; 54767361581B8332A2D7629F5E98048E /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 608E9332AF8468043B49B03317025805 /* Pods-PunkAPI_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Tests-frameworks.sh"; sourceTree = ""; }; @@ -72,6 +73,7 @@ 864A4FE64365AC74BB9E53A4618E5F55 /* PunkAPI.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; path = PunkAPI.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 92229C81AD3A318707A49C8449AEB2F5 /* Pods-PunkAPI_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PunkAPI_Example-acknowledgements.plist"; sourceTree = ""; }; 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9767CC052222B1BB00E684C4 /* URLBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBuilder.swift; sourceTree = ""; }; 9D14926C4AE138B3C55CE27E18BE194D /* Pods-PunkAPI_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Tests.modulemap"; sourceTree = ""; }; 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Example-dummy.m"; sourceTree = ""; }; @@ -192,6 +194,15 @@ path = PunkAPI/Classes/Content; sourceTree = ""; }; + 9767CC042222B13000E684C4 /* Results */ = { + isa = PBXGroup; + children = ( + 49FB5023B50B37DFC2215303164C7685 /* Errors.swift */, + 1BAFF56967C81FF81A5FE0A0F4AC9EFC /* Result.swift */, + ); + path = Results; + sourceTree = ""; + }; 9BFECB8663CD309F9214B4311C96BCB5 /* Pods-PunkAPI_Example */ = { isa = PBXGroup; children = ( @@ -214,11 +225,11 @@ isa = PBXGroup; children = ( 3DD1936865DE99565E7C6A3CA8A62046 /* Configuration.swift */, - 49FB5023B50B37DFC2215303164C7685 /* Errors.swift */, A96C503FD3BF058AD217F43E4A5954BB /* PunkAPI.swift */, + EE14703CB73E7B607CA53D2EC58437E4 /* Request */, 90DDE1C48D67E6010A82C6341C9BA92D /* Content */, + 9767CC042222B13000E684C4 /* Results */, F3C407FDC658F8445BE7AB2FF5F32CB6 /* Pod */, - EE14703CB73E7B607CA53D2EC58437E4 /* Request */, 6FCCF155F5EBF133E1D6AAA9C42FCD87 /* Support Files */, ); name = PunkAPI; @@ -254,9 +265,9 @@ EE14703CB73E7B607CA53D2EC58437E4 /* Request */ = { isa = PBXGroup; children = ( - 494668F6F12367A934530175780F1FB4 /* BeerRequest.swift */, F184F71C3E715F7CB4001C228E19BEBB /* Request.swift */, - 1BAFF56967C81FF81A5FE0A0F4AC9EFC /* Result.swift */, + 494668F6F12367A934530175780F1FB4 /* BeerRequest.swift */, + 9767CC052222B1BB00E684C4 /* URLBuilder.swift */, ); name = Request; path = PunkAPI/Classes/Request; @@ -420,6 +431,7 @@ D8CFB7B7D1AAC97CCB20D1DD5C56FB9B /* Configuration.swift in Sources */, 3AF70E263893077BB94A1C3F36DCC044 /* Errors.swift in Sources */, 8CA330EBFA4F61AE26881286B24648A7 /* Method.swift in Sources */, + 9767CC062222B1BB00E684C4 /* URLBuilder.swift in Sources */, A1658BA79EB16D586EE25257AD1D8ED6 /* PunkAPI-dummy.m in Sources */, 90001FCA9653A9974B648EAF681F4DD4 /* PunkAPI.swift in Sources */, C0BB3FEC5BB8EF2E7C42FD464D459623 /* Quantity.swift in Sources */, diff --git a/Example/PunkAPI.xcodeproj/project.pbxproj b/Example/PunkAPI.xcodeproj/project.pbxproj index 67c7927..7201ea8 100644 --- a/Example/PunkAPI.xcodeproj/project.pbxproj +++ b/Example/PunkAPI.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; 9767CBF7221993F900E684C4 /* BeerParsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF6221993F800E684C4 /* BeerParsingTests.swift */; }; 9767CBFA2219958F00E684C4 /* BeerStubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF82219958800E684C4 /* BeerStubs.swift */; }; + 9767CC092222B63700E684C4 /* URLBuildTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC072222B60F00E684C4 /* URLBuildTests.swift */; }; EBB1B4D6901624C6A90359CA /* Pods_PunkAPI_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46341D8F014E1940E53D4F02 /* Pods_PunkAPI_Tests.framework */; }; /* End PBXBuildFile section */ @@ -45,6 +46,7 @@ 613B14F018C28CF1557EC3D5 /* Pods-PunkAPI_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.debug.xcconfig"; sourceTree = ""; }; 9767CBF6221993F800E684C4 /* BeerParsingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerParsingTests.swift; sourceTree = ""; }; 9767CBF82219958800E684C4 /* BeerStubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerStubs.swift; sourceTree = ""; }; + 9767CC072222B60F00E684C4 /* URLBuildTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBuildTests.swift; sourceTree = ""; }; 9A440A355337DF96D159D208 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; A4CA42C1E1AE14F816574722 /* Pods-PunkAPI_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.debug.xcconfig"; sourceTree = ""; }; E294694CD6DD5DA5A6B471F1 /* Pods-PunkAPI_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.release.xcconfig"; sourceTree = ""; }; @@ -126,6 +128,7 @@ 607FACE81AFB9204008FA782 /* Tests */ = { isa = PBXGroup; children = ( + 9767CC032222B0C900E684C4 /* Request */, 9767CBF5221993DA00E684C4 /* BeerParsing */, 607FACE91AFB9204008FA782 /* Supporting Files */, ); @@ -170,6 +173,14 @@ name = BeerParsing; sourceTree = ""; }; + 9767CC032222B0C900E684C4 /* Request */ = { + isa = PBXGroup; + children = ( + 9767CC072222B60F00E684C4 /* URLBuildTests.swift */, + ); + name = Request; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -375,6 +386,7 @@ files = ( 9767CBF7221993F900E684C4 /* BeerParsingTests.swift in Sources */, 9767CBFA2219958F00E684C4 /* BeerStubs.swift in Sources */, + 9767CC092222B63700E684C4 /* URLBuildTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example/Tests/URLBuildTests.swift b/Example/Tests/URLBuildTests.swift new file mode 100644 index 0000000..850073d --- /dev/null +++ b/Example/Tests/URLBuildTests.swift @@ -0,0 +1,57 @@ +// +// URLBuildTests.swift +// PunkAPI_Example +// +// Created by Andrea Altea on 24/02/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import XCTest +@testable import PunkAPI + +class URLBuildTests: XCTestCase { + + var baseURL: URL! + + override func setUp() { + super.setUp() + + self.baseURL = URL(string: "https://api.test.it/v2") + } + + func testBaseURLBuilding() { + + let request = MockRequest(path: "beer/1", parameters: nil) + let url = self.baseURL.url(request: request) + XCTAssert(url?.absoluteString == "https://api.test.it/v2/beer/1") + } + + func testWrongRelativePathURLBuilding() { + + let request = MockRequest(path: "/beer/1", parameters: nil) + let url = self.baseURL.url(request: request) + XCTAssert(url?.absoluteString == "https://api.test.it/v2/beer/1") + } + + func testParametersURLBuilding() { + + let request = MockRequest(path: "/beer", + parameters: ["integer": 1, "string": "text", "object": NSNumber(value: 3)]) + guard let url = self.baseURL.url(request: request) else { + return XCTFail("undefined url") + } + guard let queryItems = URLComponents(url: url, resolvingAgainstBaseURL: true)?.queryItems else { + return XCTFail("undefined query") + } + XCTAssert(queryItems.count == 3) + XCTAssert(queryItems.contains(URLQueryItem(name: "integer", value: "1"))) + XCTAssert(queryItems.contains(URLQueryItem(name: "string", value: "text"))) + XCTAssert(queryItems.contains(URLQueryItem(name: "object", value: "3"))) + } +} + +struct MockRequest: Request { + + var path: String + var parameters: [String : Any]? = nil +} diff --git a/PunkAPI/Classes/Configuration.swift b/PunkAPI/Classes/Configuration.swift index 468f7c9..e0ef4a9 100644 --- a/PunkAPI/Classes/Configuration.swift +++ b/PunkAPI/Classes/Configuration.swift @@ -11,11 +11,17 @@ public struct Configuration { var session: URLSession - var baseComponent: URLComponents + var baseURL: URL - init(sessionConfiguration: URLSessionConfiguration) { + public init(sessionConfiguration: URLSessionConfiguration, baseURL: URL) { self.session = URLSession(configuration: sessionConfiguration) - self.baseComponent = URLComponents(string: "https://api.punkapi.com/v2/")! + self.baseURL = baseURL } } + +public extension Configuration { + + public static let `default` = Configuration(sessionConfiguration: .default, + baseURL: URL(string: "https://api.punkapi.com/v2/")!) +} diff --git a/PunkAPI/Classes/PunkAPI.swift b/PunkAPI/Classes/PunkAPI.swift index fff79e4..f3b00c1 100644 --- a/PunkAPI/Classes/PunkAPI.swift +++ b/PunkAPI/Classes/PunkAPI.swift @@ -11,20 +11,14 @@ public class PunkAPI { var configuration: Configuration - public init(sessionConfiguration: URLSessionConfiguration) { + public init(configuration: Configuration = .default) { - self.configuration = Configuration(sessionConfiguration: sessionConfiguration) - } - - public convenience init() { - self.init(sessionConfiguration: .default) + self.configuration = configuration } public func get(_ request: Request, queue: DispatchQueue = .global(qos: .background), completion: @escaping (Result<[Beer]>) -> Void) { - var urlComponent = self.configuration.baseComponent - urlComponent.path += request.path - guard let url = urlComponent.url else { + guard let url = configuration.baseURL.url(request: request) else { queue.async { completion(.failure(APIError.invalidURL)) } return } diff --git a/PunkAPI/Classes/Request/Request.swift b/PunkAPI/Classes/Request/Request.swift index 960b91a..fca3280 100644 --- a/PunkAPI/Classes/Request/Request.swift +++ b/PunkAPI/Classes/Request/Request.swift @@ -10,4 +10,13 @@ import Foundation public protocol Request { var path: String { get } + + var parameters: [String: Any]? { get } +} + +public extension Request { + + var parameters: [String: Any]? { + return nil + } } diff --git a/PunkAPI/Classes/Request/URLBuilder.swift b/PunkAPI/Classes/Request/URLBuilder.swift new file mode 100644 index 0000000..1722a90 --- /dev/null +++ b/PunkAPI/Classes/Request/URLBuilder.swift @@ -0,0 +1,19 @@ +// +// URLBuilder.swift +// PunkAPI +// +// Created by Andrea Altea on 24/02/2019. +// + +import Foundation + +extension URL { + + func url(request: Request) -> URL? { + + let url = self.appendingPathComponent(request.path) + guard var components = URLComponents(url: url, resolvingAgainstBaseURL: true) else { return nil } + components.queryItems = request.parameters?.map { URLQueryItem(name: $0, value: "\($1)") } + return components.url + } +} diff --git a/PunkAPI/Classes/Errors.swift b/Results/Errors.swift similarity index 80% rename from PunkAPI/Classes/Errors.swift rename to Results/Errors.swift index 9af4562..3e69681 100644 --- a/PunkAPI/Classes/Errors.swift +++ b/Results/Errors.swift @@ -7,7 +7,8 @@ import Foundation -enum APIError: Error { +public enum APIError: Error { + case invalidURL case emptyResponse } diff --git a/PunkAPI/Classes/Request/Result.swift b/Results/Result.swift similarity index 100% rename from PunkAPI/Classes/Request/Result.swift rename to Results/Result.swift From 7a16e8d0e3d9f4415992983afadb29d847699454 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sun, 24 Feb 2019 13:02:00 +0100 Subject: [PATCH 19/37] Feat: add BeerRequest tests --- Example/PunkAPI.xcodeproj/project.pbxproj | 8 +++ Example/Tests/BeerRequestTests.swift | 35 ++++++++++++ Example/Tests/MockSession.swift | 65 +++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 Example/Tests/BeerRequestTests.swift create mode 100644 Example/Tests/MockSession.swift diff --git a/Example/PunkAPI.xcodeproj/project.pbxproj b/Example/PunkAPI.xcodeproj/project.pbxproj index 7201ea8..95bd6bd 100644 --- a/Example/PunkAPI.xcodeproj/project.pbxproj +++ b/Example/PunkAPI.xcodeproj/project.pbxproj @@ -16,6 +16,8 @@ 9767CBF7221993F900E684C4 /* BeerParsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF6221993F800E684C4 /* BeerParsingTests.swift */; }; 9767CBFA2219958F00E684C4 /* BeerStubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF82219958800E684C4 /* BeerStubs.swift */; }; 9767CC092222B63700E684C4 /* URLBuildTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC072222B60F00E684C4 /* URLBuildTests.swift */; }; + 9767CC0B2222BB1E00E684C4 /* MockSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC0A2222BB1E00E684C4 /* MockSession.swift */; }; + 9767CC0D2222BDD000E684C4 /* BeerRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC0C2222BDD000E684C4 /* BeerRequestTests.swift */; }; EBB1B4D6901624C6A90359CA /* Pods_PunkAPI_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46341D8F014E1940E53D4F02 /* Pods_PunkAPI_Tests.framework */; }; /* End PBXBuildFile section */ @@ -47,6 +49,8 @@ 9767CBF6221993F800E684C4 /* BeerParsingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerParsingTests.swift; sourceTree = ""; }; 9767CBF82219958800E684C4 /* BeerStubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerStubs.swift; sourceTree = ""; }; 9767CC072222B60F00E684C4 /* URLBuildTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBuildTests.swift; sourceTree = ""; }; + 9767CC0A2222BB1E00E684C4 /* MockSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSession.swift; sourceTree = ""; }; + 9767CC0C2222BDD000E684C4 /* BeerRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerRequestTests.swift; sourceTree = ""; }; 9A440A355337DF96D159D208 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; A4CA42C1E1AE14F816574722 /* Pods-PunkAPI_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.debug.xcconfig"; sourceTree = ""; }; E294694CD6DD5DA5A6B471F1 /* Pods-PunkAPI_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.release.xcconfig"; sourceTree = ""; }; @@ -177,6 +181,8 @@ isa = PBXGroup; children = ( 9767CC072222B60F00E684C4 /* URLBuildTests.swift */, + 9767CC0C2222BDD000E684C4 /* BeerRequestTests.swift */, + 9767CC0A2222BB1E00E684C4 /* MockSession.swift */, ); name = Request; sourceTree = ""; @@ -384,8 +390,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9767CC0D2222BDD000E684C4 /* BeerRequestTests.swift in Sources */, 9767CBF7221993F900E684C4 /* BeerParsingTests.swift in Sources */, 9767CBFA2219958F00E684C4 /* BeerStubs.swift in Sources */, + 9767CC0B2222BB1E00E684C4 /* MockSession.swift in Sources */, 9767CC092222B63700E684C4 /* URLBuildTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Example/Tests/BeerRequestTests.swift b/Example/Tests/BeerRequestTests.swift new file mode 100644 index 0000000..ebad6bd --- /dev/null +++ b/Example/Tests/BeerRequestTests.swift @@ -0,0 +1,35 @@ +// +// BeerRequestTests.swift +// PunkAPI_Tests +// +// Created by Andrea Altea on 24/02/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import Foundation + +import XCTest +@testable import PunkAPI + +class BeerRequestTest: XCTestCase { + + func testBeerRequests() { + + self.testBeerRequest(with: 1) + self.testBeerRequest(with: 2) + self.testBeerRequest(with: 3) + self.testBeerRequest(with: 4) + self.testBeerRequest(with: 5) + self.testBeerRequest(with: 6) + self.testBeerRequest(with: 10) + self.testBeerRequest(with: 1000) + self.testBeerRequest(with: 165) + } + + func testBeerRequest(with id: Int) { + + let request = BeerRequest(id: id) + XCTAssert(request.path == "beers/\(id)") + XCTAssert(request.parameters == nil) + } +} diff --git a/Example/Tests/MockSession.swift b/Example/Tests/MockSession.swift new file mode 100644 index 0000000..f87b155 --- /dev/null +++ b/Example/Tests/MockSession.swift @@ -0,0 +1,65 @@ +// +// MockSession.swift +// PunkAPI_Tests +// +// Created by Andrea Altea on 24/02/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import Foundation + +class MockURLSession: URLSession { + + var urlCheckBlock: ((_ url: URL) -> Void)? + + var responseConfig: (data: Data?, response: HTTPURLResponse?, error: Error?)? + + override func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask { + + if let urlCheckBlock = self.urlCheckBlock { + urlCheckBlock(url) + } + + return MockSessionDataTask(config: self.responseConfig, completionHandler: completionHandler) + } +} + +class MockSessionDataTask: URLSessionDataTask { + + enum DataError: String, ConvertibleError { + + case notConfigured = "Not Configured" + } + + var config: (data: Data?, response: HTTPURLResponse?, error: Error?)? + + var completionHandler: (Data?, URLResponse?, Error?) -> Void + + init(config: (data: Data?, response: HTTPURLResponse?, error: Error?)?, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) { + + self.config = config + self.completionHandler = completionHandler + } + + override func resume() { + + guard let config = self.config else { + + completionHandler(nil, nil, DataError.notConfigured) + return + } + completionHandler(config.data, config.response, config.error) + } +} + +protocol ConvertibleError: Error { + + var message: String { get } +} + +extension ConvertibleError where Self: RawRepresentable, Self.RawValue == String{ + + var message: String { + return self.rawValue + } +} From be8cb74ebba42e2b3bb581ee9fd0fe6ab1f61e8f Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sun, 24 Feb 2019 23:57:35 +0100 Subject: [PATCH 20/37] Feat: add configuration tests --- Example/PunkAPI.xcodeproj/project.pbxproj | 4 ++++ Example/Tests/ConfigurationTests.swift | 27 +++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 Example/Tests/ConfigurationTests.swift diff --git a/Example/PunkAPI.xcodeproj/project.pbxproj b/Example/PunkAPI.xcodeproj/project.pbxproj index 95bd6bd..aabe223 100644 --- a/Example/PunkAPI.xcodeproj/project.pbxproj +++ b/Example/PunkAPI.xcodeproj/project.pbxproj @@ -18,6 +18,7 @@ 9767CC092222B63700E684C4 /* URLBuildTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC072222B60F00E684C4 /* URLBuildTests.swift */; }; 9767CC0B2222BB1E00E684C4 /* MockSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC0A2222BB1E00E684C4 /* MockSession.swift */; }; 9767CC0D2222BDD000E684C4 /* BeerRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC0C2222BDD000E684C4 /* BeerRequestTests.swift */; }; + 9767CC0F2223550E00E684C4 /* ConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC0E2223550E00E684C4 /* ConfigurationTests.swift */; }; EBB1B4D6901624C6A90359CA /* Pods_PunkAPI_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46341D8F014E1940E53D4F02 /* Pods_PunkAPI_Tests.framework */; }; /* End PBXBuildFile section */ @@ -51,6 +52,7 @@ 9767CC072222B60F00E684C4 /* URLBuildTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBuildTests.swift; sourceTree = ""; }; 9767CC0A2222BB1E00E684C4 /* MockSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSession.swift; sourceTree = ""; }; 9767CC0C2222BDD000E684C4 /* BeerRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerRequestTests.swift; sourceTree = ""; }; + 9767CC0E2223550E00E684C4 /* ConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationTests.swift; sourceTree = ""; }; 9A440A355337DF96D159D208 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; A4CA42C1E1AE14F816574722 /* Pods-PunkAPI_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.debug.xcconfig"; sourceTree = ""; }; E294694CD6DD5DA5A6B471F1 /* Pods-PunkAPI_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.release.xcconfig"; sourceTree = ""; }; @@ -183,6 +185,7 @@ 9767CC072222B60F00E684C4 /* URLBuildTests.swift */, 9767CC0C2222BDD000E684C4 /* BeerRequestTests.swift */, 9767CC0A2222BB1E00E684C4 /* MockSession.swift */, + 9767CC0E2223550E00E684C4 /* ConfigurationTests.swift */, ); name = Request; sourceTree = ""; @@ -392,6 +395,7 @@ files = ( 9767CC0D2222BDD000E684C4 /* BeerRequestTests.swift in Sources */, 9767CBF7221993F900E684C4 /* BeerParsingTests.swift in Sources */, + 9767CC0F2223550E00E684C4 /* ConfigurationTests.swift in Sources */, 9767CBFA2219958F00E684C4 /* BeerStubs.swift in Sources */, 9767CC0B2222BB1E00E684C4 /* MockSession.swift in Sources */, 9767CC092222B63700E684C4 /* URLBuildTests.swift in Sources */, diff --git a/Example/Tests/ConfigurationTests.swift b/Example/Tests/ConfigurationTests.swift new file mode 100644 index 0000000..c9e9395 --- /dev/null +++ b/Example/Tests/ConfigurationTests.swift @@ -0,0 +1,27 @@ +// +// ConfigurationTests.swift +// PunkAPI_Tests +// +// Created by Andrea Altea on 24/02/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import XCTest +@testable import PunkAPI + +class ConfigurationTests: XCTestCase { + + func testConfigurationBuild() { + + let baseURL = URL(string: "test://api.test.it/")! + let configuration = Configuration(sessionConfiguration: .ephemeral, baseURL: baseURL) + + XCTAssert(configuration.baseURL == baseURL) + } + + func testDefaultConfiguration() { + + let configuration = Configuration.default + XCTAssert(configuration.baseURL.absoluteString == "https://api.punkapi.com/v2/") + } +} From 8a7e603a8f2e58f2f7e20df46c84302dac6d81f6 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Mon, 25 Feb 2019 00:02:27 +0100 Subject: [PATCH 21/37] Feat: define RandomBeerRequest --- Example/Pods/Pods.xcodeproj/project.pbxproj | 4 ++++ Example/PunkAPI/ViewController.swift | 2 +- PunkAPI/Classes/Request/RandomBeerRequest.swift | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 PunkAPI/Classes/Request/RandomBeerRequest.swift diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 0d93688..17f46cd 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ 90001FCA9653A9974B648EAF681F4DD4 /* PunkAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = A96C503FD3BF058AD217F43E4A5954BB /* PunkAPI.swift */; }; 94ACB62152B83DE972430EAA4B24D449 /* PunkAPI-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E7002BDD7866D71B1BE5B92068B1D65E /* PunkAPI-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9767CC062222B1BB00E684C4 /* URLBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC052222B1BB00E684C4 /* URLBuilder.swift */; }; + 9767CC112223592A00E684C4 /* RandomBeerRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC102223592A00E684C4 /* RandomBeerRequest.swift */; }; 9DEE51DC320AFD89F8CCE79E659D0E92 /* Pods-PunkAPI_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; A1658BA79EB16D586EE25257AD1D8ED6 /* PunkAPI-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = ED357DDF7318810430C08E0AD4316358 /* PunkAPI-dummy.m */; }; A3F6E06BFFDEF9DAD8325928091F4B00 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BAFF56967C81FF81A5FE0A0F4AC9EFC /* Result.swift */; }; @@ -74,6 +75,7 @@ 92229C81AD3A318707A49C8449AEB2F5 /* Pods-PunkAPI_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PunkAPI_Example-acknowledgements.plist"; sourceTree = ""; }; 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 9767CC052222B1BB00E684C4 /* URLBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBuilder.swift; sourceTree = ""; }; + 9767CC102223592A00E684C4 /* RandomBeerRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RandomBeerRequest.swift; sourceTree = ""; }; 9D14926C4AE138B3C55CE27E18BE194D /* Pods-PunkAPI_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Tests.modulemap"; sourceTree = ""; }; 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Example-dummy.m"; sourceTree = ""; }; @@ -267,6 +269,7 @@ children = ( F184F71C3E715F7CB4001C228E19BEBB /* Request.swift */, 494668F6F12367A934530175780F1FB4 /* BeerRequest.swift */, + 9767CC102223592A00E684C4 /* RandomBeerRequest.swift */, 9767CC052222B1BB00E684C4 /* URLBuilder.swift */, ); name = Request; @@ -437,6 +440,7 @@ C0BB3FEC5BB8EF2E7C42FD464D459623 /* Quantity.swift in Sources */, 6017B5D2AAB067785D0E2EE754D97A17 /* Recipe.swift in Sources */, 89899DFDA224AF6393CF9985FF2AE13E /* Request.swift in Sources */, + 9767CC112223592A00E684C4 /* RandomBeerRequest.swift in Sources */, A3F6E06BFFDEF9DAD8325928091F4B00 /* Result.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Example/PunkAPI/ViewController.swift b/Example/PunkAPI/ViewController.swift index 33896fa..b9e1b26 100644 --- a/Example/PunkAPI/ViewController.swift +++ b/Example/PunkAPI/ViewController.swift @@ -21,7 +21,7 @@ class ViewController: UIViewController { @IBAction func loadBeerAction(_ sender: Any) { - PunkAPI().get(BeerRequest(id: 6), queue: .main) { [weak self] beersResult in + PunkAPI().get(RandomBeerRequest(), queue: .main) { [weak self] beersResult in guard let strongSelf = self else { return } switch beersResult { diff --git a/PunkAPI/Classes/Request/RandomBeerRequest.swift b/PunkAPI/Classes/Request/RandomBeerRequest.swift new file mode 100644 index 0000000..c75fd15 --- /dev/null +++ b/PunkAPI/Classes/Request/RandomBeerRequest.swift @@ -0,0 +1,17 @@ +// +// RandomBeerRequest.swift +// PunkAPI +// +// Created by Andrea Altea on 24/02/2019. +// + +import Foundation + +public struct RandomBeerRequest: Request { + + public var path: String { + return "beers/random" + } + + public init() { } +} From d3dd302d7c7d4f82bd2b72b3ab8367cbac697e26 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Mon, 25 Feb 2019 00:06:52 +0100 Subject: [PATCH 22/37] feat: add randomRequest tests --- Example/Tests/BeerRequestTests.swift | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Example/Tests/BeerRequestTests.swift b/Example/Tests/BeerRequestTests.swift index ebad6bd..ee49a35 100644 --- a/Example/Tests/BeerRequestTests.swift +++ b/Example/Tests/BeerRequestTests.swift @@ -13,6 +13,13 @@ import XCTest class BeerRequestTest: XCTestCase { + func testRandomBeerRequest() { + + let request = RandomBeerRequest() + XCTAssert(request.path == "beers/random") + XCTAssert(request.parameters == nil) + } + func testBeerRequests() { self.testBeerRequest(with: 1) From 00db36971acd704dcde24010d51666f5749c1a30 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Mon, 25 Feb 2019 07:42:52 +0100 Subject: [PATCH 23/37] Update Badges --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 23f217b..b590acb 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # PunkAPI -[![CI Status](https://img.shields.io/travis/acct=/PunkAPI.svg?style=flat)](https://travis-ci.org/acct=/PunkAPI) -[![Coverage Status](https://coveralls.io/repos/github/Oni-zerone/PunkAPI/badge.svg?branch=develop)](https://coveralls.io/github/Oni-zerone/PunkAPI?branch=develop)[![Version](https://img.shields.io/cocoapods/v/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) +[![Build Status](https://travis-ci.com/Oni-zerone/PunkAPI.svg?branch=develop)](https://travis-ci.com/Oni-zerone/PunkAPI) +[![Coverage Status](https://coveralls.io/repos/github/Oni-zerone/PunkAPI/badge.svg?branch=feature%2FRandom-beer-request)](https://coveralls.io/github/Oni-zerone/PunkAPI?branch=feature%2FRandom-beer-request) [![License](https://img.shields.io/cocoapods/l/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) [![Platform](https://img.shields.io/cocoapods/p/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) From f0e3634189fd5c026f19123b99f406e0efdbfba2 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Mon, 25 Feb 2019 07:52:23 +0100 Subject: [PATCH 24/37] Add a Project description --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b590acb..bdac100 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,19 @@ # PunkAPI +[![Version](https://img.shields.io/cocoapods/v/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) [![Build Status](https://travis-ci.com/Oni-zerone/PunkAPI.svg?branch=develop)](https://travis-ci.com/Oni-zerone/PunkAPI) [![Coverage Status](https://coveralls.io/repos/github/Oni-zerone/PunkAPI/badge.svg?branch=feature%2FRandom-beer-request)](https://coveralls.io/github/Oni-zerone/PunkAPI?branch=feature%2FRandom-beer-request) +[![codebeat badge](https://codebeat.co/badges/bfe75f4d-ac1f-4e09-8a25-4f836bb93428)](https://codebeat.co/projects/github-com-oni-zerone-punkapi-develop) +[![Language](https://img.shields.io/badge/language-swift-orange.svg)](https://cocoapods.org/pods/PowerTools) [![License](https://img.shields.io/cocoapods/l/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) [![Platform](https://img.shields.io/cocoapods/p/PunkAPI.svg?style=flat)](https://cocoapods.org/pods/PunkAPI) +**This is a wrapper around PunkAPI v2 by [@samjbmason](https://twitter.com/samjbmason) you can find more informations about those APIs at https://punkapi.com/** + +_Have you ever wanted to search through Brewdog's expansive back catalogue of beer in a programmatic way? Maybe build a tool that pairs beer with food, or search beers with an abv of more than 4%? Well now your prayers have been answered!_ + +_The Punk API takes Brewdog's DIY Dog and turns it into a searchable, filterable API that's completely free and open source._ + ## Example To run the example project, clone the repo, and run `pod install` from the Example directory first. @@ -22,7 +31,7 @@ pod 'PunkAPI' ## Author -acct=, oni.zerone@gmail.com +[@Oni_zerone](https://twitter.com/Oni_zerone), oni.zerone@gmail.com ## License From 585c6b51c3acf5eae0ec5ead91e30e28581c77a6 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sat, 2 Mar 2019 14:44:48 +0100 Subject: [PATCH 25/37] Feat: define beer request --- PunkAPI/Classes/Request/BeersRequest.swift | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 PunkAPI/Classes/Request/BeersRequest.swift diff --git a/PunkAPI/Classes/Request/BeersRequest.swift b/PunkAPI/Classes/Request/BeersRequest.swift new file mode 100644 index 0000000..a0a22cd --- /dev/null +++ b/PunkAPI/Classes/Request/BeersRequest.swift @@ -0,0 +1,26 @@ +// +// BeersRequest.swift +// PunkAPI +// +// Created by Andrea Altea on 25/02/2019. +// + +import UIKit + +class BeersRequest: Request { + + var page: Int + + init(page: Int = 0) { + self.page = page + + } + +} + +extension BeersRequest: Request { + + var path: String { + return "beers" + } +} From ad8645f4b68eec048a945552fde4068c09f1dcda Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sat, 2 Mar 2019 14:46:41 +0100 Subject: [PATCH 26/37] Feat: add run script --- Example/PunkAPI.xcodeproj/project.pbxproj | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Example/PunkAPI.xcodeproj/project.pbxproj b/Example/PunkAPI.xcodeproj/project.pbxproj index aabe223..2f7e640 100644 --- a/Example/PunkAPI.xcodeproj/project.pbxproj +++ b/Example/PunkAPI.xcodeproj/project.pbxproj @@ -198,6 +198,7 @@ buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "PunkAPI_Example" */; buildPhases = ( 44318C15D7E57EAD731D7620 /* [CP] Check Pods Manifest.lock */, + 9767CC15222AC06A00E684C4 /* SwiftLint */, 9767CBEB2219750F00E684C4 /* ShellScript */, 607FACCC1AFB9204008FA782 /* Sources */, 607FACCD1AFB9204008FA782 /* Frameworks */, @@ -355,6 +356,24 @@ shellPath = /bin/sh; shellScript = "export PATH=\"/usr/local/bin:$PATH\"\nexport LANG=en_US.UTF-8\n\nif which swiftlint >/dev/null; then\n\nif [ \"$CI\" == true ]; then\necho swiftlint lint --strict\nelse\necho swiftlint\nfi\n\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; }; + 9767CC15222AC06A00E684C4 /* SwiftLint */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = SwiftLint; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export PATH=\"/usr/local/bin:$PATH\"\nexport LANG=en_US.UTF-8\n\nif which swiftlint >/dev/null; then\n\nif [ \"$CI\" == true ]; then\necho swiftlint lint --strict\nelse\necho swiftlint\nfi\n\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n\n"; + }; E502466B5504391CFC64510C /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; From ae4d22bfc525b7bff58c4b1e8ef7029e6a9209b9 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sat, 2 Mar 2019 16:50:08 +0100 Subject: [PATCH 27/37] Feat: define beer parameters --- Example/Pods/Pods.xcodeproj/project.pbxproj | 8 ++ PunkAPI/Classes/Request/BeersRequest.swift | 3 +- .../Request/BeersRequestParameter.swift | 126 ++++++++++++++++++ PunkAPI/Classes/Request/Request.swift | 15 +++ 4 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 PunkAPI/Classes/Request/BeersRequestParameter.swift diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 17f46cd..c3966b3 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -22,6 +22,8 @@ 94ACB62152B83DE972430EAA4B24D449 /* PunkAPI-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E7002BDD7866D71B1BE5B92068B1D65E /* PunkAPI-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9767CC062222B1BB00E684C4 /* URLBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC052222B1BB00E684C4 /* URLBuilder.swift */; }; 9767CC112223592A00E684C4 /* RandomBeerRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC102223592A00E684C4 /* RandomBeerRequest.swift */; }; + 9767CC17222AC3F900E684C4 /* BeersRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC16222AC3F900E684C4 /* BeersRequest.swift */; }; + 9767CC19222AC45900E684C4 /* BeersRequestParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */; }; 9DEE51DC320AFD89F8CCE79E659D0E92 /* Pods-PunkAPI_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; A1658BA79EB16D586EE25257AD1D8ED6 /* PunkAPI-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = ED357DDF7318810430C08E0AD4316358 /* PunkAPI-dummy.m */; }; A3F6E06BFFDEF9DAD8325928091F4B00 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BAFF56967C81FF81A5FE0A0F4AC9EFC /* Result.swift */; }; @@ -76,6 +78,8 @@ 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 9767CC052222B1BB00E684C4 /* URLBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBuilder.swift; sourceTree = ""; }; 9767CC102223592A00E684C4 /* RandomBeerRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RandomBeerRequest.swift; sourceTree = ""; }; + 9767CC16222AC3F900E684C4 /* BeersRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeersRequest.swift; sourceTree = ""; }; + 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeersRequestParameter.swift; sourceTree = ""; }; 9D14926C4AE138B3C55CE27E18BE194D /* Pods-PunkAPI_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Tests.modulemap"; sourceTree = ""; }; 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Example-dummy.m"; sourceTree = ""; }; @@ -269,8 +273,10 @@ children = ( F184F71C3E715F7CB4001C228E19BEBB /* Request.swift */, 494668F6F12367A934530175780F1FB4 /* BeerRequest.swift */, + 9767CC16222AC3F900E684C4 /* BeersRequest.swift */, 9767CC102223592A00E684C4 /* RandomBeerRequest.swift */, 9767CC052222B1BB00E684C4 /* URLBuilder.swift */, + 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */, ); name = Request; path = PunkAPI/Classes/Request; @@ -431,6 +437,7 @@ files = ( 5ABF50E02687C014E47088344889FC06 /* Beer.swift in Sources */, 80B5BF4A54A873CBBDE11FD50E93473F /* BeerRequest.swift in Sources */, + 9767CC19222AC45900E684C4 /* BeersRequestParameter.swift in Sources */, D8CFB7B7D1AAC97CCB20D1DD5C56FB9B /* Configuration.swift in Sources */, 3AF70E263893077BB94A1C3F36DCC044 /* Errors.swift in Sources */, 8CA330EBFA4F61AE26881286B24648A7 /* Method.swift in Sources */, @@ -442,6 +449,7 @@ 89899DFDA224AF6393CF9985FF2AE13E /* Request.swift in Sources */, 9767CC112223592A00E684C4 /* RandomBeerRequest.swift in Sources */, A3F6E06BFFDEF9DAD8325928091F4B00 /* Result.swift in Sources */, + 9767CC17222AC3F900E684C4 /* BeersRequest.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/PunkAPI/Classes/Request/BeersRequest.swift b/PunkAPI/Classes/Request/BeersRequest.swift index a0a22cd..9b94108 100644 --- a/PunkAPI/Classes/Request/BeersRequest.swift +++ b/PunkAPI/Classes/Request/BeersRequest.swift @@ -7,13 +7,12 @@ import UIKit -class BeersRequest: Request { +class BeersRequest { var page: Int init(page: Int = 0) { self.page = page - } } diff --git a/PunkAPI/Classes/Request/BeersRequestParameter.swift b/PunkAPI/Classes/Request/BeersRequestParameter.swift new file mode 100644 index 0000000..e3cc9b8 --- /dev/null +++ b/PunkAPI/Classes/Request/BeersRequestParameter.swift @@ -0,0 +1,126 @@ +// +// BeersRequestParameter.swift +// PunkAPI +// +// Created by Andrea Altea on 02/03/2019. +// + +import Foundation + +extension BeersRequest { + + public enum Parameter { + + case abv(condition: Condition, value: Float) + case ibu(condition: Condition, value: Float) + case ebc(condition: Condition, value: Float) + + case beerName(value: String) + case yeast(value: String) + + case brewed(condition: Condition, value: Date) + + case hops(value: String) + case malt(value: String) + case food(value: String) + + case ids(value: [Int]) + + internal var parameter: RequestParameter { + switch self { + case let .abv(condition, value): + return FloatParameter(key: "abv", condition: condition, value: value) + case let .ibu(condition, value): + return FloatParameter(key: "ibu", condition: condition, value: value) + case let .ebc(condition, value): + return FloatParameter(key: "ebc", condition: condition, value: value) + + case let .beerName(value): + return StringParameter(key: "beer_name", value: value) + case let .yeast(value): + return StringParameter(key: "yeast", value: value) + + case let .brewed(condition, value): + return DateParameter(type: "brewed", condition: condition, dateValue: value) + + case let .hops(value): + return StringParameter(key: "hops", value: value) + case let .malt(value): + return StringParameter(key: "malt", value: value) + case let .food(value): + return StringParameter(key: "food", value: value) + + case let .ids(value): + let ids = value.map { "\($0)" }.reduce("", { $0.isEmpty ? $1 : $0 + "|" + $1 }) + return StringParameter(key: "ids", value: ids) + } + } + } +} + +enum Condition { + case greater + case lower + + var literal: String { + switch self { + case .greater: return "gt" + case .lower: return "lt" + } + } +} + +struct FloatParameter: RequestParameter { + + var type: String + var condition: Condition + var value: Any + init(key: String, condition: Condition, value: Float) { + self.type = key + self.condition = condition + self.value = value + } + var key: String { + return "\(type)_\(condition.literal)" + } + +} + +struct StringParameter: RequestParameter { + + var key: String + var value: Any + + init(key: String, value: String) { + self.key = key + self.value = value.replacingOccurrences(of: " ", with: "_") + } +} + +struct DateParameter: RequestParameter { + + var type: String + var condition: Condition + var dateValue: Date + + var key: String { + return "\(type)_\(condition.literal)" + } + + var value: Any { + return dateValue.parameterFormat + } +} + +extension Date { + + static let parameterFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "mm-yyyy" + return formatter + }() + + var parameterFormat: String { + return Date.parameterFormatter.string(from: self) + } +} diff --git a/PunkAPI/Classes/Request/Request.swift b/PunkAPI/Classes/Request/Request.swift index fca3280..c7c8452 100644 --- a/PunkAPI/Classes/Request/Request.swift +++ b/PunkAPI/Classes/Request/Request.swift @@ -20,3 +20,18 @@ public extension Request { return nil } } + +protocol RequestParameter { + + var key: String { get } + var value: Any { get } +} + +extension Array where Element: RequestParameter { + + var parameters: [String: Any] { + return self.reduce(into: [:], { (result, parameter) in + result[parameter.key] = parameter.value + }) + } +} From 5596b06201e8b9cb823755675d96c594b550108f Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sat, 2 Mar 2019 16:55:34 +0100 Subject: [PATCH 28/37] Feat: split definitions into files --- Example/Pods/Pods.xcodeproj/project.pbxproj | 26 ++++++- .../BeersRequestParameter.swift | 67 ------------------- .../Request/Parameter/DateParameter.swift | 29 ++++++++ .../Request/Parameter/FloatParameter.swift | 24 +++++++ .../Request/Parameter/RequestParameter.swift | 35 ++++++++++ .../Request/Parameter/StringParameter.swift | 19 ++++++ PunkAPI/Classes/Request/Request.swift | 15 ----- 7 files changed, 132 insertions(+), 83 deletions(-) rename PunkAPI/Classes/Request/{ => Parameter}/BeersRequestParameter.swift (60%) create mode 100644 PunkAPI/Classes/Request/Parameter/DateParameter.swift create mode 100644 PunkAPI/Classes/Request/Parameter/FloatParameter.swift create mode 100644 PunkAPI/Classes/Request/Parameter/RequestParameter.swift create mode 100644 PunkAPI/Classes/Request/Parameter/StringParameter.swift diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index c3966b3..5d1186f 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -24,6 +24,10 @@ 9767CC112223592A00E684C4 /* RandomBeerRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC102223592A00E684C4 /* RandomBeerRequest.swift */; }; 9767CC17222AC3F900E684C4 /* BeersRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC16222AC3F900E684C4 /* BeersRequest.swift */; }; 9767CC19222AC45900E684C4 /* BeersRequestParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */; }; + 9767CC1C222ADDD100E684C4 /* RequestParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC1B222ADDD100E684C4 /* RequestParameter.swift */; }; + 9767CC20222ADE2500E684C4 /* FloatParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC1F222ADE2500E684C4 /* FloatParameter.swift */; }; + 9767CC22222ADE5100E684C4 /* StringParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC21222ADE5100E684C4 /* StringParameter.swift */; }; + 9767CC24222ADE6800E684C4 /* DateParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC23222ADE6800E684C4 /* DateParameter.swift */; }; 9DEE51DC320AFD89F8CCE79E659D0E92 /* Pods-PunkAPI_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; A1658BA79EB16D586EE25257AD1D8ED6 /* PunkAPI-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = ED357DDF7318810430C08E0AD4316358 /* PunkAPI-dummy.m */; }; A3F6E06BFFDEF9DAD8325928091F4B00 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BAFF56967C81FF81A5FE0A0F4AC9EFC /* Result.swift */; }; @@ -80,6 +84,10 @@ 9767CC102223592A00E684C4 /* RandomBeerRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RandomBeerRequest.swift; sourceTree = ""; }; 9767CC16222AC3F900E684C4 /* BeersRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeersRequest.swift; sourceTree = ""; }; 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeersRequestParameter.swift; sourceTree = ""; }; + 9767CC1B222ADDD100E684C4 /* RequestParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestParameter.swift; sourceTree = ""; }; + 9767CC1F222ADE2500E684C4 /* FloatParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatParameter.swift; sourceTree = ""; }; + 9767CC21222ADE5100E684C4 /* StringParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringParameter.swift; sourceTree = ""; }; + 9767CC23222ADE6800E684C4 /* DateParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateParameter.swift; sourceTree = ""; }; 9D14926C4AE138B3C55CE27E18BE194D /* Pods-PunkAPI_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Tests.modulemap"; sourceTree = ""; }; 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Example-dummy.m"; sourceTree = ""; }; @@ -209,6 +217,18 @@ path = Results; sourceTree = ""; }; + 9767CC1A222ADDBB00E684C4 /* Parameter */ = { + isa = PBXGroup; + children = ( + 9767CC1B222ADDD100E684C4 /* RequestParameter.swift */, + 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */, + 9767CC1F222ADE2500E684C4 /* FloatParameter.swift */, + 9767CC21222ADE5100E684C4 /* StringParameter.swift */, + 9767CC23222ADE6800E684C4 /* DateParameter.swift */, + ); + path = Parameter; + sourceTree = ""; + }; 9BFECB8663CD309F9214B4311C96BCB5 /* Pods-PunkAPI_Example */ = { isa = PBXGroup; children = ( @@ -271,12 +291,12 @@ EE14703CB73E7B607CA53D2EC58437E4 /* Request */ = { isa = PBXGroup; children = ( + 9767CC1A222ADDBB00E684C4 /* Parameter */, F184F71C3E715F7CB4001C228E19BEBB /* Request.swift */, 494668F6F12367A934530175780F1FB4 /* BeerRequest.swift */, 9767CC16222AC3F900E684C4 /* BeersRequest.swift */, 9767CC102223592A00E684C4 /* RandomBeerRequest.swift */, 9767CC052222B1BB00E684C4 /* URLBuilder.swift */, - 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */, ); name = Request; path = PunkAPI/Classes/Request; @@ -439,13 +459,17 @@ 80B5BF4A54A873CBBDE11FD50E93473F /* BeerRequest.swift in Sources */, 9767CC19222AC45900E684C4 /* BeersRequestParameter.swift in Sources */, D8CFB7B7D1AAC97CCB20D1DD5C56FB9B /* Configuration.swift in Sources */, + 9767CC20222ADE2500E684C4 /* FloatParameter.swift in Sources */, 3AF70E263893077BB94A1C3F36DCC044 /* Errors.swift in Sources */, 8CA330EBFA4F61AE26881286B24648A7 /* Method.swift in Sources */, 9767CC062222B1BB00E684C4 /* URLBuilder.swift in Sources */, A1658BA79EB16D586EE25257AD1D8ED6 /* PunkAPI-dummy.m in Sources */, 90001FCA9653A9974B648EAF681F4DD4 /* PunkAPI.swift in Sources */, + 9767CC22222ADE5100E684C4 /* StringParameter.swift in Sources */, C0BB3FEC5BB8EF2E7C42FD464D459623 /* Quantity.swift in Sources */, + 9767CC24222ADE6800E684C4 /* DateParameter.swift in Sources */, 6017B5D2AAB067785D0E2EE754D97A17 /* Recipe.swift in Sources */, + 9767CC1C222ADDD100E684C4 /* RequestParameter.swift in Sources */, 89899DFDA224AF6393CF9985FF2AE13E /* Request.swift in Sources */, 9767CC112223592A00E684C4 /* RandomBeerRequest.swift in Sources */, A3F6E06BFFDEF9DAD8325928091F4B00 /* Result.swift in Sources */, diff --git a/PunkAPI/Classes/Request/BeersRequestParameter.swift b/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift similarity index 60% rename from PunkAPI/Classes/Request/BeersRequestParameter.swift rename to PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift index e3cc9b8..1670b8d 100644 --- a/PunkAPI/Classes/Request/BeersRequestParameter.swift +++ b/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift @@ -57,70 +57,3 @@ extension BeersRequest { } } } - -enum Condition { - case greater - case lower - - var literal: String { - switch self { - case .greater: return "gt" - case .lower: return "lt" - } - } -} - -struct FloatParameter: RequestParameter { - - var type: String - var condition: Condition - var value: Any - init(key: String, condition: Condition, value: Float) { - self.type = key - self.condition = condition - self.value = value - } - var key: String { - return "\(type)_\(condition.literal)" - } - -} - -struct StringParameter: RequestParameter { - - var key: String - var value: Any - - init(key: String, value: String) { - self.key = key - self.value = value.replacingOccurrences(of: " ", with: "_") - } -} - -struct DateParameter: RequestParameter { - - var type: String - var condition: Condition - var dateValue: Date - - var key: String { - return "\(type)_\(condition.literal)" - } - - var value: Any { - return dateValue.parameterFormat - } -} - -extension Date { - - static let parameterFormatter: DateFormatter = { - let formatter = DateFormatter() - formatter.dateFormat = "mm-yyyy" - return formatter - }() - - var parameterFormat: String { - return Date.parameterFormatter.string(from: self) - } -} diff --git a/PunkAPI/Classes/Request/Parameter/DateParameter.swift b/PunkAPI/Classes/Request/Parameter/DateParameter.swift new file mode 100644 index 0000000..9e79291 --- /dev/null +++ b/PunkAPI/Classes/Request/Parameter/DateParameter.swift @@ -0,0 +1,29 @@ +// +// DateParameter.swift +// PunkAPI +// +// Created by Andrea Altea on 02/03/2019. +// + +import Foundation + +struct DateParameter: RequestParameter { + + static var formatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "mm-yyyy" + return formatter + }() + + var type: String + var condition: Condition + var dateValue: Date + + var key: String { + return "\(type)_\(condition.literal)" + } + + var value: Any { + return DateParameter.formatter.string(from: dateValue) + } +} diff --git a/PunkAPI/Classes/Request/Parameter/FloatParameter.swift b/PunkAPI/Classes/Request/Parameter/FloatParameter.swift new file mode 100644 index 0000000..82cbc1e --- /dev/null +++ b/PunkAPI/Classes/Request/Parameter/FloatParameter.swift @@ -0,0 +1,24 @@ +// +// FloatParameter.swift +// PunkAPI +// +// Created by Andrea Altea on 02/03/2019. +// + +import Foundation + +struct FloatParameter: RequestParameter { + + var type: String + var condition: Condition + var value: Any + init(key: String, condition: Condition, value: Float) { + self.type = key + self.condition = condition + self.value = value + } + var key: String { + return "\(type)_\(condition.literal)" + } + +} diff --git a/PunkAPI/Classes/Request/Parameter/RequestParameter.swift b/PunkAPI/Classes/Request/Parameter/RequestParameter.swift new file mode 100644 index 0000000..648c5fd --- /dev/null +++ b/PunkAPI/Classes/Request/Parameter/RequestParameter.swift @@ -0,0 +1,35 @@ +// +// RequestParameter.swift +// PunkAPI +// +// Created by Andrea Altea on 02/03/2019. +// + +import Foundation + +protocol RequestParameter { + + var key: String { get } + var value: Any { get } +} + +extension Array where Element: RequestParameter { + + var parameters: [String: Any] { + return self.reduce(into: [:], { (result, parameter) in + result[parameter.key] = parameter.value + }) + } +} + +enum Condition { + case greater + case lower + + var literal: String { + switch self { + case .greater: return "gt" + case .lower: return "lt" + } + } +} diff --git a/PunkAPI/Classes/Request/Parameter/StringParameter.swift b/PunkAPI/Classes/Request/Parameter/StringParameter.swift new file mode 100644 index 0000000..ac25395 --- /dev/null +++ b/PunkAPI/Classes/Request/Parameter/StringParameter.swift @@ -0,0 +1,19 @@ +// +// StringParameter.swift +// PunkAPI +// +// Created by Andrea Altea on 02/03/2019. +// + +import Foundation + +struct StringParameter: RequestParameter { + + var key: String + var value: Any + + init(key: String, value: String) { + self.key = key + self.value = value.replacingOccurrences(of: " ", with: "_") + } +} diff --git a/PunkAPI/Classes/Request/Request.swift b/PunkAPI/Classes/Request/Request.swift index c7c8452..fca3280 100644 --- a/PunkAPI/Classes/Request/Request.swift +++ b/PunkAPI/Classes/Request/Request.swift @@ -20,18 +20,3 @@ public extension Request { return nil } } - -protocol RequestParameter { - - var key: String { get } - var value: Any { get } -} - -extension Array where Element: RequestParameter { - - var parameters: [String: Any] { - return self.reduce(into: [:], { (result, parameter) in - result[parameter.key] = parameter.value - }) - } -} From d2361056defd4e446fea41167d732de621976c9a Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sat, 2 Mar 2019 17:19:28 +0100 Subject: [PATCH 29/37] Feat: prepare filter parameters in BeersRequest --- Example/Pods/Pods.xcodeproj/project.pbxproj | 2 +- PunkAPI/Classes/Request/BeersRequest.swift | 36 ++++++++-- .../Parameter/BeersRequestParameter.swift | 68 ++++++++++--------- .../Request/Parameter/DateParameter.swift | 2 +- .../Request/Parameter/FloatParameter.swift | 2 +- .../Request/Parameter/RequestParameter.swift | 27 ++++---- 6 files changed, 83 insertions(+), 54 deletions(-) diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 5d1186f..7b27a13 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -221,10 +221,10 @@ isa = PBXGroup; children = ( 9767CC1B222ADDD100E684C4 /* RequestParameter.swift */, - 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */, 9767CC1F222ADE2500E684C4 /* FloatParameter.swift */, 9767CC21222ADE5100E684C4 /* StringParameter.swift */, 9767CC23222ADE6800E684C4 /* DateParameter.swift */, + 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */, ); path = Parameter; sourceTree = ""; diff --git a/PunkAPI/Classes/Request/BeersRequest.swift b/PunkAPI/Classes/Request/BeersRequest.swift index 9b94108..ce1ed0a 100644 --- a/PunkAPI/Classes/Request/BeersRequest.swift +++ b/PunkAPI/Classes/Request/BeersRequest.swift @@ -7,19 +7,43 @@ import UIKit -class BeersRequest { +public struct BeersRequest { - var page: Int - - init(page: Int = 0) { + public var page: Int + public var filter: [BeersRequest.Parameter] + + public init(filter:[BeersRequest.Parameter] = [], page: Int = 0) { + self.filter = filter self.page = page } - } extension BeersRequest: Request { - var path: String { + public var path: String { return "beers" } + + public var parameters: [String: Any]? { + + if var filter = filterParameters { + filter["page"] = page + return filter + } + return ["page": page] + } +} + +extension BeersRequest { + + var filterParameters: [String: Any]? { + + if filter.isEmpty { return nil } + + return filter.map { parameter -> RequestParameter in + return parameter.parameter + }.reduce(into: [:], { (result, parameter) in + result[parameter.key] = parameter.value + }) + } } diff --git a/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift b/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift index 1670b8d..e2a2c11 100644 --- a/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift +++ b/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift @@ -9,7 +9,7 @@ import Foundation extension BeersRequest { - public enum Parameter { + public enum Parameter { case abv(condition: Condition, value: Float) case ibu(condition: Condition, value: Float) @@ -19,41 +19,45 @@ extension BeersRequest { case yeast(value: String) case brewed(condition: Condition, value: Date) - - case hops(value: String) + + case hops(value: String) case malt(value: String) case food(value: String) + + case ids(value: [Int]) + } +} + +extension BeersRequest.Parameter { - case ids(value: [Int]) - internal var parameter: RequestParameter { - switch self { - case let .abv(condition, value): - return FloatParameter(key: "abv", condition: condition, value: value) - case let .ibu(condition, value): - return FloatParameter(key: "ibu", condition: condition, value: value) - case let .ebc(condition, value): - return FloatParameter(key: "ebc", condition: condition, value: value) - - case let .beerName(value): - return StringParameter(key: "beer_name", value: value) - case let .yeast(value): - return StringParameter(key: "yeast", value: value) - - case let .brewed(condition, value): - return DateParameter(type: "brewed", condition: condition, dateValue: value) - - case let .hops(value): - return StringParameter(key: "hops", value: value) - case let .malt(value): - return StringParameter(key: "malt", value: value) - case let .food(value): - return StringParameter(key: "food", value: value) - - case let .ids(value): - let ids = value.map { "\($0)" }.reduce("", { $0.isEmpty ? $1 : $0 + "|" + $1 }) - return StringParameter(key: "ids", value: ids) - } + internal var parameter: RequestParameter { + switch self { + case let .abv(condition, value): + return FloatParameter(key: "abv", condition: condition, value: value) + case let .ibu(condition, value): + return FloatParameter(key: "ibu", condition: condition, value: value) + case let .ebc(condition, value): + return FloatParameter(key: "ebc", condition: condition, value: value) + + case let .beerName(value): + return StringParameter(key: "beer_name", value: value) + case let .yeast(value): + return StringParameter(key: "yeast", value: value) + + case let .brewed(condition, value): + return DateParameter(type: "brewed", condition: condition, dateValue: value) + + case let .hops(value): + return StringParameter(key: "hops", value: value) + case let .malt(value): + return StringParameter(key: "malt", value: value) + case let .food(value): + return StringParameter(key: "food", value: value) + + case let .ids(value): + let ids = value.map { "\($0)" }.reduce("", { $0.isEmpty ? $1 : $0 + "|" + $1 }) + return StringParameter(key: "ids", value: ids) } } } diff --git a/PunkAPI/Classes/Request/Parameter/DateParameter.swift b/PunkAPI/Classes/Request/Parameter/DateParameter.swift index 9e79291..302830b 100644 --- a/PunkAPI/Classes/Request/Parameter/DateParameter.swift +++ b/PunkAPI/Classes/Request/Parameter/DateParameter.swift @@ -20,7 +20,7 @@ struct DateParameter: RequestParameter { var dateValue: Date var key: String { - return "\(type)_\(condition.literal)" + return "\(type)_\(condition.time)" } var value: Any { diff --git a/PunkAPI/Classes/Request/Parameter/FloatParameter.swift b/PunkAPI/Classes/Request/Parameter/FloatParameter.swift index 82cbc1e..014c24f 100644 --- a/PunkAPI/Classes/Request/Parameter/FloatParameter.swift +++ b/PunkAPI/Classes/Request/Parameter/FloatParameter.swift @@ -18,7 +18,7 @@ struct FloatParameter: RequestParameter { self.value = value } var key: String { - return "\(type)_\(condition.literal)" + return "\(type)_\(condition.dimension)" } } diff --git a/PunkAPI/Classes/Request/Parameter/RequestParameter.swift b/PunkAPI/Classes/Request/Parameter/RequestParameter.swift index 648c5fd..407ef9a 100644 --- a/PunkAPI/Classes/Request/Parameter/RequestParameter.swift +++ b/PunkAPI/Classes/Request/Parameter/RequestParameter.swift @@ -13,23 +13,24 @@ protocol RequestParameter { var value: Any { get } } -extension Array where Element: RequestParameter { - - var parameters: [String: Any] { - return self.reduce(into: [:], { (result, parameter) in - result[parameter.key] = parameter.value - }) - } +public enum Condition { + case more + case less } -enum Condition { - case greater - case lower +extension Condition { - var literal: String { + var dimension: String { + switch self { + case .more: return "gt" + case .less: return "lt" + } + } + + var time: String { switch self { - case .greater: return "gt" - case .lower: return "lt" + case .more: return "after" + case .less: return "before" } } } From b9b28437cd5864b3c2020aa83938860319831d90 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sat, 2 Mar 2019 17:28:20 +0100 Subject: [PATCH 30/37] Chore: update example --- Example/PunkAPI/ViewController.swift | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Example/PunkAPI/ViewController.swift b/Example/PunkAPI/ViewController.swift index b9e1b26..2698364 100644 --- a/Example/PunkAPI/ViewController.swift +++ b/Example/PunkAPI/ViewController.swift @@ -21,13 +21,25 @@ class ViewController: UIViewController { @IBAction func loadBeerAction(_ sender: Any) { - PunkAPI().get(RandomBeerRequest(), queue: .main) { [weak self] beersResult in + let request = BeersRequest(filter: [.abv(condition: .more, value: 1.2)]) + + PunkAPI().get(request, queue: .main) { [weak self] beersResult in guard let strongSelf = self else { return } switch beersResult { case .success(let beers): - strongSelf.label.text = beers.first?.name ?? "Not Found" + let string = beers.reduce(into: "", { (result, beer) in + + guard let name = beer.name else { return } + if result.isEmpty { + result = name + return + } + return result.append(contentsOf: ", \(name)") + }) + + strongSelf.label.text = string.isEmpty ? "Not Found" : string case .failure(let error): strongSelf.label.text = error.localizedDescription From a79841f8319882b83c4daaee1ad1da3dd9dbf2a3 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sat, 2 Mar 2019 17:45:43 +0100 Subject: [PATCH 31/37] Feat: update FloatParameter to avoid unrecognized values --- Example/Pods/Pods.xcodeproj/project.pbxproj | 8 ++++---- Example/PunkAPI/ViewController.swift | 2 +- PunkAPI/Classes/Request/BeersRequest.swift | 10 +++++----- .../Request/Parameter/BeersRequestParameter.swift | 12 ++++++------ .../{FloatParameter.swift => IntParameter.swift} | 7 +++---- 5 files changed, 19 insertions(+), 20 deletions(-) rename PunkAPI/Classes/Request/Parameter/{FloatParameter.swift => IntParameter.swift} (71%) diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 7b27a13..1aee46b 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -25,7 +25,7 @@ 9767CC17222AC3F900E684C4 /* BeersRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC16222AC3F900E684C4 /* BeersRequest.swift */; }; 9767CC19222AC45900E684C4 /* BeersRequestParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */; }; 9767CC1C222ADDD100E684C4 /* RequestParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC1B222ADDD100E684C4 /* RequestParameter.swift */; }; - 9767CC20222ADE2500E684C4 /* FloatParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC1F222ADE2500E684C4 /* FloatParameter.swift */; }; + 9767CC20222ADE2500E684C4 /* IntParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC1F222ADE2500E684C4 /* IntParameter.swift */; }; 9767CC22222ADE5100E684C4 /* StringParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC21222ADE5100E684C4 /* StringParameter.swift */; }; 9767CC24222ADE6800E684C4 /* DateParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC23222ADE6800E684C4 /* DateParameter.swift */; }; 9DEE51DC320AFD89F8CCE79E659D0E92 /* Pods-PunkAPI_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -85,7 +85,7 @@ 9767CC16222AC3F900E684C4 /* BeersRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeersRequest.swift; sourceTree = ""; }; 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeersRequestParameter.swift; sourceTree = ""; }; 9767CC1B222ADDD100E684C4 /* RequestParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestParameter.swift; sourceTree = ""; }; - 9767CC1F222ADE2500E684C4 /* FloatParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatParameter.swift; sourceTree = ""; }; + 9767CC1F222ADE2500E684C4 /* IntParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntParameter.swift; sourceTree = ""; }; 9767CC21222ADE5100E684C4 /* StringParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringParameter.swift; sourceTree = ""; }; 9767CC23222ADE6800E684C4 /* DateParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateParameter.swift; sourceTree = ""; }; 9D14926C4AE138B3C55CE27E18BE194D /* Pods-PunkAPI_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Tests.modulemap"; sourceTree = ""; }; @@ -221,7 +221,7 @@ isa = PBXGroup; children = ( 9767CC1B222ADDD100E684C4 /* RequestParameter.swift */, - 9767CC1F222ADE2500E684C4 /* FloatParameter.swift */, + 9767CC1F222ADE2500E684C4 /* IntParameter.swift */, 9767CC21222ADE5100E684C4 /* StringParameter.swift */, 9767CC23222ADE6800E684C4 /* DateParameter.swift */, 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */, @@ -459,7 +459,7 @@ 80B5BF4A54A873CBBDE11FD50E93473F /* BeerRequest.swift in Sources */, 9767CC19222AC45900E684C4 /* BeersRequestParameter.swift in Sources */, D8CFB7B7D1AAC97CCB20D1DD5C56FB9B /* Configuration.swift in Sources */, - 9767CC20222ADE2500E684C4 /* FloatParameter.swift in Sources */, + 9767CC20222ADE2500E684C4 /* IntParameter.swift in Sources */, 3AF70E263893077BB94A1C3F36DCC044 /* Errors.swift in Sources */, 8CA330EBFA4F61AE26881286B24648A7 /* Method.swift in Sources */, 9767CC062222B1BB00E684C4 /* URLBuilder.swift in Sources */, diff --git a/Example/PunkAPI/ViewController.swift b/Example/PunkAPI/ViewController.swift index 2698364..74c7deb 100644 --- a/Example/PunkAPI/ViewController.swift +++ b/Example/PunkAPI/ViewController.swift @@ -21,7 +21,7 @@ class ViewController: UIViewController { @IBAction func loadBeerAction(_ sender: Any) { - let request = BeersRequest(filter: [.abv(condition: .more, value: 1.2)]) + let request = BeersRequest(filter: [.abv(condition: .more, value: 3)]) PunkAPI().get(request, queue: .main) { [weak self] beersResult in diff --git a/PunkAPI/Classes/Request/BeersRequest.swift b/PunkAPI/Classes/Request/BeersRequest.swift index ce1ed0a..f45da1d 100644 --- a/PunkAPI/Classes/Request/BeersRequest.swift +++ b/PunkAPI/Classes/Request/BeersRequest.swift @@ -26,11 +26,11 @@ extension BeersRequest: Request { public var parameters: [String: Any]? { - if var filter = filterParameters { - filter["page"] = page - return filter - } - return ["page": page] + guard page > 0 else { return filterParameters } + + var parameters = filterParameters ?? [:] + parameters["page"] = page + return parameters } } diff --git a/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift b/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift index e2a2c11..1bbd2fb 100644 --- a/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift +++ b/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift @@ -11,9 +11,9 @@ extension BeersRequest { public enum Parameter { - case abv(condition: Condition, value: Float) - case ibu(condition: Condition, value: Float) - case ebc(condition: Condition, value: Float) + case abv(condition: Condition, value: Int) + case ibu(condition: Condition, value: Int) + case ebc(condition: Condition, value: Int) case beerName(value: String) case yeast(value: String) @@ -34,11 +34,11 @@ extension BeersRequest.Parameter { internal var parameter: RequestParameter { switch self { case let .abv(condition, value): - return FloatParameter(key: "abv", condition: condition, value: value) + return IntParameter(key: "abv", condition: condition, value: value) case let .ibu(condition, value): - return FloatParameter(key: "ibu", condition: condition, value: value) + return IntParameter(key: "ibu", condition: condition, value: value) case let .ebc(condition, value): - return FloatParameter(key: "ebc", condition: condition, value: value) + return IntParameter(key: "ebc", condition: condition, value: value) case let .beerName(value): return StringParameter(key: "beer_name", value: value) diff --git a/PunkAPI/Classes/Request/Parameter/FloatParameter.swift b/PunkAPI/Classes/Request/Parameter/IntParameter.swift similarity index 71% rename from PunkAPI/Classes/Request/Parameter/FloatParameter.swift rename to PunkAPI/Classes/Request/Parameter/IntParameter.swift index 014c24f..0830bf5 100644 --- a/PunkAPI/Classes/Request/Parameter/FloatParameter.swift +++ b/PunkAPI/Classes/Request/Parameter/IntParameter.swift @@ -1,5 +1,5 @@ // -// FloatParameter.swift +// IntParameter.swift // PunkAPI // // Created by Andrea Altea on 02/03/2019. @@ -7,12 +7,12 @@ import Foundation -struct FloatParameter: RequestParameter { +struct IntParameter: RequestParameter { var type: String var condition: Condition var value: Any - init(key: String, condition: Condition, value: Float) { + init(key: String, condition: Condition, value: Int) { self.type = key self.condition = condition self.value = value @@ -20,5 +20,4 @@ struct FloatParameter: RequestParameter { var key: String { return "\(type)_\(condition.dimension)" } - } From 153d36d954bb0fbfc65decb5cd02348d5d125b6b Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sat, 2 Mar 2019 22:07:42 +0100 Subject: [PATCH 32/37] Fix: maintain Float interface but use Int value to avoid parameter fail --- Example/Pods/Pods.xcodeproj/project.pbxproj | 8 ++++---- .../Classes/Request/Parameter/BeersRequestParameter.swift | 6 +++--- .../{IntParameter.swift => FloatParameter.swift} | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) rename PunkAPI/Classes/Request/Parameter/{IntParameter.swift => FloatParameter.swift} (79%) diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 1aee46b..7b27a13 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -25,7 +25,7 @@ 9767CC17222AC3F900E684C4 /* BeersRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC16222AC3F900E684C4 /* BeersRequest.swift */; }; 9767CC19222AC45900E684C4 /* BeersRequestParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */; }; 9767CC1C222ADDD100E684C4 /* RequestParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC1B222ADDD100E684C4 /* RequestParameter.swift */; }; - 9767CC20222ADE2500E684C4 /* IntParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC1F222ADE2500E684C4 /* IntParameter.swift */; }; + 9767CC20222ADE2500E684C4 /* FloatParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC1F222ADE2500E684C4 /* FloatParameter.swift */; }; 9767CC22222ADE5100E684C4 /* StringParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC21222ADE5100E684C4 /* StringParameter.swift */; }; 9767CC24222ADE6800E684C4 /* DateParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC23222ADE6800E684C4 /* DateParameter.swift */; }; 9DEE51DC320AFD89F8CCE79E659D0E92 /* Pods-PunkAPI_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -85,7 +85,7 @@ 9767CC16222AC3F900E684C4 /* BeersRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeersRequest.swift; sourceTree = ""; }; 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeersRequestParameter.swift; sourceTree = ""; }; 9767CC1B222ADDD100E684C4 /* RequestParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestParameter.swift; sourceTree = ""; }; - 9767CC1F222ADE2500E684C4 /* IntParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntParameter.swift; sourceTree = ""; }; + 9767CC1F222ADE2500E684C4 /* FloatParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatParameter.swift; sourceTree = ""; }; 9767CC21222ADE5100E684C4 /* StringParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringParameter.swift; sourceTree = ""; }; 9767CC23222ADE6800E684C4 /* DateParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateParameter.swift; sourceTree = ""; }; 9D14926C4AE138B3C55CE27E18BE194D /* Pods-PunkAPI_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Tests.modulemap"; sourceTree = ""; }; @@ -221,7 +221,7 @@ isa = PBXGroup; children = ( 9767CC1B222ADDD100E684C4 /* RequestParameter.swift */, - 9767CC1F222ADE2500E684C4 /* IntParameter.swift */, + 9767CC1F222ADE2500E684C4 /* FloatParameter.swift */, 9767CC21222ADE5100E684C4 /* StringParameter.swift */, 9767CC23222ADE6800E684C4 /* DateParameter.swift */, 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */, @@ -459,7 +459,7 @@ 80B5BF4A54A873CBBDE11FD50E93473F /* BeerRequest.swift in Sources */, 9767CC19222AC45900E684C4 /* BeersRequestParameter.swift in Sources */, D8CFB7B7D1AAC97CCB20D1DD5C56FB9B /* Configuration.swift in Sources */, - 9767CC20222ADE2500E684C4 /* IntParameter.swift in Sources */, + 9767CC20222ADE2500E684C4 /* FloatParameter.swift in Sources */, 3AF70E263893077BB94A1C3F36DCC044 /* Errors.swift in Sources */, 8CA330EBFA4F61AE26881286B24648A7 /* Method.swift in Sources */, 9767CC062222B1BB00E684C4 /* URLBuilder.swift in Sources */, diff --git a/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift b/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift index 1bbd2fb..c617592 100644 --- a/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift +++ b/PunkAPI/Classes/Request/Parameter/BeersRequestParameter.swift @@ -11,9 +11,9 @@ extension BeersRequest { public enum Parameter { - case abv(condition: Condition, value: Int) - case ibu(condition: Condition, value: Int) - case ebc(condition: Condition, value: Int) + case abv(condition: Condition, value: Float) + case ibu(condition: Condition, value: Float) + case ebc(condition: Condition, value: Float) case beerName(value: String) case yeast(value: String) diff --git a/PunkAPI/Classes/Request/Parameter/IntParameter.swift b/PunkAPI/Classes/Request/Parameter/FloatParameter.swift similarity index 79% rename from PunkAPI/Classes/Request/Parameter/IntParameter.swift rename to PunkAPI/Classes/Request/Parameter/FloatParameter.swift index 0830bf5..02ea838 100644 --- a/PunkAPI/Classes/Request/Parameter/IntParameter.swift +++ b/PunkAPI/Classes/Request/Parameter/FloatParameter.swift @@ -12,10 +12,10 @@ struct IntParameter: RequestParameter { var type: String var condition: Condition var value: Any - init(key: String, condition: Condition, value: Int) { + init(key: String, condition: Condition, value: Float) { self.type = key self.condition = condition - self.value = value + self.value = Int(value) } var key: String { return "\(type)_\(condition.dimension)" From 57bb3c995afd783ec7bd213aed7ad2ddaed73453 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sat, 2 Mar 2019 22:50:20 +0100 Subject: [PATCH 33/37] Feat: add parameter parsing tests --- Example/PunkAPI.xcodeproj/project.pbxproj | 4 + Example/Tests/BeerRequestTests.swift | 2 - Example/Tests/BeersRequestTests.swift | 125 ++++++++++++++++++ .../Request/Parameter/DateParameter.swift | 3 +- 4 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 Example/Tests/BeersRequestTests.swift diff --git a/Example/PunkAPI.xcodeproj/project.pbxproj b/Example/PunkAPI.xcodeproj/project.pbxproj index 2f7e640..9634009 100644 --- a/Example/PunkAPI.xcodeproj/project.pbxproj +++ b/Example/PunkAPI.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 9767CC0B2222BB1E00E684C4 /* MockSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC0A2222BB1E00E684C4 /* MockSession.swift */; }; 9767CC0D2222BDD000E684C4 /* BeerRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC0C2222BDD000E684C4 /* BeerRequestTests.swift */; }; 9767CC0F2223550E00E684C4 /* ConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC0E2223550E00E684C4 /* ConfigurationTests.swift */; }; + 9767CC27222B299300E684C4 /* BeersRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC25222B286F00E684C4 /* BeersRequestTests.swift */; }; EBB1B4D6901624C6A90359CA /* Pods_PunkAPI_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46341D8F014E1940E53D4F02 /* Pods_PunkAPI_Tests.framework */; }; /* End PBXBuildFile section */ @@ -53,6 +54,7 @@ 9767CC0A2222BB1E00E684C4 /* MockSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSession.swift; sourceTree = ""; }; 9767CC0C2222BDD000E684C4 /* BeerRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerRequestTests.swift; sourceTree = ""; }; 9767CC0E2223550E00E684C4 /* ConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationTests.swift; sourceTree = ""; }; + 9767CC25222B286F00E684C4 /* BeersRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeersRequestTests.swift; sourceTree = ""; }; 9A440A355337DF96D159D208 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; A4CA42C1E1AE14F816574722 /* Pods-PunkAPI_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.debug.xcconfig"; sourceTree = ""; }; E294694CD6DD5DA5A6B471F1 /* Pods-PunkAPI_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.release.xcconfig"; sourceTree = ""; }; @@ -184,6 +186,7 @@ children = ( 9767CC072222B60F00E684C4 /* URLBuildTests.swift */, 9767CC0C2222BDD000E684C4 /* BeerRequestTests.swift */, + 9767CC25222B286F00E684C4 /* BeersRequestTests.swift */, 9767CC0A2222BB1E00E684C4 /* MockSession.swift */, 9767CC0E2223550E00E684C4 /* ConfigurationTests.swift */, ); @@ -413,6 +416,7 @@ buildActionMask = 2147483647; files = ( 9767CC0D2222BDD000E684C4 /* BeerRequestTests.swift in Sources */, + 9767CC27222B299300E684C4 /* BeersRequestTests.swift in Sources */, 9767CBF7221993F900E684C4 /* BeerParsingTests.swift in Sources */, 9767CC0F2223550E00E684C4 /* ConfigurationTests.swift in Sources */, 9767CBFA2219958F00E684C4 /* BeerStubs.swift in Sources */, diff --git a/Example/Tests/BeerRequestTests.swift b/Example/Tests/BeerRequestTests.swift index ee49a35..d95038f 100644 --- a/Example/Tests/BeerRequestTests.swift +++ b/Example/Tests/BeerRequestTests.swift @@ -6,8 +6,6 @@ // Copyright © 2019 CocoaPods. All rights reserved. // -import Foundation - import XCTest @testable import PunkAPI diff --git a/Example/Tests/BeersRequestTests.swift b/Example/Tests/BeersRequestTests.swift new file mode 100644 index 0000000..e9b0b5d --- /dev/null +++ b/Example/Tests/BeersRequestTests.swift @@ -0,0 +1,125 @@ +// +// BeersRequestTests.swift +// PunkAPI_Example +// +// Created by Andrea Altea on 02/03/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import XCTest +@testable import PunkAPI + +class BeersRequestTest: XCTestCase { + + func testABVParameterGreater() { + let parameter = getParameter(.abv(condition: .more, value: 1.2)) + XCTAssert(parameter.key == "abv_gt") + XCTAssert(1 == parameter.value as? Int) + } + + func testABVParameterLessThan() { + let parameter = getParameter(.abv(condition: .less, value: 1.2)) + XCTAssert(parameter.key == "abv_lt") + XCTAssert(1 == parameter.value as? Int) + } + + func testIBUParameterGreater() { + let parameter = getParameter(.ibu(condition: .more, value: 1.2)) + XCTAssert(parameter.key == "ibu_gt") + XCTAssert(1 == parameter.value as? Int) + } + + func testIBUParameterLessThan() { + let parameter = getParameter(.ibu(condition: .less, value: 1.2)) + XCTAssert(parameter.key == "ibu_lt") + XCTAssert(1 == parameter.value as? Int) + } + + func testEBCParameterGreater() { + let parameter = getParameter(.ebc(condition: .more, value: 1.2)) + XCTAssert(parameter.key == "ebc_gt") + XCTAssert(1 == parameter.value as? Int) + } + + func testEBCParameterLessThan() { + let parameter = getParameter(.ebc(condition: .less, value: 1.2)) + XCTAssert(parameter.key == "ebc_lt") + XCTAssert(1 == parameter.value as? Int) + } + + func testBeerNameParameter() { + let parameter = getParameter(.beerName(value: "PunkIPA")) + XCTAssert(parameter.key == "beer_name") + XCTAssert("PunkIPA" == parameter.value as? String) + } + + func testBeerNameParameterWithSpace() { + let parameter = getParameter(.beerName(value: "Punk IPA")) + XCTAssert(parameter.key == "beer_name") + XCTAssert("Punk_IPA" == parameter.value as? String) + } + + func testYeastParameter() { + let parameter = getParameter(.yeast(value: "AmericanAle")) + XCTAssert(parameter.key == "yeast") + XCTAssert("AmericanAle" == parameter.value as? String) + } + + func testYeastParameterWithSpace() { + let parameter = getParameter(.yeast(value: "American Ale")) + XCTAssert(parameter.key == "yeast") + XCTAssert("American_Ale" == parameter.value as? String) + } + + func testBrewedParameterBefore() { + let parameter = getParameter(.brewed(condition: .less, value: Date(timeIntervalSinceReferenceDate: 5184000))) + XCTAssert(parameter.key == "brewed_before") + XCTAssert("03-2001" == parameter.value as? String) + } + + func testBrewedParameterAfter() { + let parameter = getParameter(.brewed(condition: .more, value: Date(timeIntervalSinceReferenceDate: 2592000))) + XCTAssert(parameter.key == "brewed_after") + XCTAssert("01-2001" == parameter.value as? String) + } + + func testHopsParameter() { + let parameter = getParameter(.hops(value: "Ahtanum")) + XCTAssert(parameter.key == "hops") + XCTAssert("Ahtanum" == parameter.value as? String) + } + + func testHopsParameterWithSpace() { + let parameter = getParameter(.hops(value: "Chi nook")) + XCTAssert(parameter.key == "hops") + XCTAssert("Chi_nook" == parameter.value as? String) + } + + func testFoodParameter() { + let parameter = getParameter(.food(value: "Cheesecake")) + XCTAssert(parameter.key == "food") + XCTAssert("Cheesecake" == parameter.value as? String) + } + + func testFoodParameterWithSpace() { + let parameter = getParameter(.food(value: "Spicy carne")) + XCTAssert(parameter.key == "food") + XCTAssert("Spicy_carne" == parameter.value as? String) + } + + func testIdsParameterSingle() { + let parameter = getParameter(.ids(value: [34])) + XCTAssert(parameter.key == "ids") + XCTAssert("34" == parameter.value as? String) + } + + func testIdsParameterMultiple() { + let parameter = getParameter(.ids(value: [34, 5, 21, 9])) + XCTAssert(parameter.key == "ids") + XCTAssert("34|5|21|9" == parameter.value as? String) + } + + private func getParameter(_ requestParameter: BeersRequest.Parameter) -> RequestParameter { + return requestParameter.parameter + } +} diff --git a/PunkAPI/Classes/Request/Parameter/DateParameter.swift b/PunkAPI/Classes/Request/Parameter/DateParameter.swift index 302830b..d6c8f74 100644 --- a/PunkAPI/Classes/Request/Parameter/DateParameter.swift +++ b/PunkAPI/Classes/Request/Parameter/DateParameter.swift @@ -11,7 +11,8 @@ struct DateParameter: RequestParameter { static var formatter: DateFormatter = { let formatter = DateFormatter() - formatter.dateFormat = "mm-yyyy" + formatter.locale = Locale.current + formatter.dateFormat = "MM-yyyy" return formatter }() From d449fcb95b11a851f867ff81a21ef20569f3ba64 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sat, 2 Mar 2019 23:01:55 +0100 Subject: [PATCH 34/37] chore: rename BeersRequestTests as BeersRequestParametersTests --- Example/PunkAPI.xcodeproj/project.pbxproj | 12 +- .../Tests/BeersRequestParametersTests.swift | 125 +++++++++++++++++ Example/Tests/BeersRequestTests.swift | 128 ++++-------------- 3 files changed, 159 insertions(+), 106 deletions(-) create mode 100644 Example/Tests/BeersRequestParametersTests.swift diff --git a/Example/PunkAPI.xcodeproj/project.pbxproj b/Example/PunkAPI.xcodeproj/project.pbxproj index 9634009..2739cca 100644 --- a/Example/PunkAPI.xcodeproj/project.pbxproj +++ b/Example/PunkAPI.xcodeproj/project.pbxproj @@ -13,13 +13,14 @@ 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; + 9761024E222B328F00C3BD6B /* BeersRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9761024D222B328F00C3BD6B /* BeersRequestTests.swift */; }; 9767CBF7221993F900E684C4 /* BeerParsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF6221993F800E684C4 /* BeerParsingTests.swift */; }; 9767CBFA2219958F00E684C4 /* BeerStubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CBF82219958800E684C4 /* BeerStubs.swift */; }; 9767CC092222B63700E684C4 /* URLBuildTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC072222B60F00E684C4 /* URLBuildTests.swift */; }; 9767CC0B2222BB1E00E684C4 /* MockSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC0A2222BB1E00E684C4 /* MockSession.swift */; }; 9767CC0D2222BDD000E684C4 /* BeerRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC0C2222BDD000E684C4 /* BeerRequestTests.swift */; }; 9767CC0F2223550E00E684C4 /* ConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC0E2223550E00E684C4 /* ConfigurationTests.swift */; }; - 9767CC27222B299300E684C4 /* BeersRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC25222B286F00E684C4 /* BeersRequestTests.swift */; }; + 9767CC27222B299300E684C4 /* BeersRequestParametersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC25222B286F00E684C4 /* BeersRequestParametersTests.swift */; }; EBB1B4D6901624C6A90359CA /* Pods_PunkAPI_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46341D8F014E1940E53D4F02 /* Pods_PunkAPI_Tests.framework */; }; /* End PBXBuildFile section */ @@ -48,13 +49,14 @@ 607FACE51AFB9204008FA782 /* PunkAPI_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PunkAPI_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 613B14F018C28CF1557EC3D5 /* Pods-PunkAPI_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.debug.xcconfig"; sourceTree = ""; }; + 9761024D222B328F00C3BD6B /* BeersRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeersRequestTests.swift; sourceTree = ""; }; 9767CBF6221993F800E684C4 /* BeerParsingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerParsingTests.swift; sourceTree = ""; }; 9767CBF82219958800E684C4 /* BeerStubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerStubs.swift; sourceTree = ""; }; 9767CC072222B60F00E684C4 /* URLBuildTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBuildTests.swift; sourceTree = ""; }; 9767CC0A2222BB1E00E684C4 /* MockSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSession.swift; sourceTree = ""; }; 9767CC0C2222BDD000E684C4 /* BeerRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeerRequestTests.swift; sourceTree = ""; }; 9767CC0E2223550E00E684C4 /* ConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationTests.swift; sourceTree = ""; }; - 9767CC25222B286F00E684C4 /* BeersRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeersRequestTests.swift; sourceTree = ""; }; + 9767CC25222B286F00E684C4 /* BeersRequestParametersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeersRequestParametersTests.swift; sourceTree = ""; }; 9A440A355337DF96D159D208 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; A4CA42C1E1AE14F816574722 /* Pods-PunkAPI_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.debug.xcconfig"; sourceTree = ""; }; E294694CD6DD5DA5A6B471F1 /* Pods-PunkAPI_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PunkAPI_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.release.xcconfig"; sourceTree = ""; }; @@ -186,7 +188,8 @@ children = ( 9767CC072222B60F00E684C4 /* URLBuildTests.swift */, 9767CC0C2222BDD000E684C4 /* BeerRequestTests.swift */, - 9767CC25222B286F00E684C4 /* BeersRequestTests.swift */, + 9761024D222B328F00C3BD6B /* BeersRequestTests.swift */, + 9767CC25222B286F00E684C4 /* BeersRequestParametersTests.swift */, 9767CC0A2222BB1E00E684C4 /* MockSession.swift */, 9767CC0E2223550E00E684C4 /* ConfigurationTests.swift */, ); @@ -416,12 +419,13 @@ buildActionMask = 2147483647; files = ( 9767CC0D2222BDD000E684C4 /* BeerRequestTests.swift in Sources */, - 9767CC27222B299300E684C4 /* BeersRequestTests.swift in Sources */, + 9767CC27222B299300E684C4 /* BeersRequestParametersTests.swift in Sources */, 9767CBF7221993F900E684C4 /* BeerParsingTests.swift in Sources */, 9767CC0F2223550E00E684C4 /* ConfigurationTests.swift in Sources */, 9767CBFA2219958F00E684C4 /* BeerStubs.swift in Sources */, 9767CC0B2222BB1E00E684C4 /* MockSession.swift in Sources */, 9767CC092222B63700E684C4 /* URLBuildTests.swift in Sources */, + 9761024E222B328F00C3BD6B /* BeersRequestTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example/Tests/BeersRequestParametersTests.swift b/Example/Tests/BeersRequestParametersTests.swift new file mode 100644 index 0000000..e9b0b5d --- /dev/null +++ b/Example/Tests/BeersRequestParametersTests.swift @@ -0,0 +1,125 @@ +// +// BeersRequestTests.swift +// PunkAPI_Example +// +// Created by Andrea Altea on 02/03/2019. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import XCTest +@testable import PunkAPI + +class BeersRequestTest: XCTestCase { + + func testABVParameterGreater() { + let parameter = getParameter(.abv(condition: .more, value: 1.2)) + XCTAssert(parameter.key == "abv_gt") + XCTAssert(1 == parameter.value as? Int) + } + + func testABVParameterLessThan() { + let parameter = getParameter(.abv(condition: .less, value: 1.2)) + XCTAssert(parameter.key == "abv_lt") + XCTAssert(1 == parameter.value as? Int) + } + + func testIBUParameterGreater() { + let parameter = getParameter(.ibu(condition: .more, value: 1.2)) + XCTAssert(parameter.key == "ibu_gt") + XCTAssert(1 == parameter.value as? Int) + } + + func testIBUParameterLessThan() { + let parameter = getParameter(.ibu(condition: .less, value: 1.2)) + XCTAssert(parameter.key == "ibu_lt") + XCTAssert(1 == parameter.value as? Int) + } + + func testEBCParameterGreater() { + let parameter = getParameter(.ebc(condition: .more, value: 1.2)) + XCTAssert(parameter.key == "ebc_gt") + XCTAssert(1 == parameter.value as? Int) + } + + func testEBCParameterLessThan() { + let parameter = getParameter(.ebc(condition: .less, value: 1.2)) + XCTAssert(parameter.key == "ebc_lt") + XCTAssert(1 == parameter.value as? Int) + } + + func testBeerNameParameter() { + let parameter = getParameter(.beerName(value: "PunkIPA")) + XCTAssert(parameter.key == "beer_name") + XCTAssert("PunkIPA" == parameter.value as? String) + } + + func testBeerNameParameterWithSpace() { + let parameter = getParameter(.beerName(value: "Punk IPA")) + XCTAssert(parameter.key == "beer_name") + XCTAssert("Punk_IPA" == parameter.value as? String) + } + + func testYeastParameter() { + let parameter = getParameter(.yeast(value: "AmericanAle")) + XCTAssert(parameter.key == "yeast") + XCTAssert("AmericanAle" == parameter.value as? String) + } + + func testYeastParameterWithSpace() { + let parameter = getParameter(.yeast(value: "American Ale")) + XCTAssert(parameter.key == "yeast") + XCTAssert("American_Ale" == parameter.value as? String) + } + + func testBrewedParameterBefore() { + let parameter = getParameter(.brewed(condition: .less, value: Date(timeIntervalSinceReferenceDate: 5184000))) + XCTAssert(parameter.key == "brewed_before") + XCTAssert("03-2001" == parameter.value as? String) + } + + func testBrewedParameterAfter() { + let parameter = getParameter(.brewed(condition: .more, value: Date(timeIntervalSinceReferenceDate: 2592000))) + XCTAssert(parameter.key == "brewed_after") + XCTAssert("01-2001" == parameter.value as? String) + } + + func testHopsParameter() { + let parameter = getParameter(.hops(value: "Ahtanum")) + XCTAssert(parameter.key == "hops") + XCTAssert("Ahtanum" == parameter.value as? String) + } + + func testHopsParameterWithSpace() { + let parameter = getParameter(.hops(value: "Chi nook")) + XCTAssert(parameter.key == "hops") + XCTAssert("Chi_nook" == parameter.value as? String) + } + + func testFoodParameter() { + let parameter = getParameter(.food(value: "Cheesecake")) + XCTAssert(parameter.key == "food") + XCTAssert("Cheesecake" == parameter.value as? String) + } + + func testFoodParameterWithSpace() { + let parameter = getParameter(.food(value: "Spicy carne")) + XCTAssert(parameter.key == "food") + XCTAssert("Spicy_carne" == parameter.value as? String) + } + + func testIdsParameterSingle() { + let parameter = getParameter(.ids(value: [34])) + XCTAssert(parameter.key == "ids") + XCTAssert("34" == parameter.value as? String) + } + + func testIdsParameterMultiple() { + let parameter = getParameter(.ids(value: [34, 5, 21, 9])) + XCTAssert(parameter.key == "ids") + XCTAssert("34|5|21|9" == parameter.value as? String) + } + + private func getParameter(_ requestParameter: BeersRequest.Parameter) -> RequestParameter { + return requestParameter.parameter + } +} diff --git a/Example/Tests/BeersRequestTests.swift b/Example/Tests/BeersRequestTests.swift index e9b0b5d..3c89e4f 100644 --- a/Example/Tests/BeersRequestTests.swift +++ b/Example/Tests/BeersRequestTests.swift @@ -1,6 +1,6 @@ // // BeersRequestTests.swift -// PunkAPI_Example +// PunkAPI_Tests // // Created by Andrea Altea on 02/03/2019. // Copyright © 2019 CocoaPods. All rights reserved. @@ -9,117 +9,41 @@ import XCTest @testable import PunkAPI -class BeersRequestTest: XCTestCase { - - func testABVParameterGreater() { - let parameter = getParameter(.abv(condition: .more, value: 1.2)) - XCTAssert(parameter.key == "abv_gt") - XCTAssert(1 == parameter.value as? Int) - } - - func testABVParameterLessThan() { - let parameter = getParameter(.abv(condition: .less, value: 1.2)) - XCTAssert(parameter.key == "abv_lt") - XCTAssert(1 == parameter.value as? Int) - } - - func testIBUParameterGreater() { - let parameter = getParameter(.ibu(condition: .more, value: 1.2)) - XCTAssert(parameter.key == "ibu_gt") - XCTAssert(1 == parameter.value as? Int) - } - - func testIBUParameterLessThan() { - let parameter = getParameter(.ibu(condition: .less, value: 1.2)) - XCTAssert(parameter.key == "ibu_lt") - XCTAssert(1 == parameter.value as? Int) - } - - func testEBCParameterGreater() { - let parameter = getParameter(.ebc(condition: .more, value: 1.2)) - XCTAssert(parameter.key == "ebc_gt") - XCTAssert(1 == parameter.value as? Int) - } - - func testEBCParameterLessThan() { - let parameter = getParameter(.ebc(condition: .less, value: 1.2)) - XCTAssert(parameter.key == "ebc_lt") - XCTAssert(1 == parameter.value as? Int) - } - - func testBeerNameParameter() { - let parameter = getParameter(.beerName(value: "PunkIPA")) - XCTAssert(parameter.key == "beer_name") - XCTAssert("PunkIPA" == parameter.value as? String) - } +class BeersRequestTests: XCTestCase { - func testBeerNameParameterWithSpace() { - let parameter = getParameter(.beerName(value: "Punk IPA")) - XCTAssert(parameter.key == "beer_name") - XCTAssert("Punk_IPA" == parameter.value as? String) + override func setUp() { + // Put setup code here. This method is called before the invocation of each test method in the class. } - func testYeastParameter() { - let parameter = getParameter(.yeast(value: "AmericanAle")) - XCTAssert(parameter.key == "yeast") - XCTAssert("AmericanAle" == parameter.value as? String) - } - - func testYeastParameterWithSpace() { - let parameter = getParameter(.yeast(value: "American Ale")) - XCTAssert(parameter.key == "yeast") - XCTAssert("American_Ale" == parameter.value as? String) + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. } - func testBrewedParameterBefore() { - let parameter = getParameter(.brewed(condition: .less, value: Date(timeIntervalSinceReferenceDate: 5184000))) - XCTAssert(parameter.key == "brewed_before") - XCTAssert("03-2001" == parameter.value as? String) + func testSingleParameter() { + let request = BeersRequest(filter: [.abv(condition: .more, value: 34)]) + XCTAssert(request.path == "beers") + XCTAssert(1 == request.parameters?.count) + XCTAssert(34 == request.parameters?["abv_gt"] as? Int) } - func testBrewedParameterAfter() { - let parameter = getParameter(.brewed(condition: .more, value: Date(timeIntervalSinceReferenceDate: 2592000))) - XCTAssert(parameter.key == "brewed_after") - XCTAssert("01-2001" == parameter.value as? String) - } - - func testHopsParameter() { - let parameter = getParameter(.hops(value: "Ahtanum")) - XCTAssert(parameter.key == "hops") - XCTAssert("Ahtanum" == parameter.value as? String) + func testPageParameter() { + let request = BeersRequest(page: 1) + XCTAssert(request.path == "beers") + XCTAssert(1 == request.parameters?.count) + XCTAssert(1 == request.parameters?["page"] as? Int) } - func testHopsParameterWithSpace() { - let parameter = getParameter(.hops(value: "Chi nook")) - XCTAssert(parameter.key == "hops") - XCTAssert("Chi_nook" == parameter.value as? String) - } - - func testFoodParameter() { - let parameter = getParameter(.food(value: "Cheesecake")) - XCTAssert(parameter.key == "food") - XCTAssert("Cheesecake" == parameter.value as? String) + func testInvalidPageParameter() { + let request = BeersRequest(page: 0) + XCTAssert(request.path == "beers") + XCTAssert(request.parameters == nil) } - func testFoodParameterWithSpace() { - let parameter = getParameter(.food(value: "Spicy carne")) - XCTAssert(parameter.key == "food") - XCTAssert("Spicy_carne" == parameter.value as? String) - } - - func testIdsParameterSingle() { - let parameter = getParameter(.ids(value: [34])) - XCTAssert(parameter.key == "ids") - XCTAssert("34" == parameter.value as? String) - } - - func testIdsParameterMultiple() { - let parameter = getParameter(.ids(value: [34, 5, 21, 9])) - XCTAssert(parameter.key == "ids") - XCTAssert("34|5|21|9" == parameter.value as? String) - } - - private func getParameter(_ requestParameter: BeersRequest.Parameter) -> RequestParameter { - return requestParameter.parameter + func testPageWithSingleParameter() { + let request = BeersRequest(filter: [.abv(condition: .more, value: 34)], page: 1) + XCTAssert(request.path == "beers") + XCTAssert(2 == request.parameters?.count) + XCTAssert(1 == request.parameters?["page"] as? Int) + XCTAssert(34 == request.parameters?["abv_gt"] as? Int) } } From 08d224a9fc1f8df847fe6fbdfd7b8307de79287a Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sat, 2 Mar 2019 23:02:07 +0100 Subject: [PATCH 35/37] Feat: add BeersRequest tests --- Example/Tests/BeersRequestParametersTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Example/Tests/BeersRequestParametersTests.swift b/Example/Tests/BeersRequestParametersTests.swift index e9b0b5d..4e3949d 100644 --- a/Example/Tests/BeersRequestParametersTests.swift +++ b/Example/Tests/BeersRequestParametersTests.swift @@ -9,7 +9,7 @@ import XCTest @testable import PunkAPI -class BeersRequestTest: XCTestCase { +class BeersRequestParametersTests: XCTestCase { func testABVParameterGreater() { let parameter = getParameter(.abv(condition: .more, value: 1.2)) From f47f14d13e6baae3d2f63be8f224af7b14f5b1d3 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sun, 3 Mar 2019 09:36:42 +0100 Subject: [PATCH 36/37] feat: Prepare pod for release --- Example/Podfile.lock | 2 +- .../Pods/Local Podspecs/PunkAPI.podspec.json | 1 + Example/Pods/Manifest.lock | 2 +- Example/Pods/Pods.xcodeproj/project.pbxproj | 551 +++++++++--------- Example/PunkAPI.xcodeproj/project.pbxproj | 2 + PunkAPI.podspec | 3 +- .../Classes/Results}/Errors.swift | 0 .../Classes/Results}/Result.swift | 0 8 files changed, 287 insertions(+), 274 deletions(-) rename {Results => PunkAPI/Classes/Results}/Errors.swift (100%) rename {Results => PunkAPI/Classes/Results}/Result.swift (100%) diff --git a/Example/Podfile.lock b/Example/Podfile.lock index dfeada2..cf454a6 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -9,7 +9,7 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - PunkAPI: 3604e01855fc2f1e591d704f2728e7e2cbce27ad + PunkAPI: c9891a38a2efa7a052f02d02decceb58ca87b5ed PODFILE CHECKSUM: 77a7edfbda92bc42f026175f2a4105df175a2c99 diff --git a/Example/Pods/Local Podspecs/PunkAPI.podspec.json b/Example/Pods/Local Podspecs/PunkAPI.podspec.json index 73a02ef..a076944 100644 --- a/Example/Pods/Local Podspecs/PunkAPI.podspec.json +++ b/Example/Pods/Local Podspecs/PunkAPI.podspec.json @@ -2,6 +2,7 @@ "name": "PunkAPI", "version": "0.1.0", "summary": "A little swift wrapper for PunkAPI by @samjbmason", + "swift_version": "4.2", "description": "\"Have you ever wanted to search through Brewdog's expansive back catalogue of beer in a programmatic way? Maybe build a tool that pairs beer with food, or search beers with an abv of more than 4%? Well now your prayers have been answered!\"", "homepage": "https://github.com/Oni-zerone/PunkAPI", "license": { diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock index dfeada2..cf454a6 100644 --- a/Example/Pods/Manifest.lock +++ b/Example/Pods/Manifest.lock @@ -9,7 +9,7 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - PunkAPI: 3604e01855fc2f1e591d704f2728e7e2cbce27ad + PunkAPI: c9891a38a2efa7a052f02d02decceb58ca87b5ed PODFILE CHECKSUM: 77a7edfbda92bc42f026175f2a4105df175a2c99 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 7b27a13..1f6f8ef 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -7,33 +7,33 @@ objects = { /* Begin PBXBuildFile section */ + 040633ED2DA398496AD631E73B9CB953 /* Beer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C6F916B3844F173B183C5BC45E825DC /* Beer.swift */; }; + 0706F758C5F2CE0E83E44396DE53B472 /* StringParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D332B9F96F752E235840BDE2286619A5 /* StringParameter.swift */; }; + 0C4C6C5EED9509237E097606FBBF2046 /* BeerRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6968BCE43B140E358870F66D7258F957 /* BeerRequest.swift */; }; + 156976A157354FAC4A76CDD07C60C630 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2718DFE97DA930B98881C184088EFA6B /* Errors.swift */; }; 1DEF7BF616CC3F2EF46A7F9E5514F9AC /* Pods-PunkAPI_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E9F6D3BEDEF11CDF5DC7C24AEF5989 /* Pods-PunkAPI_Tests-dummy.m */; }; - 3AF70E263893077BB94A1C3F36DCC044 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49FB5023B50B37DFC2215303164C7685 /* Errors.swift */; }; + 1F269E313E3E5E6D95C7EA4117A4EF52 /* RequestParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E73CF54C263C0540BBD135CCBAE448F9 /* RequestParameter.swift */; }; + 4C4AB5D20013C59D1BE1A0DC0AA4A90E /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67F5B1D8A153F21971D389D7D78E3709 /* Request.swift */; }; 4DE6F5415AA32E45E1A1B40AA8194B63 /* Pods-PunkAPI_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E322AC54183F0711E107C333BF42C3CF /* Pods-PunkAPI_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4F478C6F6571A694E377026C7020B987 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */; }; 5563E1330468FB6D76F769A6697DF682 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */; }; - 5ABF50E02687C014E47088344889FC06 /* Beer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 541ACAD8BAF53EB42A722470D92D1723 /* Beer.swift */; }; - 6017B5D2AAB067785D0E2EE754D97A17 /* Recipe.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE9253651B7E158F09FC4029478AD23A /* Recipe.swift */; }; - 80B5BF4A54A873CBBDE11FD50E93473F /* BeerRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 494668F6F12367A934530175780F1FB4 /* BeerRequest.swift */; }; + 567123199E19D2AF982C095A91F499E3 /* PunkAPI-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = AF457128C49817820875EFC37DDC2763 /* PunkAPI-dummy.m */; }; + 58196BD46A6A962CD2291747E891A4FF /* Recipe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FEECE1958551B13C700A5127274F0A0 /* Recipe.swift */; }; 861F0ED5029160D63BEA52EEDC4F5B2D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */; }; - 89899DFDA224AF6393CF9985FF2AE13E /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = F184F71C3E715F7CB4001C228E19BEBB /* Request.swift */; }; - 8CA330EBFA4F61AE26881286B24648A7 /* Method.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FCD590B492E88AEC8C08B25E45BCFA7 /* Method.swift */; }; - 90001FCA9653A9974B648EAF681F4DD4 /* PunkAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = A96C503FD3BF058AD217F43E4A5954BB /* PunkAPI.swift */; }; - 94ACB62152B83DE972430EAA4B24D449 /* PunkAPI-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E7002BDD7866D71B1BE5B92068B1D65E /* PunkAPI-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9767CC062222B1BB00E684C4 /* URLBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC052222B1BB00E684C4 /* URLBuilder.swift */; }; - 9767CC112223592A00E684C4 /* RandomBeerRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC102223592A00E684C4 /* RandomBeerRequest.swift */; }; - 9767CC17222AC3F900E684C4 /* BeersRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC16222AC3F900E684C4 /* BeersRequest.swift */; }; - 9767CC19222AC45900E684C4 /* BeersRequestParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */; }; - 9767CC1C222ADDD100E684C4 /* RequestParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC1B222ADDD100E684C4 /* RequestParameter.swift */; }; - 9767CC20222ADE2500E684C4 /* FloatParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC1F222ADE2500E684C4 /* FloatParameter.swift */; }; - 9767CC22222ADE5100E684C4 /* StringParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC21222ADE5100E684C4 /* StringParameter.swift */; }; - 9767CC24222ADE6800E684C4 /* DateParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9767CC23222ADE6800E684C4 /* DateParameter.swift */; }; + 8CA6935D75E79F06DC50B80FBFA04E52 /* BeersRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A36C69522325B64312822D021FE1AA /* BeersRequest.swift */; }; + 94ACB62152B83DE972430EAA4B24D449 /* PunkAPI-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E6E75F5999AC210521146C7375A3313 /* PunkAPI-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9C1115413D21B46B31F5D70FE29CA857 /* Method.swift in Sources */ = {isa = PBXBuildFile; fileRef = 272E2F86C0B64A9624B4C3B045C95054 /* Method.swift */; }; 9DEE51DC320AFD89F8CCE79E659D0E92 /* Pods-PunkAPI_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A1658BA79EB16D586EE25257AD1D8ED6 /* PunkAPI-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = ED357DDF7318810430C08E0AD4316358 /* PunkAPI-dummy.m */; }; - A3F6E06BFFDEF9DAD8325928091F4B00 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BAFF56967C81FF81A5FE0A0F4AC9EFC /* Result.swift */; }; + 9E26D0BC2A8D1AB927AD665EB5032162 /* PunkAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5EF39F3AF34782AC8545A51C195DF61 /* PunkAPI.swift */; }; + 9EB5A8CE4227261D6FDB84878505ACED /* RandomBeerRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCA6949E012F3A32EE618525D6C1C918 /* RandomBeerRequest.swift */; }; + 9F91EF3525A1E94F87950035B1DEF148 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06A91CE54D5004C034494C163FD6F954 /* Result.swift */; }; + A2A4C282870BFE912F85DB1151BC24B3 /* DateParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E53AB03421ECCCAC36BA6463E532AF2D /* DateParameter.swift */; }; + AA5C8E19C31A6A5CDAD11062F1625806 /* URLBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F1A67AAC30418B7829B4645C698A64E /* URLBuilder.swift */; }; + ADCB0254782B197A401A2AAC39C0E882 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E63AF47725611B0A82E5D288783A976 /* Configuration.swift */; }; B0D852DC953C7A0E2C1CB872F9E315BB /* Pods-PunkAPI_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */; }; - C0BB3FEC5BB8EF2E7C42FD464D459623 /* Quantity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A9D4151E2B98C6AEE60102C96A95D43 /* Quantity.swift */; }; - D8CFB7B7D1AAC97CCB20D1DD5C56FB9B /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD1936865DE99565E7C6A3CA8A62046 /* Configuration.swift */; }; + BBCC787A76C3C536D049EB6E228394FF /* Quantity.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0640B723338BC89B5BF58530FC5A3D0 /* Quantity.swift */; }; + EA2895A6DC98FCFBB5A54F5837E8304F /* FloatParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EB937A449C35D61D642784A44C83FF1 /* FloatParameter.swift */; }; + FAEC0D53EBA4A5BCFCDA4CB97EA975AA /* BeersRequestParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52B3CD426204500053E942213EDD6A6 /* BeersRequestParameter.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -54,58 +54,58 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 06A91CE54D5004C034494C163FD6F954 /* Result.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = ""; }; 06BAF05CBDEA8E295E4784A5A5D4506C /* Pods-PunkAPI_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PunkAPI_Tests-acknowledgements.plist"; sourceTree = ""; }; + 073D13EDB6E52C7CA76600719DF8FCCA /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 08865B1A9072612C58080056C52A36BE /* Pods-PunkAPI_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Example.modulemap"; sourceTree = ""; }; - 1A9D4151E2B98C6AEE60102C96A95D43 /* Quantity.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Quantity.swift; sourceTree = ""; }; - 1AE9EEDB05092385E557ED3979AAEBC1 /* PunkAPI.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PunkAPI.xcconfig; sourceTree = ""; }; - 1BAFF56967C81FF81A5FE0A0F4AC9EFC /* Result.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = ""; }; - 2B6E62A798BEE3FE5AE9D84C877FD756 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0C6F916B3844F173B183C5BC45E825DC /* Beer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Beer.swift; sourceTree = ""; }; + 16EF8876C605E8EC561718EF37E64EF9 /* PunkAPI-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PunkAPI-prefix.pch"; sourceTree = ""; }; + 1E8F3184E27473ACF2CB0ECC931D49B9 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; + 2718DFE97DA930B98881C184088EFA6B /* Errors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; }; + 272E2F86C0B64A9624B4C3B045C95054 /* Method.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Method.swift; sourceTree = ""; }; 2EC29BADC6D4B129C97F077B8D1AAD24 /* Pods-PunkAPI_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Example-frameworks.sh"; sourceTree = ""; }; 34E9F6D3BEDEF11CDF5DC7C24AEF5989 /* Pods-PunkAPI_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Tests-dummy.m"; sourceTree = ""; }; - 3CA7DD0E0D9E3D052F0DA83C7B3B79FC /* Pods_PunkAPI_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 3DD1936865DE99565E7C6A3CA8A62046 /* Configuration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Configuration.swift; path = PunkAPI/Classes/Configuration.swift; sourceTree = ""; }; - 3F4208A029892D178EE8F5C95D6D79EB /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; - 3FCD590B492E88AEC8C08B25E45BCFA7 /* Method.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Method.swift; sourceTree = ""; }; + 3CA7DD0E0D9E3D052F0DA83C7B3B79FC /* Pods_PunkAPI_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PunkAPI_Tests.framework; path = "Pods-PunkAPI_Tests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3EB937A449C35D61D642784A44C83FF1 /* FloatParameter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FloatParameter.swift; sourceTree = ""; }; 492C127C07A0D9D778B3D645FCDED6AC /* Pods-PunkAPI_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Tests.release.xcconfig"; sourceTree = ""; }; - 494668F6F12367A934530175780F1FB4 /* BeerRequest.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BeerRequest.swift; sourceTree = ""; }; - 49FB5023B50B37DFC2215303164C7685 /* Errors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; }; - 541ACAD8BAF53EB42A722470D92D1723 /* Beer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Beer.swift; sourceTree = ""; }; - 54767361581B8332A2D7629F5E98048E /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; + 4F1A67AAC30418B7829B4645C698A64E /* URLBuilder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = URLBuilder.swift; sourceTree = ""; }; + 5E6E75F5999AC210521146C7375A3313 /* PunkAPI-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PunkAPI-umbrella.h"; sourceTree = ""; }; + 5FEECE1958551B13C700A5127274F0A0 /* Recipe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Recipe.swift; sourceTree = ""; }; 608E9332AF8468043B49B03317025805 /* Pods-PunkAPI_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Tests-frameworks.sh"; sourceTree = ""; }; + 67A36C69522325B64312822D021FE1AA /* BeersRequest.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BeersRequest.swift; sourceTree = ""; }; + 67F5B1D8A153F21971D389D7D78E3709 /* Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = ""; }; + 6968BCE43B140E358870F66D7258F957 /* BeerRequest.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BeerRequest.swift; sourceTree = ""; }; 6ABEAC72915A583BE08AF19F226F5157 /* Pods-PunkAPI_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PunkAPI_Example-umbrella.h"; sourceTree = ""; }; 6EDD1194CE9C142C26AD6C6803C306E4 /* Pods-PunkAPI_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Tests.debug.xcconfig"; sourceTree = ""; }; 7F7764549D1799C2D5D6A7B2D65E3550 /* Pods-PunkAPI_Example-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Example-resources.sh"; sourceTree = ""; }; 8342B62283B06E1CA90A14E1BCB6D62B /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 8458C84A594F726E1A8DB6294F78DB73 /* Pods-PunkAPI_Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PunkAPI_Tests-resources.sh"; sourceTree = ""; }; - 864A4FE64365AC74BB9E53A4618E5F55 /* PunkAPI.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; path = PunkAPI.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 92229C81AD3A318707A49C8449AEB2F5 /* Pods-PunkAPI_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PunkAPI_Example-acknowledgements.plist"; sourceTree = ""; }; - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 9767CC052222B1BB00E684C4 /* URLBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBuilder.swift; sourceTree = ""; }; - 9767CC102223592A00E684C4 /* RandomBeerRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RandomBeerRequest.swift; sourceTree = ""; }; - 9767CC16222AC3F900E684C4 /* BeersRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeersRequest.swift; sourceTree = ""; }; - 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeersRequestParameter.swift; sourceTree = ""; }; - 9767CC1B222ADDD100E684C4 /* RequestParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestParameter.swift; sourceTree = ""; }; - 9767CC1F222ADE2500E684C4 /* FloatParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatParameter.swift; sourceTree = ""; }; - 9767CC21222ADE5100E684C4 /* StringParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringParameter.swift; sourceTree = ""; }; - 9767CC23222ADE6800E684C4 /* DateParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateParameter.swift; sourceTree = ""; }; + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9A4A66A2F2CD393AE19E9C41284E7A10 /* PunkAPI.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; path = PunkAPI.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 9D14926C4AE138B3C55CE27E18BE194D /* Pods-PunkAPI_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PunkAPI_Tests.modulemap"; sourceTree = ""; }; - 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PunkAPI_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PunkAPI_Example.framework; path = "Pods-PunkAPI_Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 9E63AF47725611B0A82E5D288783A976 /* Configuration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Configuration.swift; path = PunkAPI/Classes/Configuration.swift; sourceTree = ""; }; A4E9F26077D1238C6BF679ED6AB0504D /* Pods-PunkAPI_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PunkAPI_Example-dummy.m"; sourceTree = ""; }; + A52B3CD426204500053E942213EDD6A6 /* BeersRequestParameter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BeersRequestParameter.swift; sourceTree = ""; }; A5D146483FC9684CF2C15F85C081EF35 /* Pods-PunkAPI_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Example.release.xcconfig"; sourceTree = ""; }; - A96C503FD3BF058AD217F43E4A5954BB /* PunkAPI.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PunkAPI.swift; path = PunkAPI/Classes/PunkAPI.swift; sourceTree = ""; }; - CE9253651B7E158F09FC4029478AD23A /* Recipe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Recipe.swift; sourceTree = ""; }; - CFBB1E2E92ABC5FA4F246BD9E188EBB3 /* PunkAPI.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = PunkAPI.modulemap; sourceTree = ""; }; + AF457128C49817820875EFC37DDC2763 /* PunkAPI-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PunkAPI-dummy.m"; sourceTree = ""; }; + C0640B723338BC89B5BF58530FC5A3D0 /* Quantity.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Quantity.swift; sourceTree = ""; }; + D332B9F96F752E235840BDE2286619A5 /* StringParameter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StringParameter.swift; sourceTree = ""; }; + D5EF39F3AF34782AC8545A51C195DF61 /* PunkAPI.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PunkAPI.swift; path = PunkAPI/Classes/PunkAPI.swift; sourceTree = ""; }; D6DFF15000AFE2A371BF499E7AFDA808 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + DEC567BAB5C34B4B7667B6C1478CE2DA /* PunkAPI.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = PunkAPI.modulemap; sourceTree = ""; }; E322AC54183F0711E107C333BF42C3CF /* Pods-PunkAPI_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PunkAPI_Tests-umbrella.h"; sourceTree = ""; }; - E7002BDD7866D71B1BE5B92068B1D65E /* PunkAPI-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PunkAPI-umbrella.h"; sourceTree = ""; }; + E53AB03421ECCCAC36BA6463E532AF2D /* DateParameter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DateParameter.swift; sourceTree = ""; }; E722B264627A535D845CCF418E225784 /* Pods-PunkAPI_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PunkAPI_Tests-acknowledgements.markdown"; sourceTree = ""; }; + E73CF54C263C0540BBD135CCBAE448F9 /* RequestParameter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = RequestParameter.swift; sourceTree = ""; }; E816F7DA6C1CBE532E1590E0F05B9532 /* Pods-PunkAPI_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PunkAPI_Example.debug.xcconfig"; sourceTree = ""; }; EAE741F8D3D7DED0544AD07D421892ED /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - ED0E564BBBF9D91E8AA8F76C0E47F9C9 /* PunkAPI-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PunkAPI-prefix.pch"; sourceTree = ""; }; - ED357DDF7318810430C08E0AD4316358 /* PunkAPI-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PunkAPI-dummy.m"; sourceTree = ""; }; - F184F71C3E715F7CB4001C228E19BEBB /* Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = ""; }; - FA66D5ED6E33AA7DD32A8C962841F3B0 /* PunkAPI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PunkAPI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F5FCAD7EA85132D2D8D1388DA3081592 /* PunkAPI.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PunkAPI.xcconfig; sourceTree = ""; }; + FA66D5ED6E33AA7DD32A8C962841F3B0 /* PunkAPI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = PunkAPI.framework; path = PunkAPI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FAD9273D9A1D66770D45A643EDA9E88E /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; FB1D3C212D7A0519F22CF554E249675E /* Pods-PunkAPI_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PunkAPI_Example-acknowledgements.markdown"; sourceTree = ""; }; + FCA6949E012F3A32EE618525D6C1C918 /* RandomBeerRequest.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = RandomBeerRequest.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -136,10 +136,44 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 0514815A5F57F1358DA701F5C9BCA5D2 /* Results */ = { + isa = PBXGroup; + children = ( + 2718DFE97DA930B98881C184088EFA6B /* Errors.swift */, + 06A91CE54D5004C034494C163FD6F954 /* Result.swift */, + ); + name = Results; + path = PunkAPI/Classes/Results; + sourceTree = ""; + }; + 090992C0DECBC3153B28556E0B42A41B /* Request */ = { + isa = PBXGroup; + children = ( + 6968BCE43B140E358870F66D7258F957 /* BeerRequest.swift */, + 67A36C69522325B64312822D021FE1AA /* BeersRequest.swift */, + FCA6949E012F3A32EE618525D6C1C918 /* RandomBeerRequest.swift */, + 67F5B1D8A153F21971D389D7D78E3709 /* Request.swift */, + 4F1A67AAC30418B7829B4645C698A64E /* URLBuilder.swift */, + 64A82D6E12F29B9C311952C99CAAF80D /* Parameter */, + ); + name = Request; + path = PunkAPI/Classes/Request; + sourceTree = ""; + }; + 1EAE5A66A94268C182B75D7DB0BFCB3F /* Pod */ = { + isa = PBXGroup; + children = ( + FAD9273D9A1D66770D45A643EDA9E88E /* LICENSE */, + 9A4A66A2F2CD393AE19E9C41284E7A10 /* PunkAPI.podspec */, + 1E8F3184E27473ACF2CB0ECC931D49B9 /* README.md */, + ); + name = Pod; + sourceTree = ""; + }; 3C48D264DEAC135E647F4628351B96D3 /* Development Pods */ = { isa = PBXGroup; children = ( - B18B6D748213693EB25E110701CCA43E /* PunkAPI */, + F7A6E9EE825581F4F5E91FACA3E20C0F /* PunkAPI */, ); name = "Development Pods"; sourceTree = ""; @@ -161,28 +195,27 @@ name = "Targets Support Files"; sourceTree = ""; }; - 6C92B5E2C39B71B9A3D59EB753CF598A /* Products */ = { + 64A82D6E12F29B9C311952C99CAAF80D /* Parameter */ = { isa = PBXGroup; children = ( - 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */, - 3CA7DD0E0D9E3D052F0DA83C7B3B79FC /* Pods_PunkAPI_Tests.framework */, - FA66D5ED6E33AA7DD32A8C962841F3B0 /* PunkAPI.framework */, + A52B3CD426204500053E942213EDD6A6 /* BeersRequestParameter.swift */, + E53AB03421ECCCAC36BA6463E532AF2D /* DateParameter.swift */, + 3EB937A449C35D61D642784A44C83FF1 /* FloatParameter.swift */, + E73CF54C263C0540BBD135CCBAE448F9 /* RequestParameter.swift */, + D332B9F96F752E235840BDE2286619A5 /* StringParameter.swift */, ); - name = Products; + name = Parameter; + path = Parameter; sourceTree = ""; }; - 6FCCF155F5EBF133E1D6AAA9C42FCD87 /* Support Files */ = { + 6C92B5E2C39B71B9A3D59EB753CF598A /* Products */ = { isa = PBXGroup; children = ( - 2B6E62A798BEE3FE5AE9D84C877FD756 /* Info.plist */, - CFBB1E2E92ABC5FA4F246BD9E188EBB3 /* PunkAPI.modulemap */, - 1AE9EEDB05092385E557ED3979AAEBC1 /* PunkAPI.xcconfig */, - ED357DDF7318810430C08E0AD4316358 /* PunkAPI-dummy.m */, - ED0E564BBBF9D91E8AA8F76C0E47F9C9 /* PunkAPI-prefix.pch */, - E7002BDD7866D71B1BE5B92068B1D65E /* PunkAPI-umbrella.h */, + 9DDE148E1E89B985353411506461E509 /* Pods_PunkAPI_Example.framework */, + 3CA7DD0E0D9E3D052F0DA83C7B3B79FC /* Pods_PunkAPI_Tests.framework */, + FA66D5ED6E33AA7DD32A8C962841F3B0 /* PunkAPI.framework */, ); - name = "Support Files"; - path = "Example/Pods/Target Support Files/PunkAPI"; + name = Products; sourceTree = ""; }; 7DB346D0F39D3F0E887471402A8071AB = { @@ -196,39 +229,18 @@ ); sourceTree = ""; }; - 90DDE1C48D67E6010A82C6341C9BA92D /* Content */ = { + 883B8E4B6F6171944650345EDD78EC6C /* Content */ = { isa = PBXGroup; children = ( - 541ACAD8BAF53EB42A722470D92D1723 /* Beer.swift */, - 3FCD590B492E88AEC8C08B25E45BCFA7 /* Method.swift */, - 1A9D4151E2B98C6AEE60102C96A95D43 /* Quantity.swift */, - CE9253651B7E158F09FC4029478AD23A /* Recipe.swift */, + 0C6F916B3844F173B183C5BC45E825DC /* Beer.swift */, + 272E2F86C0B64A9624B4C3B045C95054 /* Method.swift */, + C0640B723338BC89B5BF58530FC5A3D0 /* Quantity.swift */, + 5FEECE1958551B13C700A5127274F0A0 /* Recipe.swift */, ); name = Content; path = PunkAPI/Classes/Content; sourceTree = ""; }; - 9767CC042222B13000E684C4 /* Results */ = { - isa = PBXGroup; - children = ( - 49FB5023B50B37DFC2215303164C7685 /* Errors.swift */, - 1BAFF56967C81FF81A5FE0A0F4AC9EFC /* Result.swift */, - ); - path = Results; - sourceTree = ""; - }; - 9767CC1A222ADDBB00E684C4 /* Parameter */ = { - isa = PBXGroup; - children = ( - 9767CC1B222ADDD100E684C4 /* RequestParameter.swift */, - 9767CC1F222ADE2500E684C4 /* FloatParameter.swift */, - 9767CC21222ADE5100E684C4 /* StringParameter.swift */, - 9767CC23222ADE6800E684C4 /* DateParameter.swift */, - 9767CC18222AC45900E684C4 /* BeersRequestParameter.swift */, - ); - path = Parameter; - sourceTree = ""; - }; 9BFECB8663CD309F9214B4311C96BCB5 /* Pods-PunkAPI_Example */ = { isa = PBXGroup; children = ( @@ -247,21 +259,6 @@ path = "Target Support Files/Pods-PunkAPI_Example"; sourceTree = ""; }; - B18B6D748213693EB25E110701CCA43E /* PunkAPI */ = { - isa = PBXGroup; - children = ( - 3DD1936865DE99565E7C6A3CA8A62046 /* Configuration.swift */, - A96C503FD3BF058AD217F43E4A5954BB /* PunkAPI.swift */, - EE14703CB73E7B607CA53D2EC58437E4 /* Request */, - 90DDE1C48D67E6010A82C6341C9BA92D /* Content */, - 9767CC042222B13000E684C4 /* Results */, - F3C407FDC658F8445BE7AB2FF5F32CB6 /* Pod */, - 6FCCF155F5EBF133E1D6AAA9C42FCD87 /* Support Files */, - ); - name = PunkAPI; - path = ../..; - sourceTree = ""; - }; B2D5CC793D96E6B1A0442EA2481F7DF2 /* Pods-PunkAPI_Tests */ = { isa = PBXGroup; children = ( @@ -288,28 +285,33 @@ name = Frameworks; sourceTree = ""; }; - EE14703CB73E7B607CA53D2EC58437E4 /* Request */ = { + CB553B8B7B06165B82FCA92BD5137F9D /* Support Files */ = { isa = PBXGroup; children = ( - 9767CC1A222ADDBB00E684C4 /* Parameter */, - F184F71C3E715F7CB4001C228E19BEBB /* Request.swift */, - 494668F6F12367A934530175780F1FB4 /* BeerRequest.swift */, - 9767CC16222AC3F900E684C4 /* BeersRequest.swift */, - 9767CC102223592A00E684C4 /* RandomBeerRequest.swift */, - 9767CC052222B1BB00E684C4 /* URLBuilder.swift */, + 073D13EDB6E52C7CA76600719DF8FCCA /* Info.plist */, + DEC567BAB5C34B4B7667B6C1478CE2DA /* PunkAPI.modulemap */, + F5FCAD7EA85132D2D8D1388DA3081592 /* PunkAPI.xcconfig */, + AF457128C49817820875EFC37DDC2763 /* PunkAPI-dummy.m */, + 16EF8876C605E8EC561718EF37E64EF9 /* PunkAPI-prefix.pch */, + 5E6E75F5999AC210521146C7375A3313 /* PunkAPI-umbrella.h */, ); - name = Request; - path = PunkAPI/Classes/Request; + name = "Support Files"; + path = "Example/Pods/Target Support Files/PunkAPI"; sourceTree = ""; }; - F3C407FDC658F8445BE7AB2FF5F32CB6 /* Pod */ = { + F7A6E9EE825581F4F5E91FACA3E20C0F /* PunkAPI */ = { isa = PBXGroup; children = ( - 54767361581B8332A2D7629F5E98048E /* LICENSE */, - 864A4FE64365AC74BB9E53A4618E5F55 /* PunkAPI.podspec */, - 3F4208A029892D178EE8F5C95D6D79EB /* README.md */, + 9E63AF47725611B0A82E5D288783A976 /* Configuration.swift */, + D5EF39F3AF34782AC8545A51C195DF61 /* PunkAPI.swift */, + 883B8E4B6F6171944650345EDD78EC6C /* Content */, + 1EAE5A66A94268C182B75D7DB0BFCB3F /* Pod */, + 090992C0DECBC3153B28556E0B42A41B /* Request */, + 0514815A5F57F1358DA701F5C9BCA5D2 /* Results */, + CB553B8B7B06165B82FCA92BD5137F9D /* Support Files */, ); - name = Pod; + name = PunkAPI; + path = ../..; sourceTree = ""; }; /* End PBXGroup section */ @@ -347,7 +349,7 @@ buildConfigurationList = C5CFB8D87EAAD43FF2A708011ADF9DF5 /* Build configuration list for PBXNativeTarget "PunkAPI" */; buildPhases = ( 6BAF60135FDFD6B381631C7BED9969B3 /* Headers */, - 20F3A7AEDB67EAE35B24D16B388F9A4B /* Sources */, + 86F73B177785FEBCB3F340D791903737 /* Sources */, 64469F9A8CDA0C6CFDD8BA665E002A2F /* Frameworks */, 971F83F24AFBDD4CF88BD6ED289EEB1C /* Resources */, ); @@ -451,37 +453,37 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 20F3A7AEDB67EAE35B24D16B388F9A4B /* Sources */ = { + 7D76001470C4ECFAD45A4E50C07DF2B8 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 5ABF50E02687C014E47088344889FC06 /* Beer.swift in Sources */, - 80B5BF4A54A873CBBDE11FD50E93473F /* BeerRequest.swift in Sources */, - 9767CC19222AC45900E684C4 /* BeersRequestParameter.swift in Sources */, - D8CFB7B7D1AAC97CCB20D1DD5C56FB9B /* Configuration.swift in Sources */, - 9767CC20222ADE2500E684C4 /* FloatParameter.swift in Sources */, - 3AF70E263893077BB94A1C3F36DCC044 /* Errors.swift in Sources */, - 8CA330EBFA4F61AE26881286B24648A7 /* Method.swift in Sources */, - 9767CC062222B1BB00E684C4 /* URLBuilder.swift in Sources */, - A1658BA79EB16D586EE25257AD1D8ED6 /* PunkAPI-dummy.m in Sources */, - 90001FCA9653A9974B648EAF681F4DD4 /* PunkAPI.swift in Sources */, - 9767CC22222ADE5100E684C4 /* StringParameter.swift in Sources */, - C0BB3FEC5BB8EF2E7C42FD464D459623 /* Quantity.swift in Sources */, - 9767CC24222ADE6800E684C4 /* DateParameter.swift in Sources */, - 6017B5D2AAB067785D0E2EE754D97A17 /* Recipe.swift in Sources */, - 9767CC1C222ADDD100E684C4 /* RequestParameter.swift in Sources */, - 89899DFDA224AF6393CF9985FF2AE13E /* Request.swift in Sources */, - 9767CC112223592A00E684C4 /* RandomBeerRequest.swift in Sources */, - A3F6E06BFFDEF9DAD8325928091F4B00 /* Result.swift in Sources */, - 9767CC17222AC3F900E684C4 /* BeersRequest.swift in Sources */, + 1DEF7BF616CC3F2EF46A7F9E5514F9AC /* Pods-PunkAPI_Tests-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 7D76001470C4ECFAD45A4E50C07DF2B8 /* Sources */ = { + 86F73B177785FEBCB3F340D791903737 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1DEF7BF616CC3F2EF46A7F9E5514F9AC /* Pods-PunkAPI_Tests-dummy.m in Sources */, + 040633ED2DA398496AD631E73B9CB953 /* Beer.swift in Sources */, + 0C4C6C5EED9509237E097606FBBF2046 /* BeerRequest.swift in Sources */, + 8CA6935D75E79F06DC50B80FBFA04E52 /* BeersRequest.swift in Sources */, + FAEC0D53EBA4A5BCFCDA4CB97EA975AA /* BeersRequestParameter.swift in Sources */, + ADCB0254782B197A401A2AAC39C0E882 /* Configuration.swift in Sources */, + A2A4C282870BFE912F85DB1151BC24B3 /* DateParameter.swift in Sources */, + 156976A157354FAC4A76CDD07C60C630 /* Errors.swift in Sources */, + EA2895A6DC98FCFBB5A54F5837E8304F /* FloatParameter.swift in Sources */, + 9C1115413D21B46B31F5D70FE29CA857 /* Method.swift in Sources */, + 567123199E19D2AF982C095A91F499E3 /* PunkAPI-dummy.m in Sources */, + 9E26D0BC2A8D1AB927AD665EB5032162 /* PunkAPI.swift in Sources */, + BBCC787A76C3C536D049EB6E228394FF /* Quantity.swift in Sources */, + 9EB5A8CE4227261D6FDB84878505ACED /* RandomBeerRequest.swift in Sources */, + 58196BD46A6A962CD2291747E891A4FF /* Recipe.swift in Sources */, + 4C4AB5D20013C59D1BE1A0DC0AA4A90E /* Request.swift in Sources */, + 1F269E313E3E5E6D95C7EA4117A4EF52 /* RequestParameter.swift in Sources */, + 9F91EF3525A1E94F87950035B1DEF148 /* Result.swift in Sources */, + 0706F758C5F2CE0E83E44396DE53B472 /* StringParameter.swift in Sources */, + AA5C8E19C31A6A5CDAD11062F1625806 /* URLBuilder.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -511,11 +513,45 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 403B3CA7AD0B06503DC7AB172EBAC118 /* Debug */ = { + 0B544C28097B1323AC34E22808695EB6 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 6EDD1194CE9C142C26AD6C6803C306E4 /* Pods-PunkAPI_Tests.debug.xcconfig */; + baseConfigurationReference = F5FCAD7EA85132D2D8D1388DA3081592 /* PunkAPI.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/PunkAPI/PunkAPI-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/PunkAPI/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/PunkAPI/PunkAPI.modulemap"; + PRODUCT_MODULE_NAME = PunkAPI; + PRODUCT_NAME = PunkAPI; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 0F7F14A2385ED2D3C3346A495562A023 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E816F7DA6C1CBE532E1590E0F05B9532 /* Pods-PunkAPI_Example.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -525,12 +561,12 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Tests/Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Example/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -544,11 +580,12 @@ }; name = Debug; }; - 46AF96B59BED2112D06B134F951A4153 /* Release */ = { + 8D795C21A9507CA6A9E811BFB95FEAC5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A5D146483FC9684CF2C15F85C081EF35 /* Pods-PunkAPI_Example.release.xcconfig */; + baseConfigurationReference = 6EDD1194CE9C142C26AD6C6803C306E4 /* Pods-PunkAPI_Tests.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -558,12 +595,12 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Example/Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Tests/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -572,13 +609,12 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; - 50646285DD9FD95AF390BDA3FB1948EA /* Debug */ = { + 8DDFA5FA8D4131BFD96E5E26F3672644 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -631,7 +667,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -644,7 +680,77 @@ }; name = Debug; }; - 58DCB2BA7C34E84C00C38CEF18A96D11 /* Release */ = { + A6182063646965CD3A9B8CBF97BA24A3 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A5D146483FC9684CF2C15F85C081EF35 /* Pods-PunkAPI_Example.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Example/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D44F402051D76F6439E6BA95C278A702 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 492C127C07A0D9D778B3D645FCDED6AC /* Pods-PunkAPI_Tests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Tests/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D5F759C82752B2EB010DB3CD3D69707C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -694,52 +800,23 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; STRIP_INSTALLED_PRODUCT = NO; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 4.2; SYMROOT = "${SRCROOT}/../build"; }; name = Release; }; - 7CC3C9EDFC11B302ABDBAC490D072DF4 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1AE9EEDB05092385E557ED3979AAEBC1 /* PunkAPI.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/PunkAPI/PunkAPI-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/PunkAPI/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/PunkAPI/PunkAPI.modulemap"; - PRODUCT_MODULE_NAME = PunkAPI; - PRODUCT_NAME = PunkAPI; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 4.2; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - C4C31973A271F96E49F93F0B1190E36C /* Release */ = { + E478EE7340C05210B36C506ACA88CC8F /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 1AE9EEDB05092385E557ED3979AAEBC1 /* PunkAPI.xcconfig */; + baseConfigurationReference = F5FCAD7EA85132D2D8D1388DA3081592 /* PunkAPI.xcconfig */; buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -752,7 +829,7 @@ GCC_PREFIX_HEADER = "Target Support Files/PunkAPI/PunkAPI-prefix.pch"; INFOPLIST_FILE = "Target Support Files/PunkAPI/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/PunkAPI/PunkAPI.modulemap"; PRODUCT_MODULE_NAME = PunkAPI; @@ -762,74 +839,6 @@ SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - CEA1F7ADD2A14B78BDC2402ECBA8804F /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 492C127C07A0D9D778B3D645FCDED6AC /* Pods-PunkAPI_Tests.release.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Tests/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Tests/Pods-PunkAPI_Tests.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - D1B38F9CCE04509C680580A3EE523419 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = E816F7DA6C1CBE532E1590E0F05B9532 /* Pods-PunkAPI_Example.debug.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-PunkAPI_Example/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-PunkAPI_Example/Pods-PunkAPI_Example.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -841,8 +850,8 @@ 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - 50646285DD9FD95AF390BDA3FB1948EA /* Debug */, - 58DCB2BA7C34E84C00C38CEF18A96D11 /* Release */, + 8DDFA5FA8D4131BFD96E5E26F3672644 /* Debug */, + D5F759C82752B2EB010DB3CD3D69707C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -850,8 +859,8 @@ 418812EEE776D4446934FDEFBBAAB6E0 /* Build configuration list for PBXNativeTarget "Pods-PunkAPI_Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 403B3CA7AD0B06503DC7AB172EBAC118 /* Debug */, - CEA1F7ADD2A14B78BDC2402ECBA8804F /* Release */, + 8D795C21A9507CA6A9E811BFB95FEAC5 /* Debug */, + D44F402051D76F6439E6BA95C278A702 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -859,8 +868,8 @@ B97836D74BBC103F707A992128BA2EBA /* Build configuration list for PBXNativeTarget "Pods-PunkAPI_Example" */ = { isa = XCConfigurationList; buildConfigurations = ( - D1B38F9CCE04509C680580A3EE523419 /* Debug */, - 46AF96B59BED2112D06B134F951A4153 /* Release */, + 0F7F14A2385ED2D3C3346A495562A023 /* Debug */, + A6182063646965CD3A9B8CBF97BA24A3 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -868,8 +877,8 @@ C5CFB8D87EAAD43FF2A708011ADF9DF5 /* Build configuration list for PBXNativeTarget "PunkAPI" */ = { isa = XCConfigurationList; buildConfigurations = ( - 7CC3C9EDFC11B302ABDBAC490D072DF4 /* Debug */, - C4C31973A271F96E49F93F0B1190E36C /* Release */, + E478EE7340C05210B36C506ACA88CC8F /* Debug */, + 0B544C28097B1323AC34E22808695EB6 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Example/PunkAPI.xcodeproj/project.pbxproj b/Example/PunkAPI.xcodeproj/project.pbxproj index 2739cca..2cbaab2 100644 --- a/Example/PunkAPI.xcodeproj/project.pbxproj +++ b/Example/PunkAPI.xcodeproj/project.pbxproj @@ -569,6 +569,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = 6RS7DS4QV5; INFOPLIST_FILE = PunkAPI/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; @@ -584,6 +585,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = 6RS7DS4QV5; INFOPLIST_FILE = PunkAPI/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; diff --git a/PunkAPI.podspec b/PunkAPI.podspec index 3025aa7..660fbad 100644 --- a/PunkAPI.podspec +++ b/PunkAPI.podspec @@ -10,7 +10,8 @@ Pod::Spec.new do |s| s.name = 'PunkAPI' s.version = '0.1.0' s.summary = 'A little swift wrapper for PunkAPI by @samjbmason' - + s.swift_version = '4.2' + s.description = <<-DESC "Have you ever wanted to search through Brewdog's expansive back catalogue of beer in a programmatic way? Maybe build a tool that pairs beer with food, or search beers with an abv of more than 4%? Well now your prayers have been answered!" DESC diff --git a/Results/Errors.swift b/PunkAPI/Classes/Results/Errors.swift similarity index 100% rename from Results/Errors.swift rename to PunkAPI/Classes/Results/Errors.swift diff --git a/Results/Result.swift b/PunkAPI/Classes/Results/Result.swift similarity index 100% rename from Results/Result.swift rename to PunkAPI/Classes/Results/Result.swift From 0c53fd4339fface5bf7b59de848ff7cb5218ed36 Mon Sep 17 00:00:00 2001 From: Andrea Altea Date: Sun, 3 Mar 2019 13:25:52 +0100 Subject: [PATCH 37/37] Fix: update Test deployment target --- Example/PunkAPI.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Example/PunkAPI.xcodeproj/project.pbxproj b/Example/PunkAPI.xcodeproj/project.pbxproj index 2cbaab2..eb12836 100644 --- a/Example/PunkAPI.xcodeproj/project.pbxproj +++ b/Example/PunkAPI.xcodeproj/project.pbxproj @@ -506,7 +506,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -554,7 +554,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";