diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..d46f9c7 Binary files /dev/null and b/.DS_Store differ diff --git a/Fakestagram-Xcode10/Fakestagram-Xcode10.xcodeproj/project.pbxproj b/Fakestagram-Xcode10/Fakestagram-Xcode10.xcodeproj/project.pbxproj new file mode 100755 index 0000000..01d56d3 --- /dev/null +++ b/Fakestagram-Xcode10/Fakestagram-Xcode10.xcodeproj/project.pbxproj @@ -0,0 +1,470 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 7701BEB1233F1B1B0004C30D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7701BEB0233F1B1B0004C30D /* AppDelegate.swift */; }; + 7701BEB6233F1B1B0004C30D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7701BEB4233F1B1B0004C30D /* Main.storyboard */; }; + 7701BEB8233F1B1C0004C30D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7701BEB7233F1B1C0004C30D /* Assets.xcassets */; }; + 7701BEBB233F1B1C0004C30D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7701BEB9233F1B1C0004C30D /* LaunchScreen.storyboard */; }; + 7701BEC6233F1B1C0004C30D /* Fakestagram_Xcode10Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7701BEC5233F1B1C0004C30D /* Fakestagram_Xcode10Tests.swift */; }; + 7701BED1233F1B540004C30D /* PostsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7701BED0233F1B540004C30D /* PostsTableViewController.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 7701BEC2233F1B1C0004C30D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7701BEA5233F1B1B0004C30D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 7701BEAC233F1B1B0004C30D; + remoteInfo = "Fakestagram-Xcode10"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 7701BEAD233F1B1B0004C30D /* Fakestagram-Xcode10.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Fakestagram-Xcode10.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 7701BEB0233F1B1B0004C30D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7701BEB5233F1B1B0004C30D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 7701BEB7233F1B1C0004C30D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 7701BEBA233F1B1C0004C30D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 7701BEBC233F1B1C0004C30D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 7701BEC1233F1B1C0004C30D /* Fakestagram-Xcode10Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Fakestagram-Xcode10Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 7701BEC5233F1B1C0004C30D /* Fakestagram_Xcode10Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Fakestagram_Xcode10Tests.swift; sourceTree = ""; }; + 7701BEC7233F1B1C0004C30D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 7701BED0233F1B540004C30D /* PostsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostsTableViewController.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7701BEAA233F1B1B0004C30D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7701BEBE233F1B1C0004C30D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7701BEA4233F1B1B0004C30D = { + isa = PBXGroup; + children = ( + 7701BEAF233F1B1B0004C30D /* Fakestagram-Xcode10 */, + 7701BEC4233F1B1C0004C30D /* Fakestagram-Xcode10Tests */, + 7701BEAE233F1B1B0004C30D /* Products */, + ); + sourceTree = ""; + }; + 7701BEAE233F1B1B0004C30D /* Products */ = { + isa = PBXGroup; + children = ( + 7701BEAD233F1B1B0004C30D /* Fakestagram-Xcode10.app */, + 7701BEC1233F1B1C0004C30D /* Fakestagram-Xcode10Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7701BEAF233F1B1B0004C30D /* Fakestagram-Xcode10 */ = { + isa = PBXGroup; + children = ( + 7701BEB0233F1B1B0004C30D /* AppDelegate.swift */, + 7701BED0233F1B540004C30D /* PostsTableViewController.swift */, + 7701BEB4233F1B1B0004C30D /* Main.storyboard */, + 7701BEB7233F1B1C0004C30D /* Assets.xcassets */, + 7701BEB9233F1B1C0004C30D /* LaunchScreen.storyboard */, + 7701BEBC233F1B1C0004C30D /* Info.plist */, + ); + path = "Fakestagram-Xcode10"; + sourceTree = ""; + }; + 7701BEC4233F1B1C0004C30D /* Fakestagram-Xcode10Tests */ = { + isa = PBXGroup; + children = ( + 7701BEC5233F1B1C0004C30D /* Fakestagram_Xcode10Tests.swift */, + 7701BEC7233F1B1C0004C30D /* Info.plist */, + ); + path = "Fakestagram-Xcode10Tests"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7701BEAC233F1B1B0004C30D /* Fakestagram-Xcode10 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7701BECA233F1B1C0004C30D /* Build configuration list for PBXNativeTarget "Fakestagram-Xcode10" */; + buildPhases = ( + 7701BEA9233F1B1B0004C30D /* Sources */, + 7701BEAA233F1B1B0004C30D /* Frameworks */, + 7701BEAB233F1B1B0004C30D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Fakestagram-Xcode10"; + productName = "Fakestagram-Xcode10"; + productReference = 7701BEAD233F1B1B0004C30D /* Fakestagram-Xcode10.app */; + productType = "com.apple.product-type.application"; + }; + 7701BEC0233F1B1C0004C30D /* Fakestagram-Xcode10Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7701BECD233F1B1C0004C30D /* Build configuration list for PBXNativeTarget "Fakestagram-Xcode10Tests" */; + buildPhases = ( + 7701BEBD233F1B1C0004C30D /* Sources */, + 7701BEBE233F1B1C0004C30D /* Frameworks */, + 7701BEBF233F1B1C0004C30D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 7701BEC3233F1B1C0004C30D /* PBXTargetDependency */, + ); + name = "Fakestagram-Xcode10Tests"; + productName = "Fakestagram-Xcode10Tests"; + productReference = 7701BEC1233F1B1C0004C30D /* Fakestagram-Xcode10Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7701BEA5233F1B1B0004C30D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1030; + LastUpgradeCheck = 1030; + ORGANIZATIONNAME = unam; + TargetAttributes = { + 7701BEAC233F1B1B0004C30D = { + CreatedOnToolsVersion = 10.3; + }; + 7701BEC0233F1B1C0004C30D = { + CreatedOnToolsVersion = 10.3; + TestTargetID = 7701BEAC233F1B1B0004C30D; + }; + }; + }; + buildConfigurationList = 7701BEA8233F1B1B0004C30D /* Build configuration list for PBXProject "Fakestagram-Xcode10" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7701BEA4233F1B1B0004C30D; + productRefGroup = 7701BEAE233F1B1B0004C30D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7701BEAC233F1B1B0004C30D /* Fakestagram-Xcode10 */, + 7701BEC0233F1B1C0004C30D /* Fakestagram-Xcode10Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7701BEAB233F1B1B0004C30D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7701BEBB233F1B1C0004C30D /* LaunchScreen.storyboard in Resources */, + 7701BEB8233F1B1C0004C30D /* Assets.xcassets in Resources */, + 7701BEB6233F1B1B0004C30D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7701BEBF233F1B1C0004C30D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7701BEA9233F1B1B0004C30D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7701BED1233F1B540004C30D /* PostsTableViewController.swift in Sources */, + 7701BEB1233F1B1B0004C30D /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7701BEBD233F1B1C0004C30D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7701BEC6233F1B1C0004C30D /* Fakestagram_Xcode10Tests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 7701BEC3233F1B1C0004C30D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 7701BEAC233F1B1B0004C30D /* Fakestagram-Xcode10 */; + targetProxy = 7701BEC2233F1B1C0004C30D /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 7701BEB4233F1B1B0004C30D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 7701BEB5233F1B1B0004C30D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 7701BEB9233F1B1C0004C30D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 7701BEBA233F1B1C0004C30D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 7701BEC8233F1B1C0004C30D /* 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_SIGN_IDENTITY = "iPhone Developer"; + 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 = ( + "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 = 12.4; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7701BEC9233F1B1C0004C30D /* 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_SIGN_IDENTITY = "iPhone Developer"; + 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_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 = 12.4; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 7701BECB233F1B1C0004C30D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = F2BL68NTA5; + INFOPLIST_FILE = "Fakestagram-Xcode10/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "unam.Fakestagram-Xcode10"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 7701BECC233F1B1C0004C30D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = F2BL68NTA5; + INFOPLIST_FILE = "Fakestagram-Xcode10/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "unam.Fakestagram-Xcode10"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 7701BECE233F1B1C0004C30D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = F2BL68NTA5; + INFOPLIST_FILE = "Fakestagram-Xcode10Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "unam.Fakestagram-Xcode10Tests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Fakestagram-Xcode10.app/Fakestagram-Xcode10"; + }; + name = Debug; + }; + 7701BECF233F1B1C0004C30D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = F2BL68NTA5; + INFOPLIST_FILE = "Fakestagram-Xcode10Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "unam.Fakestagram-Xcode10Tests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Fakestagram-Xcode10.app/Fakestagram-Xcode10"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7701BEA8233F1B1B0004C30D /* Build configuration list for PBXProject "Fakestagram-Xcode10" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7701BEC8233F1B1C0004C30D /* Debug */, + 7701BEC9233F1B1C0004C30D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7701BECA233F1B1C0004C30D /* Build configuration list for PBXNativeTarget "Fakestagram-Xcode10" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7701BECB233F1B1C0004C30D /* Debug */, + 7701BECC233F1B1C0004C30D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7701BECD233F1B1C0004C30D /* Build configuration list for PBXNativeTarget "Fakestagram-Xcode10Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7701BECE233F1B1C0004C30D /* Debug */, + 7701BECF233F1B1C0004C30D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7701BEA5233F1B1B0004C30D /* Project object */; +} diff --git a/Fakestagram-Xcode10/Fakestagram-Xcode10.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Fakestagram-Xcode10/Fakestagram-Xcode10.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..11506a6 --- /dev/null +++ b/Fakestagram-Xcode10/Fakestagram-Xcode10.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Fakestagram-Xcode10/Fakestagram-Xcode10.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Fakestagram-Xcode10/Fakestagram-Xcode10.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 0000000..18d9810 --- /dev/null +++ b/Fakestagram-Xcode10/Fakestagram-Xcode10.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Fakestagram-Xcode10/Fakestagram-Xcode10.xcodeproj/project.xcworkspace/xcuserdata/richard_ohg.xcuserdatad/UserInterfaceState.xcuserstate b/Fakestagram-Xcode10/Fakestagram-Xcode10.xcodeproj/project.xcworkspace/xcuserdata/richard_ohg.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100755 index 0000000..f122098 Binary files /dev/null and b/Fakestagram-Xcode10/Fakestagram-Xcode10.xcodeproj/project.xcworkspace/xcuserdata/richard_ohg.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Fakestagram-Xcode10/Fakestagram-Xcode10.xcodeproj/xcuserdata/richard_ohg.xcuserdatad/xcschemes/xcschememanagement.plist b/Fakestagram-Xcode10/Fakestagram-Xcode10.xcodeproj/xcuserdata/richard_ohg.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100755 index 0000000..117850a --- /dev/null +++ b/Fakestagram-Xcode10/Fakestagram-Xcode10.xcodeproj/xcuserdata/richard_ohg.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + Fakestagram-Xcode10.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/Fakestagram-Xcode10/Fakestagram-Xcode10/AppDelegate.swift b/Fakestagram-Xcode10/Fakestagram-Xcode10/AppDelegate.swift new file mode 100755 index 0000000..a89d52f --- /dev/null +++ b/Fakestagram-Xcode10/Fakestagram-Xcode10/AppDelegate.swift @@ -0,0 +1,43 @@ +// +// AppDelegate.swift +// Fakestagram-Xcode10 +// +// Created by Ricardo Hernández González on 9/27/19. +// Copyright © 2019 unam. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + +} diff --git a/Fakestagram-Xcode10/Fakestagram-Xcode10/Assets.xcassets/AppIcon.appiconset/Contents.json b/Fakestagram-Xcode10/Fakestagram-Xcode10/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 0000000..d8db8d6 --- /dev/null +++ b/Fakestagram-Xcode10/Fakestagram-Xcode10/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Fakestagram-Xcode10/Fakestagram-Xcode10/Assets.xcassets/Contents.json b/Fakestagram-Xcode10/Fakestagram-Xcode10/Assets.xcassets/Contents.json new file mode 100755 index 0000000..da4a164 --- /dev/null +++ b/Fakestagram-Xcode10/Fakestagram-Xcode10/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Fakestagram-Xcode10/Fakestagram-Xcode10/Base.lproj/LaunchScreen.storyboard b/Fakestagram-Xcode10/Fakestagram-Xcode10/Base.lproj/LaunchScreen.storyboard new file mode 100755 index 0000000..bfa3612 --- /dev/null +++ b/Fakestagram-Xcode10/Fakestagram-Xcode10/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Fakestagram-Xcode10/Fakestagram-Xcode10/Base.lproj/Main.storyboard b/Fakestagram-Xcode10/Fakestagram-Xcode10/Base.lproj/Main.storyboard new file mode 100755 index 0000000..e29aa1a --- /dev/null +++ b/Fakestagram-Xcode10/Fakestagram-Xcode10/Base.lproj/Main.storyboard @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Fakestagram-Xcode10/Fakestagram-Xcode10/Info.plist b/Fakestagram-Xcode10/Fakestagram-Xcode10/Info.plist new file mode 100755 index 0000000..16be3b6 --- /dev/null +++ b/Fakestagram-Xcode10/Fakestagram-Xcode10/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/fakestagram/PostsTableViewController.swift b/Fakestagram-Xcode10/Fakestagram-Xcode10/PostsTableViewController.swift old mode 100644 new mode 100755 similarity index 67% rename from fakestagram/PostsTableViewController.swift rename to Fakestagram-Xcode10/Fakestagram-Xcode10/PostsTableViewController.swift index 2f4c4d7..a54149b --- a/fakestagram/PostsTableViewController.swift +++ b/Fakestagram-Xcode10/Fakestagram-Xcode10/PostsTableViewController.swift @@ -42,7 +42,7 @@ class PostsTableViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() - loadPosts() { data in + loadPosts { data in DispatchQueue.main.async { self.posts = data self.tableView.reloadData() @@ -79,58 +79,58 @@ class PostsTableViewController: UITableViewController { } /* - // Override to support conditional editing of the table view. - override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { - // Return false if you do not want the specified item to be editable. - return true - } - */ + // Override to support conditional editing of the table view. + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ /* - // Override to support editing the table view. - override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { - if editingStyle == .delete { - // Delete the row from the data source - tableView.deleteRows(at: [indexPath], with: .fade) - } else if editingStyle == .insert { - // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view - } - } - */ + // Override to support editing the table view. + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete { + // Delete the row from the data source + tableView.deleteRows(at: [indexPath], with: .fade) + } else if editingStyle == .insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ /* - // Override to support rearranging the table view. - override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { - - } - */ + // Override to support rearranging the table view. + override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { + + } + */ /* - // Override to support conditional rearranging of the table view. - override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { - // Return false if you do not want the item to be re-orderable. - return true - } - */ + // Override to support conditional rearranging of the table view. + override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ /* - // MARK: - Navigation + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ - func loadPosts(successful: @escaping ([Post]) -> Void) { var request = URLRequest(url: URL(string: "https://fakestagram-api.herokuapp.com/api/v1/posts")!) request.setValue("application/json", forHTTPHeaderField: "Accept") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpMethod = "get" request.addValue("Bearer f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e", forHTTPHeaderField: "Authorization") - - let task = URLSession.shared.dataTask(with: request) { (data, response, error) in + + let task = URLSession.shared.dataTask(with: request) { (data, _, error) in if error != nil || data == nil { return } diff --git a/fakestagramTests/fakestagramTests.swift b/Fakestagram-Xcode10/Fakestagram-Xcode10Tests/Fakestagram_Xcode10Tests.swift old mode 100644 new mode 100755 similarity index 73% rename from fakestagramTests/fakestagramTests.swift rename to Fakestagram-Xcode10/Fakestagram-Xcode10Tests/Fakestagram_Xcode10Tests.swift index f022cfd..021e737 --- a/fakestagramTests/fakestagramTests.swift +++ b/Fakestagram-Xcode10/Fakestagram-Xcode10Tests/Fakestagram_Xcode10Tests.swift @@ -1,15 +1,15 @@ // -// fakestagramTests.swift -// fakestagramTests +// Fakestagram_Xcode10Tests.swift +// Fakestagram-Xcode10Tests // -// Created by LuisE on 9/24/19. -// Copyright © 2019 3zcurdia. All rights reserved. +// Created by Ricardo Hernández González on 9/27/19. +// Copyright © 2019 unam. All rights reserved. // import XCTest -@testable import fakestagram +@testable import Fakestagram_Xcode10 -class fakestagramTests: XCTestCase { +class Fakestagram_Xcode10Tests: XCTestCase { override func setUp() { // Put setup code here. This method is called before the invocation of each test method in the class. diff --git a/Fakestagram-Xcode10/Fakestagram-Xcode10Tests/Info.plist b/Fakestagram-Xcode10/Fakestagram-Xcode10Tests/Info.plist new file mode 100755 index 0000000..6c40a6c --- /dev/null +++ b/Fakestagram-Xcode10/Fakestagram-Xcode10Tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/Podfile b/Podfile new file mode 100755 index 0000000..77cfa72 --- /dev/null +++ b/Podfile @@ -0,0 +1,14 @@ +# Uncomment the next line to define a global platform for your project +platform :ios, '13.0' + +target 'fakestagram' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + # Pods for fakestagram + pod 'SAMKeychain' + + target 'fakestagramTests' do + inherit! :search_paths + pod 'DVR' + end +end diff --git a/Podfile.lock b/Podfile.lock new file mode 100755 index 0000000..b5bd883 --- /dev/null +++ b/Podfile.lock @@ -0,0 +1,20 @@ +PODS: + - DVR (2.0.0) + - SAMKeychain (1.5.3) + +DEPENDENCIES: + - DVR + - SAMKeychain + +SPEC REPOS: + trunk: + - DVR + - SAMKeychain + +SPEC CHECKSUMS: + DVR: 062c287b9dc613a84120e44640176e4ef3ecf943 + SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c + +PODFILE CHECKSUM: 02c21c317ba9be4fdecdfff242f3fa20e9b269bd + +COCOAPODS: 1.8.4 diff --git a/Pods/DVR/LICENSE b/Pods/DVR/LICENSE new file mode 100755 index 0000000..2317f84 --- /dev/null +++ b/Pods/DVR/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2015 Venmo + +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. diff --git a/Pods/DVR/Readme.markdown b/Pods/DVR/Readme.markdown new file mode 100755 index 0000000..92bf3d0 --- /dev/null +++ b/Pods/DVR/Readme.markdown @@ -0,0 +1,56 @@ +# DVR + +[![Version](https://img.shields.io/github/release/venmo/DVR.svg)](https://github.com/venmo/DVR/releases) +![Status](https://travis-ci.org/venmo/DVR.svg?branch=master) +![Swift Version](https://img.shields.io/badge/swift-4.2-orange.svg) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![Swift Package Manager](https://img.shields.io/badge/SPM-compatible-brightgreen.svg)](https://swift.org/package-manager/) + +DVR is a simple Swift framework for making fake `NSURLSession` requests for iOS, +watchOS, and OS X based on [VCR](https://github.com/vcr/vcr). + +Easy [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection) is the main design goal. The API is the same as `NSURLSession`. `DVR.Session` is a subclass of `NSURLSession` so you can use it as a drop in replacement anywhere. (Currently only data tasks are supported.) + + +## Usage + +```swift +let session = Session(cassetteName: "example") +let task = session.dataTask(with: request) { data, response, error in + // Do something with the response +} + +// Nothing happens until you call `resume` as you'd expect. +task.resume() +``` + +This will playback the `example` cassette. The completion handler exactly the same way it normally would. In this example, DVR will look for a cassette named `example.json` in your test bundle. + +If the recording of the request is missing, it will record and save it to disk. After saving to disk, it will assert with path of the recorded file. This causes the tests to stop so you can add the cassette to your test target and rerun your tests. + + +### Recording Multiple Requests + +By default, a DVR session only records one request. You can record multiple requests in the same cassette if you tell DVR when to start and stop recording. + +``` swift +let session = Session(cassetteName: "multiple") + +// Begin recording multiple requests +session.beginRecording() + +session.dataTask(with: URLRequest(url: URL(string: "http://apple.com")!)) { data, response, error in + // Do something with the response + + session.dataTask(with: URLRequest(url: URL(string: "http://google.com")!)) { data, response, error in + // Do something with the response + }.resume() + + // Finish recording multiple requests + session.endRecording() { + // All requests have completed + } +}.resume() +``` + +If you don't call `beginRecording` and `endRecording`, DVR will call these for your around the first request you make to a session. You can call `endRecording` immediately after you've submitted all of your requests to the session. The optional completion block that `endRecording` accepts will be called when all requests have finished. This is a good spot to fulfill XCTest expectations you've setup or do whatever else now that networking has finished. diff --git a/Pods/DVR/Sources/DVR/Cassette.swift b/Pods/DVR/Sources/DVR/Cassette.swift new file mode 100755 index 0000000..b3e8fb9 --- /dev/null +++ b/Pods/DVR/Sources/DVR/Cassette.swift @@ -0,0 +1,68 @@ +import Foundation + +struct Cassette { + + // MARK: - Properties + + let name: String + let interactions: [Interaction] + + + // MARK: - Initializers + + init(name: String, interactions: [Interaction]) { + self.name = name + self.interactions = interactions + } + + + // MARK: - Functions + + func interactionForRequest(_ request: URLRequest) -> Interaction? { + for interaction in interactions { + let interactionRequest = interaction.request + + // Note: We don't check headers right now + if interactionRequest.httpMethod == request.httpMethod && interactionRequest.url == request.url && interactionRequest.hasHTTPBodyEqualToThatOfRequest(request) { + return interaction + } + } + return nil + } +} + + +extension Cassette { + var dictionary: [String: Any] { + return [ + "name": name as Any, + "interactions": interactions.map { $0.dictionary } + ] + } + + init?(dictionary: [String: Any]) { + guard let name = dictionary["name"] as? String else { return nil } + + self.name = name + + if let array = dictionary["interactions"] as? [[String: Any]] { + interactions = array.compactMap { Interaction(dictionary: $0) } + } else { + interactions = [] + } + } +} + +private extension URLRequest { + func hasHTTPBodyEqualToThatOfRequest(_ request: URLRequest) -> Bool { + guard let body1 = self.httpBody, + let body2 = request.httpBody, + let encoded1 = Interaction.encodeBody(body1, headers: self.allHTTPHeaderFields), + let encoded2 = Interaction.encodeBody(body2, headers: request.allHTTPHeaderFields) + else { + return self.httpBody == request.httpBody + } + + return encoded1.isEqual(encoded2) + } +} diff --git a/Pods/DVR/Sources/DVR/HTTPURLResponse.swift b/Pods/DVR/Sources/DVR/HTTPURLResponse.swift new file mode 100755 index 0000000..7078b3d --- /dev/null +++ b/Pods/DVR/Sources/DVR/HTTPURLResponse.swift @@ -0,0 +1,57 @@ +import Foundation + +// There isn't a mutable HTTPURLResponse, so we have to make our own. +class HTTPURLResponse: Foundation.HTTPURLResponse { + + // MARK: - Properties + + private var _url: URL? + override var url: URL? { + get { + return _url ?? super.url + } + + set { + _url = newValue + } + } + + private var _statusCode: Int? + override var statusCode: Int { + get { + return _statusCode ?? super.statusCode + } + + set { + _statusCode = newValue + } + } + + private var _allHeaderFields: [AnyHashable: Any]? + override var allHeaderFields: [AnyHashable: Any] { + get { + return _allHeaderFields ?? super.allHeaderFields + } + + set { + _allHeaderFields = newValue + } + } +} + + +extension HTTPURLResponse { + convenience init(dictionary: [String: Any]) { + let url = URL(string: dictionary["url"] as! String)! + + self.init(url: url, mimeType: nil, expectedContentLength: 0, textEncodingName: nil) + + if let headers = dictionary["headers"] as? [String: String] { + allHeaderFields = headers + } + + if let status = dictionary["status"] as? Int { + statusCode = status + } + } +} diff --git a/Pods/DVR/Sources/DVR/Interaction.swift b/Pods/DVR/Sources/DVR/Interaction.swift new file mode 100755 index 0000000..b37af0b --- /dev/null +++ b/Pods/DVR/Sources/DVR/Interaction.swift @@ -0,0 +1,110 @@ +import Foundation + +struct Interaction { + + // MARK: - Properties + + let request: URLRequest + let response: Foundation.URLResponse + let responseData: Data? + let recordedAt: Date + + + // MARK: - Initializers + + init(request: URLRequest, response: Foundation.URLResponse, responseData: Data? = nil, recordedAt: Date = Date()) { + self.request = request + self.response = response + self.responseData = responseData + self.recordedAt = recordedAt + } + + + // MARK: - Encoding + + static func encodeBody(_ body: Data, headers: [String: String]? = nil) -> AnyObject? { + if let contentType = headers?["Content-Type"] { + // Text + if contentType.hasPrefix("text/") { + // TODO: Use text encoding if specified in headers + return NSString(data: body, encoding: String.Encoding.utf8.rawValue) + } + + // JSON + if contentType.hasPrefix("application/json") { + do { + return try JSONSerialization.jsonObject(with: body, options: []) as AnyObject + } catch { + return nil + } + } + } + + // Base64 + return body.base64EncodedString(options: []) as AnyObject? + } + + static func dencodeBody(_ body: Any?, headers: [String: String]? = nil) -> Data? { + guard let body = body else { return nil } + + if let contentType = headers?["Content-Type"] { + // Text + if let string = body as? String , contentType.hasPrefix("text/") { + // TODO: Use encoding if specified in headers + return string.data(using: String.Encoding.utf8) + } + + // JSON + if contentType.hasPrefix("application/json") { + do { + return try JSONSerialization.data(withJSONObject: body, options: []) + } catch { + return nil + } + } + } + + // Base64 + if let base64 = body as? String { + return Data(base64Encoded: base64, options: []) + } + + return nil + } +} + + +extension Interaction { + var dictionary: [String: Any] { + var dictionary: [String: Any] = [ + "request": request.dictionary, + "recorded_at": recordedAt.timeIntervalSince1970 + ] + + var responseDictionary = self.response.dictionary + + if let httpResponse = response as? Foundation.HTTPURLResponse { + responseDictionary["headers"] = httpResponse.allHeaderFields + responseDictionary["status"] = httpResponse.statusCode + } + + if let data = responseData, let body = Interaction.encodeBody(data, headers: responseDictionary["headers"] as? [String: String]) { + responseDictionary["body"] = body + } + + dictionary["response"] = responseDictionary + + return dictionary + } + + init?(dictionary: [String: Any]) { + guard let request = dictionary["request"] as? [String: Any], + let response = dictionary["response"] as? [String: Any], + let recordedAt = dictionary["recorded_at"] as? TimeInterval else { return nil } + + self.request = NSMutableURLRequest(dictionary: request) as URLRequest + self.response = HTTPURLResponse(dictionary: response) + self.recordedAt = Date(timeIntervalSince1970: recordedAt) + self.responseData = Interaction.dencodeBody(response["body"], headers: response["headers"] as? [String: String]) + } +} diff --git a/Pods/DVR/Sources/DVR/Session.swift b/Pods/DVR/Sources/DVR/Session.swift new file mode 100755 index 0000000..3cf1aab --- /dev/null +++ b/Pods/DVR/Sources/DVR/Session.swift @@ -0,0 +1,241 @@ +import Foundation + +open class Session: URLSession { + + // MARK: - Properties + + public static var defaultTestBundle: Bundle? { + return Bundle.allBundles.first { $0.bundlePath.hasSuffix(".xctest") } + } + + open var outputDirectory: String + public let cassetteName: String + public let backingSession: URLSession + open var recordingEnabled = true + + private let testBundle: Bundle + + private var recording = false + private var needsPersistence = false + private var outstandingTasks = [URLSessionTask]() + private var completedInteractions = [Interaction]() + private var completionBlock: (() -> Void)? + + override open var delegate: URLSessionDelegate? { + return backingSession.delegate + } + + // MARK: - Initializers + + public init(outputDirectory: String = "~/Desktop/DVR/", cassetteName: String, testBundle: Bundle = Session.defaultTestBundle!, backingSession: URLSession = URLSession.shared) { + self.outputDirectory = outputDirectory + self.cassetteName = cassetteName + self.testBundle = testBundle + self.backingSession = backingSession + super.init() + } + + + // MARK: - URLSession + + open override func dataTask(with request: URLRequest) -> URLSessionDataTask { + return addDataTask(request) + } + + open override func dataTask(with request: URLRequest, completionHandler: @escaping ((Data?, Foundation.URLResponse?, Error?) -> Void)) -> URLSessionDataTask { + return addDataTask(request, completionHandler: completionHandler) + } + + open override func downloadTask(with request: URLRequest) -> URLSessionDownloadTask { + return addDownloadTask(request) + } + + open override func downloadTask(with request: URLRequest, completionHandler: @escaping (URL?, Foundation.URLResponse?, Error?) -> Void) -> URLSessionDownloadTask { + return addDownloadTask(request, completionHandler: completionHandler) + } + + open override func uploadTask(with request: URLRequest, from bodyData: Data) -> URLSessionUploadTask { + return addUploadTask(request, fromData: bodyData) + } + + open override func uploadTask(with request: URLRequest, from bodyData: Data?, completionHandler: @escaping (Data?, Foundation.URLResponse?, Error?) -> Void) -> URLSessionUploadTask { + return addUploadTask(request, fromData: bodyData, completionHandler: completionHandler) + } + + open override func uploadTask(with request: URLRequest, fromFile fileURL: URL) -> URLSessionUploadTask { + let data = try! Data(contentsOf: fileURL) + return addUploadTask(request, fromData: data) + } + + open override func uploadTask(with request: URLRequest, fromFile fileURL: URL, completionHandler: @escaping (Data?, Foundation.URLResponse?, Error?) -> Void) -> URLSessionUploadTask { + let data = try! Data(contentsOf: fileURL) + return addUploadTask(request, fromData: data, completionHandler: completionHandler) + } + + open override func invalidateAndCancel() { + recording = false + outstandingTasks.removeAll() + backingSession.invalidateAndCancel() + } + + + // MARK: - Recording + + /// You don’t need to call this method if you're only recoding one request. + open func beginRecording() { + if recording { + return + } + + recording = true + needsPersistence = false + outstandingTasks = [] + completedInteractions = [] + completionBlock = nil + } + + /// This only needs to be called if you call `beginRecording`. `completion` will be called on the main queue after + /// the completion block of the last task is called. `completion` is useful for fulfilling an expectation you setup + /// before calling `beginRecording`. + open func endRecording(_ completion: (() -> Void)? = nil) { + if !recording { + return + } + + recording = false + completionBlock = completion + + if outstandingTasks.count == 0 { + finishRecording() + } + } + + + // MARK: - Internal + + var cassette: Cassette? { + guard let path = testBundle.path(forResource: cassetteName, ofType: "json"), + let data = try? Data(contentsOf: URL(fileURLWithPath: path)), + let raw = try? JSONSerialization.jsonObject(with: data, options: []), + let json = raw as? [String: Any] + else { return nil } + + return Cassette(dictionary: json) + } + + func finishTask(_ task: URLSessionTask, interaction: Interaction, playback: Bool) { + needsPersistence = needsPersistence || !playback + + if let index = outstandingTasks.firstIndex(of: task) { + outstandingTasks.remove(at: index) + } + + completedInteractions.append(interaction) + + if !recording && outstandingTasks.count == 0 { + finishRecording() + } + + if let delegate = delegate as? URLSessionDataDelegate, let task = task as? URLSessionDataTask, let data = interaction.responseData { + delegate.urlSession?(self, dataTask: task, didReceive: data as Data) + } + + if let delegate = delegate as? URLSessionTaskDelegate { + delegate.urlSession?(self, task: task, didCompleteWithError: nil) + } + } + + + // MARK: - Private + + private func addDataTask(_ request: URLRequest, completionHandler: ((Data?, Foundation.URLResponse?, NSError?) -> Void)? = nil) -> URLSessionDataTask { + let modifiedRequest = backingSession.configuration.httpAdditionalHeaders.map(request.appending) ?? request + let task = SessionDataTask(session: self, request: modifiedRequest, completion: completionHandler) + addTask(task) + return task + } + + private func addDownloadTask(_ request: URLRequest, completionHandler: SessionDownloadTask.Completion? = nil) -> URLSessionDownloadTask { + let modifiedRequest = backingSession.configuration.httpAdditionalHeaders.map(request.appending) ?? request + let task = SessionDownloadTask(session: self, request: modifiedRequest, completion: completionHandler) + addTask(task) + return task + } + + private func addUploadTask(_ request: URLRequest, fromData data: Data?, completionHandler: SessionUploadTask.Completion? = nil) -> URLSessionUploadTask { + var modifiedRequest = backingSession.configuration.httpAdditionalHeaders.map(request.appending) ?? request + modifiedRequest = data.map(modifiedRequest.appending) ?? modifiedRequest + let task = SessionUploadTask(session: self, request: modifiedRequest, completion: completionHandler) + addTask(task.dataTask) + return task + } + + private func addTask(_ task: URLSessionTask) { + let shouldRecord = !recording + if shouldRecord { + beginRecording() + } + + outstandingTasks.append(task) + + if shouldRecord { + endRecording() + } + } + + private func persist(_ interactions: [Interaction]) { + defer { + abort() + } + + // Create directory + let outputDirectory = (self.outputDirectory as NSString).expandingTildeInPath + let fileManager = FileManager.default + if !fileManager.fileExists(atPath: outputDirectory) { + do { + try fileManager.createDirectory(atPath: outputDirectory, withIntermediateDirectories: true, attributes: nil) + } catch { + print("[DVR] Failed to create cassettes directory.") + } + } + + let cassette = Cassette(name: cassetteName, interactions: interactions) + + // Persist + + + do { + let outputPath = ((outputDirectory as NSString).appendingPathComponent(cassetteName) as NSString).appendingPathExtension("json")! + let data = try JSONSerialization.data(withJSONObject: cassette.dictionary, options: [.prettyPrinted]) + + // Add trailing new line + guard var string = NSString(data: data, encoding: String.Encoding.utf8.rawValue) else { + print("[DVR] Failed to persist cassette.") + return + } + string = string.appending("\n") as NSString + + if let data = string.data(using: String.Encoding.utf8.rawValue) { + try? data.write(to: URL(fileURLWithPath: outputPath), options: [.atomic]) + print("[DVR] Persisted cassette at \(outputPath). Please add this file to your test target") + return + } + + print("[DVR] Failed to persist cassette.") + } catch { + print("[DVR] Failed to persist cassette.") + } + } + + private func finishRecording() { + if needsPersistence { + persist(completedInteractions) + } + + // Clean up + completedInteractions = [] + + // Call session’s completion block + completionBlock?() + } +} diff --git a/Pods/DVR/Sources/DVR/SessionDataTask.swift b/Pods/DVR/Sources/DVR/SessionDataTask.swift new file mode 100755 index 0000000..8ac1a3a --- /dev/null +++ b/Pods/DVR/Sources/DVR/SessionDataTask.swift @@ -0,0 +1,85 @@ +import Foundation + +final class SessionDataTask: URLSessionDataTask { + + // MARK: - Types + + typealias Completion = (Data?, Foundation.URLResponse?, NSError?) -> Void + + + // MARK: - Properties + + weak var session: Session! + let request: URLRequest + let completion: Completion? + private let queue = DispatchQueue(label: "com.venmo.DVR.sessionDataTaskQueue", attributes: []) + private var interaction: Interaction? + + override var response: Foundation.URLResponse? { + return interaction?.response + } + + + // MARK: - Initializers + + init(session: Session, request: URLRequest, completion: (Completion)? = nil) { + self.session = session + self.request = request + self.completion = completion + } + + + // MARK: - URLSessionTask + + override func cancel() { + // Don't do anything + } + + override func resume() { + let cassette = session.cassette + + // Find interaction + if let interaction = session.cassette?.interactionForRequest(request) { + self.interaction = interaction + // Forward completion + if let completion = completion { + queue.async { + completion(interaction.responseData, interaction.response, nil) + } + } + session.finishTask(self, interaction: interaction, playback: true) + return + } + + if cassette != nil { + fatalError("[DVR] Invalid request. The request was not found in the cassette.") + } + + // Cassette is missing. Record. + if session.recordingEnabled == false { + fatalError("[DVR] Recording is disabled.") + } + + let task = session.backingSession.dataTask(with: request, completionHandler: { [weak self] data, response, error in + + //Ensure we have a response + guard let response = response else { + fatalError("[DVR] Failed to record because the task returned a nil response.") + } + + guard let this = self else { + fatalError("[DVR] Something has gone horribly wrong.") + } + + // Still call the completion block so the user can chain requests while recording. + this.queue.async { + this.completion?(data, response, nil) + } + + // Create interaction + this.interaction = Interaction(request: this.request, response: response, responseData: data) + this.session.finishTask(this, interaction: this.interaction!, playback: false) + }) + task.resume() + } +} diff --git a/Pods/DVR/Sources/DVR/SessionDownloadTask.swift b/Pods/DVR/Sources/DVR/SessionDownloadTask.swift new file mode 100755 index 0000000..0cd70df --- /dev/null +++ b/Pods/DVR/Sources/DVR/SessionDownloadTask.swift @@ -0,0 +1,46 @@ +import Foundation + +final class SessionDownloadTask: URLSessionDownloadTask { + + // MARK: - Types + + typealias Completion = (URL?, Foundation.URLResponse?, NSError?) -> Void + + // MARK: - Properties + + weak var session: Session! + let request: URLRequest + let completion: Completion? + + + // MARK: - Initializers + + init(session: Session, request: URLRequest, completion: Completion? = nil) { + self.session = session + self.request = request + self.completion = completion + } + + // MARK: - URLSessionTask + + override func cancel() { + // Don't do anything + } + + override func resume() { + let task = SessionDataTask(session: session, request: request) { data, response, error in + let location: URL? + if let data = data { + // Write data to temporary file + let tempURL = URL(fileURLWithPath: (NSTemporaryDirectory() as NSString).appendingPathComponent(UUID().uuidString)) + try? data.write(to: tempURL, options: [.atomic]) + location = tempURL + } else { + location = nil + } + + self.completion?(location, response, error) + } + task.resume() + } +} diff --git a/Pods/DVR/Sources/DVR/SessionUploadTask.swift b/Pods/DVR/Sources/DVR/SessionUploadTask.swift new file mode 100755 index 0000000..fb66596 --- /dev/null +++ b/Pods/DVR/Sources/DVR/SessionUploadTask.swift @@ -0,0 +1,34 @@ +import Foundation + +final class SessionUploadTask: URLSessionUploadTask { + + // MARK: - Types + + typealias Completion = (Data?, Foundation.URLResponse?, NSError?) -> Void + + // MARK: - Properties + + weak var session: Session! + let request: URLRequest + let completion: Completion? + let dataTask: SessionDataTask + + // MARK: - Initializers + + init(session: Session, request: URLRequest, completion: Completion? = nil) { + self.session = session + self.request = request + self.completion = completion + dataTask = SessionDataTask(session: session, request: request, completion: completion) + } + + // MARK: - URLSessionTask + + override func cancel() { + // Don't do anything + } + + override func resume() { + dataTask.resume() + } +} diff --git a/Pods/DVR/Sources/DVR/URLRequest.swift b/Pods/DVR/Sources/DVR/URLRequest.swift new file mode 100755 index 0000000..8299383 --- /dev/null +++ b/Pods/DVR/Sources/DVR/URLRequest.swift @@ -0,0 +1,86 @@ +import Foundation + +extension URLRequest { + var dictionary: [String: Any] { + var dictionary = [String: Any]() + + if let method = httpMethod { + dictionary["method"] = method as Any? + } + + if let url = url?.absoluteString { + dictionary["url"] = url as Any? + } + + if let headers = allHTTPHeaderFields { + dictionary["headers"] = headers as Any? + } + + if let data = httpBody, let body = Interaction.encodeBody(data, headers: allHTTPHeaderFields) { + dictionary["body"] = body + } + + return dictionary + } +} + + +extension URLRequest { + func appending(headers: [AnyHashable: Any]) -> URLRequest { + guard let headers = headers as? [String: String] else { return self } + + var request = self + + for (key, value) in headers { + request.addValue(value, forHTTPHeaderField: key) + } + + return request + } + + func appending(body: Data?) -> URLRequest { + var request = self + request.httpBody = body + return request + } +} + + +extension NSMutableURLRequest { + convenience init(dictionary: [String: Any]) { + self.init() + + if let method = dictionary["method"] as? String { + httpMethod = method + } + + if let string = dictionary["url"] as? String, let url = URL(string: string) { + self.url = url + } + + if let headers = dictionary["headers"] as? [String: String] { + allHTTPHeaderFields = headers + } + + if let body = dictionary["body"] { + httpBody = Interaction.dencodeBody(body, headers: allHTTPHeaderFields) + } + } +} + + +extension NSMutableURLRequest { + func appendHeaders(_ headers: [AnyHashable: Any]) { + var existingHeaders = allHTTPHeaderFields ?? [:] + + headers.forEach { header in + guard let key = header.0 as? String, let value = header.1 as? String , existingHeaders[key] == nil else { + return + } + + existingHeaders[key] = value + } + + allHTTPHeaderFields = existingHeaders + } +} diff --git a/Pods/DVR/Sources/DVR/URLResponse.swift b/Pods/DVR/Sources/DVR/URLResponse.swift new file mode 100755 index 0000000..b5b4ba2 --- /dev/null +++ b/Pods/DVR/Sources/DVR/URLResponse.swift @@ -0,0 +1,37 @@ +import Foundation + +// There isn't a mutable URLResponse, so we have to make our own. +class URLResponse: Foundation.URLResponse { + private var _URL: Foundation.URL? + override var url: Foundation.URL? { + get { + return _URL ?? super.url + } + + set { + _URL = newValue + } + } +} + + +extension Foundation.URLResponse { + var dictionary: [String: Any] { + if let url = url?.absoluteString { + return ["url": url as Any] + } + + return [:] + } +} + + +extension URLResponse { + convenience init(dictionary: [String: Any]) { + self.init() + + if let string = dictionary["url"] as? String, let url = Foundation.URL(string: string) { + self.url = url + } + } +} diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock new file mode 100755 index 0000000..b5bd883 --- /dev/null +++ b/Pods/Manifest.lock @@ -0,0 +1,20 @@ +PODS: + - DVR (2.0.0) + - SAMKeychain (1.5.3) + +DEPENDENCIES: + - DVR + - SAMKeychain + +SPEC REPOS: + trunk: + - DVR + - SAMKeychain + +SPEC CHECKSUMS: + DVR: 062c287b9dc613a84120e44640176e4ef3ecf943 + SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c + +PODFILE CHECKSUM: 02c21c317ba9be4fdecdfff242f3fa20e9b269bd + +COCOAPODS: 1.8.4 diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj new file mode 100755 index 0000000..0a0633c --- /dev/null +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,1029 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 06807C205FE8C18B68229A21B79F2C0A /* SAMKeychainQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = F1E84E3242B3EB1E5E85DCC2E8B03EBC /* SAMKeychainQuery.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 0E740145DC8569F11C3D23161F42A3F3 /* SAMKeychainQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AEEE2832AFF20A6F549EC2A319C1A5A /* SAMKeychainQuery.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 180B0BC996F28420A22940BB965F2687 /* SAMKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = B63FFF6C3E3EC854DDA25565ECB653DF /* SAMKeychain.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 1B815895BB27D326F959D2E3C8C99302 /* URLRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68A7621ACBD07E7C91AB6184DDE51591 /* URLRequest.swift */; }; + 1F76FE48BAE3021631A8C0EC47758EA0 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 40C6FBEEEFA5DEBF6E6E83512D4F03EE /* Security.framework */; }; + 2550EA80C45F86FEFB6B484590C3127B /* SAMKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = B0545A9742888BED4846C62C54D0A65B /* SAMKeychain.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2581FFD24BA6040D51D1026A22D662A2 /* DVR-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A49D9706970C362DC8749280AFD7897 /* DVR-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 27A2EE4A3D8CCFC8A952A5456C9F16E0 /* Pods-fakestagramTests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 59A8492818977F5930B0AAAFD8AD5E42 /* Pods-fakestagramTests-dummy.m */; }; + 2CEE9A3A00184D730B23CD8A599D5C9B /* URLResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD323A0687C01A094A4398393F61D003 /* URLResponse.swift */; }; + 2F2DE653FDC005F2E921F46B3EE3E7D8 /* Pods-fakestagram-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 90BCDA4ADEBFA1F53BA12D6B569F08CC /* Pods-fakestagram-dummy.m */; }; + 3CBF47DECEC4BC7EF06674F7B94A39DE /* SessionUploadTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A0D780E187FAC62513FE66BABFDFD2 /* SessionUploadTask.swift */; }; + 48749968F49ABC19B218B6A650DA2EFA /* SAMKeychain.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 6A510F250C2F135F01D673AD47A38DE6 /* SAMKeychain.bundle */; }; + 4F467F8DE7756FE386809A1A36E8759C /* HTTPURLResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 311FE9B18E379AA65C325B06E9528351 /* HTTPURLResponse.swift */; }; + 824FE389846E821F786C40A28CC9B89E /* Pods-fakestagram-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 91F5BE5AE8BF396D2FFE3A083654F55D /* Pods-fakestagram-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8E68897246F917EC04BC035BADFF78C3 /* SessionDownloadTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 122017F22A2F0B330DC1A3C61F57F696 /* SessionDownloadTask.swift */; }; + 8E860D3F5EAA1B9BA6C8B0772356FCB6 /* Pods-fakestagramTests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E64F123CB3E44E23F1E2260C175ACABB /* Pods-fakestagramTests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 99BD442E3473FF1BD45267F99AF9FB17 /* Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = 718AC69AAFAF41AD67F09D13C8F3619E /* Session.swift */; }; + 9DF6D02518F1F91B36CEA39816658F98 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF0537674118F909E1B2AFD9940729FD /* Foundation.framework */; }; + A44705A450B7BC75180A9FC266CCFB3D /* SAMKeychain-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B550E0B60910515F7A99C95B9941DBF4 /* SAMKeychain-dummy.m */; }; + A89C15CBEAFACA18FD1704EAB020BAD1 /* Cassette.swift in Sources */ = {isa = PBXBuildFile; fileRef = B35816E22FFBA22812C78F4018E1216E /* Cassette.swift */; }; + ADC58AC3629C08D95E3F5D45CC0C6094 /* Interaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = D682B8F67556C7E2C4750006588D16A3 /* Interaction.swift */; }; + C050181AF88C681D976640BD1FCC41BB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF0537674118F909E1B2AFD9940729FD /* Foundation.framework */; }; + C2792E6A65FDBBF7261F1C6F21146FAE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF0537674118F909E1B2AFD9940729FD /* Foundation.framework */; }; + C62F2DC3C488FEB2A1C1E0FA31FCDE81 /* DVR-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 94825A1BAD66FA89734231732C9CC363 /* DVR-dummy.m */; }; + CCC0CABB1AADB1E1751D6FC4F8CC4DAC /* SAMKeychain-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F1B372698496D28CDA2D055E888C4348 /* SAMKeychain-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D6CE1DA5D5D86C699A9F9B5DD25BE95B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF0537674118F909E1B2AFD9940729FD /* Foundation.framework */; }; + F49DAB6CD6CE82D9AE54962891D2DF6B /* SessionDataTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD3978B6A33339DDA9D3ED2B69F53C81 /* SessionDataTask.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 17414ED8749102A3FA2A67AFBD067C61 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5572D14DECB5A676C1B31B30A3BA7F10; + remoteInfo = SAMKeychain; + }; + 86CA88CA94FD6858C9AC02D6320864DA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 61AEDBBA57E392B1F205C81674A649D6; + remoteInfo = "Pods-fakestagram"; + }; + BF29B87760F0FC7D925FA0F749D1A5DA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 26F44590B017B9CF61B71B978A6C48A9; + remoteInfo = DVR; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 053512BAF1A5A9D43C8DBE24A968B099 /* Pods-fakestagramTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-fakestagramTests.release.xcconfig"; sourceTree = ""; }; + 122017F22A2F0B330DC1A3C61F57F696 /* SessionDownloadTask.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SessionDownloadTask.swift; path = Sources/DVR/SessionDownloadTask.swift; sourceTree = ""; }; + 13933B2BA0EA9B8C7F04CB48B4D211EC /* Pods-fakestagramTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-fakestagramTests.debug.xcconfig"; sourceTree = ""; }; + 1413B6EBAE58CA3D1EB635F37FD0D8FB /* Pods-fakestagram-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-fakestagram-Info.plist"; sourceTree = ""; }; + 1AEEE2832AFF20A6F549EC2A319C1A5A /* SAMKeychainQuery.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SAMKeychainQuery.h; path = Sources/SAMKeychainQuery.h; sourceTree = ""; }; + 1E1EA3F1B3EB127825D5DB0D8EDFC9C7 /* DVR.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = DVR.framework; path = DVR.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F30323AA9315F80C09F38F3FA4FB6DB /* Pods_fakestagram.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_fakestagram.framework; path = "Pods-fakestagram.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 20BA74F50916A518C61868BDBE8A0A53 /* Pods-fakestagram.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-fakestagram.release.xcconfig"; sourceTree = ""; }; + 2CCCF5CA7CE74E382143A3DFF0C4EAF6 /* Pods-fakestagram-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-fakestagram-frameworks.sh"; sourceTree = ""; }; + 311FE9B18E379AA65C325B06E9528351 /* HTTPURLResponse.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HTTPURLResponse.swift; path = Sources/DVR/HTTPURLResponse.swift; sourceTree = ""; }; + 40C6FBEEEFA5DEBF6E6E83512D4F03EE /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + 583116C34718B4104B213A754C2F14AF /* Pods-fakestagramTests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-fakestagramTests-acknowledgements.markdown"; sourceTree = ""; }; + 59A8492818977F5930B0AAAFD8AD5E42 /* Pods-fakestagramTests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-fakestagramTests-dummy.m"; sourceTree = ""; }; + 612028EAFF1C2054A0EB821A9C9F2440 /* SAMKeychain.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SAMKeychain.framework; path = SAMKeychain.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6864987775489E2B6D4C815D5311D86F /* DVR-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "DVR-prefix.pch"; sourceTree = ""; }; + 68A569029EE104E8308612D026219115 /* Pods-fakestagramTests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-fakestagramTests-Info.plist"; sourceTree = ""; }; + 68A7621ACBD07E7C91AB6184DDE51591 /* URLRequest.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = URLRequest.swift; path = Sources/DVR/URLRequest.swift; sourceTree = ""; }; + 694C3B279742AA9A8DD64C3F11CC8EDA /* DVR.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = DVR.modulemap; sourceTree = ""; }; + 6A49D9706970C362DC8749280AFD7897 /* DVR-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "DVR-umbrella.h"; sourceTree = ""; }; + 6A510F250C2F135F01D673AD47A38DE6 /* SAMKeychain.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = SAMKeychain.bundle; path = Support/SAMKeychain.bundle; sourceTree = ""; }; + 718AC69AAFAF41AD67F09D13C8F3619E /* Session.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Session.swift; path = Sources/DVR/Session.swift; sourceTree = ""; }; + 84A0D780E187FAC62513FE66BABFDFD2 /* SessionUploadTask.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SessionUploadTask.swift; path = Sources/DVR/SessionUploadTask.swift; sourceTree = ""; }; + 85425238E1D910A19C2AFDA001348B9C /* DVR-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "DVR-Info.plist"; sourceTree = ""; }; + 90BCDA4ADEBFA1F53BA12D6B569F08CC /* Pods-fakestagram-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-fakestagram-dummy.m"; sourceTree = ""; }; + 91F5BE5AE8BF396D2FFE3A083654F55D /* Pods-fakestagram-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-fakestagram-umbrella.h"; sourceTree = ""; }; + 935B2EBEB5C8126CBD501146563B912A /* Pods_fakestagramTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_fakestagramTests.framework; path = "Pods-fakestagramTests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 94825A1BAD66FA89734231732C9CC363 /* DVR-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "DVR-dummy.m"; sourceTree = ""; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + A2B48B4990FCC0EBB3CF1968C2EE7F97 /* DVR.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = DVR.xcconfig; sourceTree = ""; }; + ADE202199E8AE3E45C7B773CA2F823F4 /* Pods-fakestagram-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-fakestagram-acknowledgements.plist"; sourceTree = ""; }; + B0545A9742888BED4846C62C54D0A65B /* SAMKeychain.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SAMKeychain.h; path = Sources/SAMKeychain.h; sourceTree = ""; }; + B35816E22FFBA22812C78F4018E1216E /* Cassette.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Cassette.swift; path = Sources/DVR/Cassette.swift; sourceTree = ""; }; + B550E0B60910515F7A99C95B9941DBF4 /* SAMKeychain-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SAMKeychain-dummy.m"; sourceTree = ""; }; + B63FFF6C3E3EC854DDA25565ECB653DF /* SAMKeychain.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SAMKeychain.m; path = Sources/SAMKeychain.m; sourceTree = ""; }; + CD323A0687C01A094A4398393F61D003 /* URLResponse.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = URLResponse.swift; path = Sources/DVR/URLResponse.swift; sourceTree = ""; }; + D682B8F67556C7E2C4750006588D16A3 /* Interaction.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Interaction.swift; path = Sources/DVR/Interaction.swift; sourceTree = ""; }; + D9D3551B5F195DE7A99E1E25F557E8DC /* Pods-fakestagramTests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-fakestagramTests-acknowledgements.plist"; sourceTree = ""; }; + E08D35AC1BA4D8EB4520D9E7A0363FB2 /* SAMKeychain-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SAMKeychain-prefix.pch"; sourceTree = ""; }; + E64F123CB3E44E23F1E2260C175ACABB /* Pods-fakestagramTests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-fakestagramTests-umbrella.h"; sourceTree = ""; }; + E96E855D25BDAB602D5D6FC1D6FF4980 /* SAMKeychain-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SAMKeychain-Info.plist"; sourceTree = ""; }; + EB9CD9D588692FFC8C171E8959FC6A5E /* Pods-fakestagramTests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-fakestagramTests-frameworks.sh"; sourceTree = ""; }; + ED561DD918F6540A952AB8AE94257DCF /* Pods-fakestagram.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-fakestagram.modulemap"; sourceTree = ""; }; + EF0537674118F909E1B2AFD9940729FD /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + EFBC1B690A9F27CF95FDD0D98628D8DA /* SAMKeychain.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SAMKeychain.xcconfig; sourceTree = ""; }; + F1B372698496D28CDA2D055E888C4348 /* SAMKeychain-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SAMKeychain-umbrella.h"; sourceTree = ""; }; + F1E84E3242B3EB1E5E85DCC2E8B03EBC /* SAMKeychainQuery.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SAMKeychainQuery.m; path = Sources/SAMKeychainQuery.m; sourceTree = ""; }; + F1F82FB9189506D61C6B7A94BC71DFA5 /* Pods-fakestagram-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-fakestagram-acknowledgements.markdown"; sourceTree = ""; }; + F79885221207B69427C47E713867DFD4 /* Pods-fakestagramTests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-fakestagramTests.modulemap"; sourceTree = ""; }; + F7E71CBB4B160B59D5219FC079FFBB1A /* Pods-fakestagram.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-fakestagram.debug.xcconfig"; sourceTree = ""; }; + FD0429D3D8416DC13AE06064AD1A268D /* SAMKeychain.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SAMKeychain.modulemap; sourceTree = ""; }; + FD3978B6A33339DDA9D3ED2B69F53C81 /* SessionDataTask.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SessionDataTask.swift; path = Sources/DVR/SessionDataTask.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4C4576A34B849022BE42DD796D17F6EC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9DF6D02518F1F91B36CEA39816658F98 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B3D5D6B487B493B2D48298B3DED84BD9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D6CE1DA5D5D86C699A9F9B5DD25BE95B /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C92F66CC4A5F2F7CEBEF011807241DFE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C050181AF88C681D976640BD1FCC41BB /* Foundation.framework in Frameworks */, + 1F76FE48BAE3021631A8C0EC47758EA0 /* Security.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D679A4D37A03CF5C6A767C980A64E61E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C2792E6A65FDBBF7261F1C6F21146FAE /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 6B475D44F9DE8B3EB70D1C14FDE147B9 /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + 1B2CC7483679035B85390AF56CA2B745 /* Products */ = { + isa = PBXGroup; + children = ( + 1E1EA3F1B3EB127825D5DB0D8EDFC9C7 /* DVR.framework */, + 1F30323AA9315F80C09F38F3FA4FB6DB /* Pods_fakestagram.framework */, + 935B2EBEB5C8126CBD501146563B912A /* Pods_fakestagramTests.framework */, + 612028EAFF1C2054A0EB821A9C9F2440 /* SAMKeychain.framework */, + ); + name = Products; + sourceTree = ""; + }; + 23FC5D5FCCEFDF054462B86E2E45F18E /* Resources */ = { + isa = PBXGroup; + children = ( + 6A510F250C2F135F01D673AD47A38DE6 /* SAMKeychain.bundle */, + ); + name = Resources; + sourceTree = ""; + }; + 4EE7C35955D73545FBF950BD9111503F /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + CA24EBD84B723DF2E72AA948AC765356 /* Pods-fakestagram */, + C6988779A6E720A4EB3777144850697B /* Pods-fakestagramTests */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + 6B475D44F9DE8B3EB70D1C14FDE147B9 /* iOS */ = { + isa = PBXGroup; + children = ( + EF0537674118F909E1B2AFD9940729FD /* Foundation.framework */, + 40C6FBEEEFA5DEBF6E6E83512D4F03EE /* Security.framework */, + ); + name = iOS; + sourceTree = ""; + }; + 7FAAF75322C60EEC429FE19549CAFE8B /* Support Files */ = { + isa = PBXGroup; + children = ( + 694C3B279742AA9A8DD64C3F11CC8EDA /* DVR.modulemap */, + A2B48B4990FCC0EBB3CF1968C2EE7F97 /* DVR.xcconfig */, + 94825A1BAD66FA89734231732C9CC363 /* DVR-dummy.m */, + 85425238E1D910A19C2AFDA001348B9C /* DVR-Info.plist */, + 6864987775489E2B6D4C815D5311D86F /* DVR-prefix.pch */, + 6A49D9706970C362DC8749280AFD7897 /* DVR-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/DVR"; + sourceTree = ""; + }; + 92D95B49133DFC1C864296A8A7B17B11 /* SAMKeychain */ = { + isa = PBXGroup; + children = ( + B0545A9742888BED4846C62C54D0A65B /* SAMKeychain.h */, + B63FFF6C3E3EC854DDA25565ECB653DF /* SAMKeychain.m */, + 1AEEE2832AFF20A6F549EC2A319C1A5A /* SAMKeychainQuery.h */, + F1E84E3242B3EB1E5E85DCC2E8B03EBC /* SAMKeychainQuery.m */, + 23FC5D5FCCEFDF054462B86E2E45F18E /* Resources */, + A6A92A0E14AEDCFF0D413455369BA437 /* Support Files */, + ); + name = SAMKeychain; + path = SAMKeychain; + sourceTree = ""; + }; + A6A92A0E14AEDCFF0D413455369BA437 /* Support Files */ = { + isa = PBXGroup; + children = ( + FD0429D3D8416DC13AE06064AD1A268D /* SAMKeychain.modulemap */, + EFBC1B690A9F27CF95FDD0D98628D8DA /* SAMKeychain.xcconfig */, + B550E0B60910515F7A99C95B9941DBF4 /* SAMKeychain-dummy.m */, + E96E855D25BDAB602D5D6FC1D6FF4980 /* SAMKeychain-Info.plist */, + E08D35AC1BA4D8EB4520D9E7A0363FB2 /* SAMKeychain-prefix.pch */, + F1B372698496D28CDA2D055E888C4348 /* SAMKeychain-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/SAMKeychain"; + sourceTree = ""; + }; + C6988779A6E720A4EB3777144850697B /* Pods-fakestagramTests */ = { + isa = PBXGroup; + children = ( + F79885221207B69427C47E713867DFD4 /* Pods-fakestagramTests.modulemap */, + 583116C34718B4104B213A754C2F14AF /* Pods-fakestagramTests-acknowledgements.markdown */, + D9D3551B5F195DE7A99E1E25F557E8DC /* Pods-fakestagramTests-acknowledgements.plist */, + 59A8492818977F5930B0AAAFD8AD5E42 /* Pods-fakestagramTests-dummy.m */, + EB9CD9D588692FFC8C171E8959FC6A5E /* Pods-fakestagramTests-frameworks.sh */, + 68A569029EE104E8308612D026219115 /* Pods-fakestagramTests-Info.plist */, + E64F123CB3E44E23F1E2260C175ACABB /* Pods-fakestagramTests-umbrella.h */, + 13933B2BA0EA9B8C7F04CB48B4D211EC /* Pods-fakestagramTests.debug.xcconfig */, + 053512BAF1A5A9D43C8DBE24A968B099 /* Pods-fakestagramTests.release.xcconfig */, + ); + name = "Pods-fakestagramTests"; + path = "Target Support Files/Pods-fakestagramTests"; + sourceTree = ""; + }; + CA24EBD84B723DF2E72AA948AC765356 /* Pods-fakestagram */ = { + isa = PBXGroup; + children = ( + ED561DD918F6540A952AB8AE94257DCF /* Pods-fakestagram.modulemap */, + F1F82FB9189506D61C6B7A94BC71DFA5 /* Pods-fakestagram-acknowledgements.markdown */, + ADE202199E8AE3E45C7B773CA2F823F4 /* Pods-fakestagram-acknowledgements.plist */, + 90BCDA4ADEBFA1F53BA12D6B569F08CC /* Pods-fakestagram-dummy.m */, + 2CCCF5CA7CE74E382143A3DFF0C4EAF6 /* Pods-fakestagram-frameworks.sh */, + 1413B6EBAE58CA3D1EB635F37FD0D8FB /* Pods-fakestagram-Info.plist */, + 91F5BE5AE8BF396D2FFE3A083654F55D /* Pods-fakestagram-umbrella.h */, + F7E71CBB4B160B59D5219FC079FFBB1A /* Pods-fakestagram.debug.xcconfig */, + 20BA74F50916A518C61868BDBE8A0A53 /* Pods-fakestagram.release.xcconfig */, + ); + name = "Pods-fakestagram"; + path = "Target Support Files/Pods-fakestagram"; + sourceTree = ""; + }; + CF1408CF629C7361332E53B88F7BD30C = { + isa = PBXGroup; + children = ( + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, + 1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */, + D83AA71E53446D48D21689E6E794CCF4 /* Pods */, + 1B2CC7483679035B85390AF56CA2B745 /* Products */, + 4EE7C35955D73545FBF950BD9111503F /* Targets Support Files */, + ); + sourceTree = ""; + }; + D83AA71E53446D48D21689E6E794CCF4 /* Pods */ = { + isa = PBXGroup; + children = ( + ED840B56367C1B27CC3CA5DAF7B3580A /* DVR */, + 92D95B49133DFC1C864296A8A7B17B11 /* SAMKeychain */, + ); + name = Pods; + sourceTree = ""; + }; + ED840B56367C1B27CC3CA5DAF7B3580A /* DVR */ = { + isa = PBXGroup; + children = ( + B35816E22FFBA22812C78F4018E1216E /* Cassette.swift */, + 311FE9B18E379AA65C325B06E9528351 /* HTTPURLResponse.swift */, + D682B8F67556C7E2C4750006588D16A3 /* Interaction.swift */, + 718AC69AAFAF41AD67F09D13C8F3619E /* Session.swift */, + FD3978B6A33339DDA9D3ED2B69F53C81 /* SessionDataTask.swift */, + 122017F22A2F0B330DC1A3C61F57F696 /* SessionDownloadTask.swift */, + 84A0D780E187FAC62513FE66BABFDFD2 /* SessionUploadTask.swift */, + 68A7621ACBD07E7C91AB6184DDE51591 /* URLRequest.swift */, + CD323A0687C01A094A4398393F61D003 /* URLResponse.swift */, + 7FAAF75322C60EEC429FE19549CAFE8B /* Support Files */, + ); + name = DVR; + path = DVR; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 6245C00F64E89DA283F0798C9544BB7B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 8E860D3F5EAA1B9BA6C8B0772356FCB6 /* Pods-fakestagramTests-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 784080E16476341D20781AF2902317C5 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 2581FFD24BA6040D51D1026A22D662A2 /* DVR-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + ADEF261B253DB102D68EBF8E235DA9FF /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CCC0CABB1AADB1E1751D6FC4F8CC4DAC /* SAMKeychain-umbrella.h in Headers */, + 2550EA80C45F86FEFB6B484590C3127B /* SAMKeychain.h in Headers */, + 0E740145DC8569F11C3D23161F42A3F3 /* SAMKeychainQuery.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E0F73066CC66D05653B61AFE5205EDC9 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 824FE389846E821F786C40A28CC9B89E /* Pods-fakestagram-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 26F44590B017B9CF61B71B978A6C48A9 /* DVR */ = { + isa = PBXNativeTarget; + buildConfigurationList = BB4A8EDF819F1F0E0B18EA4D9BF70600 /* Build configuration list for PBXNativeTarget "DVR" */; + buildPhases = ( + 784080E16476341D20781AF2902317C5 /* Headers */, + A9F19AE051CBB89DAFBD44FD2E39980F /* Sources */, + B3D5D6B487B493B2D48298B3DED84BD9 /* Frameworks */, + 821CB6386DC60F6A19F6CEAA2E7AEE0B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = DVR; + productName = DVR; + productReference = 1E1EA3F1B3EB127825D5DB0D8EDFC9C7 /* DVR.framework */; + productType = "com.apple.product-type.framework"; + }; + 37DFBE9967A351080A46211968162EDE /* Pods-fakestagramTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 50602180414D758F8D725517101D4C5B /* Build configuration list for PBXNativeTarget "Pods-fakestagramTests" */; + buildPhases = ( + 6245C00F64E89DA283F0798C9544BB7B /* Headers */, + F4B17D67EA1413FDE96A9A76FBECB97C /* Sources */, + 4C4576A34B849022BE42DD796D17F6EC /* Frameworks */, + 506D48D632D979E702F9FDBA4112059B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + C0EA27B480E84CF98928B1B8A341A924 /* PBXTargetDependency */, + 7CF03A27C10B968562A4216FD01FDD0C /* PBXTargetDependency */, + ); + name = "Pods-fakestagramTests"; + productName = "Pods-fakestagramTests"; + productReference = 935B2EBEB5C8126CBD501146563B912A /* Pods_fakestagramTests.framework */; + productType = "com.apple.product-type.framework"; + }; + 5572D14DECB5A676C1B31B30A3BA7F10 /* SAMKeychain */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D0BF722BE8E60C7D236665B49E830FF /* Build configuration list for PBXNativeTarget "SAMKeychain" */; + buildPhases = ( + ADEF261B253DB102D68EBF8E235DA9FF /* Headers */, + A63338510D2B653EDCDA5C95CBFCA292 /* Sources */, + C92F66CC4A5F2F7CEBEF011807241DFE /* Frameworks */, + E057DD10B33CF59170DCD03B6F66E50E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SAMKeychain; + productName = SAMKeychain; + productReference = 612028EAFF1C2054A0EB821A9C9F2440 /* SAMKeychain.framework */; + productType = "com.apple.product-type.framework"; + }; + 61AEDBBA57E392B1F205C81674A649D6 /* Pods-fakestagram */ = { + isa = PBXNativeTarget; + buildConfigurationList = 20A69520979FE10BFD5B0F0DBD12647E /* Build configuration list for PBXNativeTarget "Pods-fakestagram" */; + buildPhases = ( + E0F73066CC66D05653B61AFE5205EDC9 /* Headers */, + 44E4A6AD7438ABD266A86B72783800F1 /* Sources */, + D679A4D37A03CF5C6A767C980A64E61E /* Frameworks */, + BE5AC97192CFD183414F38C0752E98D7 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 4370C1ABA79BBD5765042F46F6F1D887 /* PBXTargetDependency */, + ); + name = "Pods-fakestagram"; + productName = "Pods-fakestagram"; + productReference = 1F30323AA9315F80C09F38F3FA4FB6DB /* Pods_fakestagram.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + BFDFE7DC352907FC980B868725387E98 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1100; + LastUpgradeCheck = 1100; + }; + buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 10.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = CF1408CF629C7361332E53B88F7BD30C; + productRefGroup = 1B2CC7483679035B85390AF56CA2B745 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 26F44590B017B9CF61B71B978A6C48A9 /* DVR */, + 61AEDBBA57E392B1F205C81674A649D6 /* Pods-fakestagram */, + 37DFBE9967A351080A46211968162EDE /* Pods-fakestagramTests */, + 5572D14DECB5A676C1B31B30A3BA7F10 /* SAMKeychain */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 506D48D632D979E702F9FDBA4112059B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 821CB6386DC60F6A19F6CEAA2E7AEE0B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BE5AC97192CFD183414F38C0752E98D7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E057DD10B33CF59170DCD03B6F66E50E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 48749968F49ABC19B218B6A650DA2EFA /* SAMKeychain.bundle in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 44E4A6AD7438ABD266A86B72783800F1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2F2DE653FDC005F2E921F46B3EE3E7D8 /* Pods-fakestagram-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A63338510D2B653EDCDA5C95CBFCA292 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A44705A450B7BC75180A9FC266CCFB3D /* SAMKeychain-dummy.m in Sources */, + 180B0BC996F28420A22940BB965F2687 /* SAMKeychain.m in Sources */, + 06807C205FE8C18B68229A21B79F2C0A /* SAMKeychainQuery.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A9F19AE051CBB89DAFBD44FD2E39980F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A89C15CBEAFACA18FD1704EAB020BAD1 /* Cassette.swift in Sources */, + C62F2DC3C488FEB2A1C1E0FA31FCDE81 /* DVR-dummy.m in Sources */, + 4F467F8DE7756FE386809A1A36E8759C /* HTTPURLResponse.swift in Sources */, + ADC58AC3629C08D95E3F5D45CC0C6094 /* Interaction.swift in Sources */, + 99BD442E3473FF1BD45267F99AF9FB17 /* Session.swift in Sources */, + F49DAB6CD6CE82D9AE54962891D2DF6B /* SessionDataTask.swift in Sources */, + 8E68897246F917EC04BC035BADFF78C3 /* SessionDownloadTask.swift in Sources */, + 3CBF47DECEC4BC7EF06674F7B94A39DE /* SessionUploadTask.swift in Sources */, + 1B815895BB27D326F959D2E3C8C99302 /* URLRequest.swift in Sources */, + 2CEE9A3A00184D730B23CD8A599D5C9B /* URLResponse.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F4B17D67EA1413FDE96A9A76FBECB97C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 27A2EE4A3D8CCFC8A952A5456C9F16E0 /* Pods-fakestagramTests-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 4370C1ABA79BBD5765042F46F6F1D887 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SAMKeychain; + target = 5572D14DECB5A676C1B31B30A3BA7F10 /* SAMKeychain */; + targetProxy = 17414ED8749102A3FA2A67AFBD067C61 /* PBXContainerItemProxy */; + }; + 7CF03A27C10B968562A4216FD01FDD0C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Pods-fakestagram"; + target = 61AEDBBA57E392B1F205C81674A649D6 /* Pods-fakestagram */; + targetProxy = 86CA88CA94FD6858C9AC02D6320864DA /* PBXContainerItemProxy */; + }; + C0EA27B480E84CF98928B1B8A341A924 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = DVR; + target = 26F44590B017B9CF61B71B978A6C48A9 /* DVR */; + targetProxy = BF29B87760F0FC7D925FA0F749D1A5DA /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 1422B121EAEAEA11307496903FA623C6 /* 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; + 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 = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + 3547A182D8304E546E03392FE52804C4 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 20BA74F50916A518C61868BDBE8A0A53 /* Pods-fakestagram.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-fakestagram/Pods-fakestagram-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-fakestagram/Pods-fakestagram.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; + }; + 53E59C198B6DC3AF5B94923214D99515 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 13933B2BA0EA9B8C7F04CB48B4D211EC /* Pods-fakestagramTests.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*]" = ""; + "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-fakestagramTests/Pods-fakestagramTests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.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; + }; + 5B8944E8CB02AEF5B66B2727234DA374 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F7E71CBB4B160B59D5219FC079FFBB1A /* Pods-fakestagram.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*]" = ""; + "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-fakestagram/Pods-fakestagram-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-fakestagram/Pods-fakestagram.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; + }; + 80B8E3CCEC8B37739AF5D737CD55445B /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EFBC1B690A9F27CF95FDD0D98628D8DA /* SAMKeychain.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/SAMKeychain/SAMKeychain-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SAMKeychain/SAMKeychain-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/SAMKeychain/SAMKeychain.modulemap"; + PRODUCT_MODULE_NAME = SAMKeychain; + PRODUCT_NAME = SAMKeychain; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 84D002ED109032D26D7727656816360D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 053512BAF1A5A9D43C8DBE24A968B099 /* Pods-fakestagramTests.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-fakestagramTests/Pods-fakestagramTests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.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; + }; + 8D404CBFE53B67F33C3EB2ED8ECEADEB /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A2B48B4990FCC0EBB3CF1968C2EE7F97 /* DVR.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/DVR/DVR-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/DVR/DVR-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/DVR/DVR.modulemap"; + PRODUCT_MODULE_NAME = DVR; + PRODUCT_NAME = DVR; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 97172E77B9DF71E94D334322B5D9A612 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A2B48B4990FCC0EBB3CF1968C2EE7F97 /* DVR.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/DVR/DVR-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/DVR/DVR-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/DVR/DVR.modulemap"; + PRODUCT_MODULE_NAME = DVR; + PRODUCT_NAME = DVR; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + A7E6A10383C96330489D1B81BEC6B474 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EFBC1B690A9F27CF95FDD0D98628D8DA /* SAMKeychain.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/SAMKeychain/SAMKeychain-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SAMKeychain/SAMKeychain-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/SAMKeychain/SAMKeychain.modulemap"; + PRODUCT_MODULE_NAME = SAMKeychain; + PRODUCT_NAME = SAMKeychain; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + ED7888FA6713EABBF66D26A8003AD1CA /* 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; + 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 = 13.0; + 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 = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 20A69520979FE10BFD5B0F0DBD12647E /* Build configuration list for PBXNativeTarget "Pods-fakestagram" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5B8944E8CB02AEF5B66B2727234DA374 /* Debug */, + 3547A182D8304E546E03392FE52804C4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + ED7888FA6713EABBF66D26A8003AD1CA /* Debug */, + 1422B121EAEAEA11307496903FA623C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 50602180414D758F8D725517101D4C5B /* Build configuration list for PBXNativeTarget "Pods-fakestagramTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 53E59C198B6DC3AF5B94923214D99515 /* Debug */, + 84D002ED109032D26D7727656816360D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D0BF722BE8E60C7D236665B49E830FF /* Build configuration list for PBXNativeTarget "SAMKeychain" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 80B8E3CCEC8B37739AF5D737CD55445B /* Debug */, + A7E6A10383C96330489D1B81BEC6B474 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + BB4A8EDF819F1F0E0B18EA4D9BF70600 /* Build configuration list for PBXNativeTarget "DVR" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97172E77B9DF71E94D334322B5D9A612 /* Debug */, + 8D404CBFE53B67F33C3EB2ED8ECEADEB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; +} diff --git a/Pods/Pods.xcodeproj/xcuserdata/jolvera.xcuserdatad/xcschemes/xcschememanagement.plist b/Pods/Pods.xcodeproj/xcuserdata/jolvera.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..ab1da4b --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/jolvera.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,29 @@ + + + + + SchemeUserState + + DVR.xcscheme_^#shared#^_ + + orderHint + 1 + + Pods-fakestagram.xcscheme_^#shared#^_ + + orderHint + 2 + + Pods-fakestagramTests.xcscheme_^#shared#^_ + + orderHint + 3 + + SAMKeychain.xcscheme_^#shared#^_ + + orderHint + 4 + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/DVR.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/DVR.xcscheme new file mode 100755 index 0000000..0f901e0 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/DVR.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/Pods-fakestagram.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/Pods-fakestagram.xcscheme new file mode 100755 index 0000000..32f2715 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/Pods-fakestagram.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/Pods-fakestagramTests.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/Pods-fakestagramTests.xcscheme new file mode 100755 index 0000000..4f5af4e --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/Pods-fakestagramTests.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/SAMKeychain.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/SAMKeychain.xcscheme new file mode 100755 index 0000000..8cb3dd4 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/SAMKeychain.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/xcschememanagement.plist b/Pods/Pods.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100755 index 0000000..4b967f8 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,39 @@ + + + + + SchemeUserState + + DVR.xcscheme + + isShown + + orderHint + 0 + + Pods-fakestagram.xcscheme + + isShown + + orderHint + 1 + + Pods-fakestagramTests.xcscheme + + isShown + + orderHint + 2 + + SAMKeychain.xcscheme + + isShown + + orderHint + 3 + + + SuppressBuildableAutocreation + + + diff --git a/Pods/SAMKeychain/LICENSE b/Pods/SAMKeychain/LICENSE new file mode 100755 index 0000000..21fe4ef --- /dev/null +++ b/Pods/SAMKeychain/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2010-2016 Sam Soffes, http://soff.es + +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. diff --git a/Pods/SAMKeychain/Readme.markdown b/Pods/SAMKeychain/Readme.markdown new file mode 100755 index 0000000..fbd8d96 --- /dev/null +++ b/Pods/SAMKeychain/Readme.markdown @@ -0,0 +1,87 @@ +# SAMKeychain + +[![Version](https://img.shields.io/github/release/soffes/SAMKeychain.svg)](https://github.com/soffes/SAMKeychain/releases) +[![CocoaPods](https://img.shields.io/cocoapods/v/SAMKeychain.svg)](https://cocoapods.org/pods/SAMKeychain) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) + +SAMKeychain is a simple wrapper for accessing accounts, getting passwords, setting passwords, and deleting passwords using the system Keychain on Mac OS X and iOS. + +## Adding to Your Project + +Simply add the following to your Podfile if you're using CocoaPods: + +``` ruby +pod 'SAMKeychain' +``` + +or Cartfile if you're using Carthage: + +``` +github "soffes/SAMKeychain" +``` + +To manually add to your project: + +1. Add `Security.framework` to your target +2. Add `SAMKeychain.h`, `SAMKeychain.m`, `SAMKeychainQuery.h`, and `SAMKeychainQuery.m` to your project. + +SAMKeychain requires ARC. + +Note: Currently SAMKeychain does not support Mac OS 10.6. + +## Working with the Keychain + +SAMKeychain has the following class methods for working with the system keychain: + +```objective-c ++ (NSArray *)allAccounts; ++ (NSArray *)accountsForService:(NSString *)serviceName; ++ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account; ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account; ++ (void)setAccessibilityType:(CFTypeRef)accessibilityType; ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account; +``` + +Easy as that. (See [SAMKeychain.h](https://github.com/soffes/samkeychain/blob/master/Sources/SAMKeychain.h) and [SAMKeychainQuery.h](https://github.com/soffes/samkeychain/blob/master/Sources/SAMKeychainQuery.h) for all of the methods.) + + +## Documentation + +### Use prepared documentation + +Read the [online documentation](http://cocoadocs.org/docsets/SAMKeychain). + +## Debugging + +If your saving to the keychain fails, use the NSError object to handle it. You can invoke `[error code]` to get the numeric error code. A few values are defined in SAMKeychain.h, and the rest in SecBase.h. + +```objective-c +NSError *error = nil; +SAMKeychainQuery *query = [[SAMKeychainQuery alloc] init]; +query.service = @"MyService"; +query.account = @"soffes"; +[query fetch:&error]; + +if ([error code] == errSecItemNotFound) { + NSLog(@"Password not found"); +} else if (error != nil) { + NSLog(@"Some other error occurred: %@", [error localizedDescription]); +} +``` + +Obviously, you should do something more sophisticated. You can just call `[error localizedDescription]` if all you need is the error message. + +## Disclaimer + +Working with the keychain is pretty sucky. You should really check for errors and failures. This library doesn't make it any more stable, it just wraps up all of the annoying C APIs. + +You also really should not use the default but set the `accessibilityType`. +`kSecAttrAccessibleWhenUnlocked` should work for most applications. See +[Apple Documentation](https://developer.apple.com/library/ios/DOCUMENTATION/Security/Reference/keychainservices/Reference/reference.html#//apple_ref/doc/constant_group/Keychain_Item_Accessibility_Constants) +for other options. + +## Thanks + +This was originally inspired by EMKeychain and SDKeychain (both of which are now gone). Thanks to the authors. SAMKeychain has since switched to a simpler implementation that was abstracted from [SSToolkit](https://github.com/soffes/sstoolkit). + +A huge thanks to [Caleb Davenport](https://github.com/calebd) for leading the way on version 1.0 of SAMKeychain. diff --git a/Pods/SAMKeychain/Sources/SAMKeychain.h b/Pods/SAMKeychain/Sources/SAMKeychain.h new file mode 100755 index 0000000..2af305d --- /dev/null +++ b/Pods/SAMKeychain/Sources/SAMKeychain.h @@ -0,0 +1,203 @@ +// +// SAMKeychain.h +// SAMKeychain +// +// Created by Sam Soffes on 5/19/10. +// Copyright (c) 2010-2014 Sam Soffes. All rights reserved. +// + +#if __has_feature(modules) + @import Foundation; +#else + #import +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** + Error code specific to SAMKeychain that can be returned in NSError objects. + For codes returned by the operating system, refer to SecBase.h for your + platform. + */ +typedef NS_ENUM(OSStatus, SAMKeychainErrorCode) { + /** Some of the arguments were invalid. */ + SAMKeychainErrorBadArguments = -1001, +}; + +/** SAMKeychain error domain */ +extern NSString *const kSAMKeychainErrorDomain; + +/** Account name. */ +extern NSString *const kSAMKeychainAccountKey; + +/** + Time the item was created. + + The value will be a string. + */ +extern NSString *const kSAMKeychainCreatedAtKey; + +/** Item class. */ +extern NSString *const kSAMKeychainClassKey; + +/** Item description. */ +extern NSString *const kSAMKeychainDescriptionKey; + +/** Item label. */ +extern NSString *const kSAMKeychainLabelKey; + +/** Time the item was last modified. + + The value will be a string. + */ +extern NSString *const kSAMKeychainLastModifiedKey; + +/** Where the item was created. */ +extern NSString *const kSAMKeychainWhereKey; + +/** + Simple wrapper for accessing accounts, getting passwords, setting passwords, and deleting passwords using the system + Keychain on Mac OS X and iOS. + + This was originally inspired by EMKeychain and SDKeychain (both of which are now gone). Thanks to the authors. + SAMKeychain has since switched to a simpler implementation that was abstracted from [SSToolkit](http://sstoolk.it). + */ +@interface SAMKeychain : NSObject + +#pragma mark - Classic methods + +/** + Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't have a + password for the given parameters. + + @param serviceName The service for which to return the corresponding password. + + @param account The account for which to return the corresponding password. + + @return Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't + have a password for the given parameters. + */ ++ (nullable NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account; ++ (nullable NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error __attribute__((swift_error(none))); + +/** + Returns a nsdata containing the password for a given account and service, or `nil` if the Keychain doesn't have a + password for the given parameters. + + @param serviceName The service for which to return the corresponding password. + + @param account The account for which to return the corresponding password. + + @return Returns a nsdata containing the password for a given account and service, or `nil` if the Keychain doesn't + have a password for the given parameters. + */ ++ (nullable NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account; ++ (nullable NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error __attribute__((swift_error(none))); + + +/** + Deletes a password from the Keychain. + + @param serviceName The service for which to delete the corresponding password. + + @param account The account for which to delete the corresponding password. + + @return Returns `YES` on success, or `NO` on failure. + */ ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account; ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error __attribute__((swift_error(none))); + + +/** + Sets a password in the Keychain. + + @param password The password to store in the Keychain. + + @param serviceName The service for which to set the corresponding password. + + @param account The account for which to set the corresponding password. + + @return Returns `YES` on success, or `NO` on failure. + */ ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account; ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error __attribute__((swift_error(none))); + +/** + Sets a password in the Keychain. + + @param password The password to store in the Keychain. + + @param serviceName The service for which to set the corresponding password. + + @param account The account for which to set the corresponding password. + + @return Returns `YES` on success, or `NO` on failure. + */ ++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account; ++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error __attribute__((swift_error(none))); + +/** + Returns an array containing the Keychain's accounts, or `nil` if the Keychain has no accounts. + + See the `NSString` constants declared in SAMKeychain.h for a list of keys that can be used when accessing the + dictionaries returned by this method. + + @return An array of dictionaries containing the Keychain's accounts, or `nil` if the Keychain doesn't have any + accounts. The order of the objects in the array isn't defined. + */ ++ (nullable NSArray *> *)allAccounts; ++ (nullable NSArray *> *)allAccounts:(NSError *__autoreleasing *)error __attribute__((swift_error(none))); + + +/** + Returns an array containing the Keychain's accounts for a given service, or `nil` if the Keychain doesn't have any + accounts for the given service. + + See the `NSString` constants declared in SAMKeychain.h for a list of keys that can be used when accessing the + dictionaries returned by this method. + + @param serviceName The service for which to return the corresponding accounts. + + @return An array of dictionaries containing the Keychain's accounts for a given `serviceName`, or `nil` if the Keychain + doesn't have any accounts for the given `serviceName`. The order of the objects in the array isn't defined. + */ ++ (nullable NSArray *> *)accountsForService:(nullable NSString *)serviceName; ++ (nullable NSArray *> *)accountsForService:(nullable NSString *)serviceName error:(NSError *__autoreleasing *)error __attribute__((swift_error(none))); + + +#pragma mark - Configuration + +#if __IPHONE_4_0 && TARGET_OS_IPHONE +/** + Returns the accessibility type for all future passwords saved to the Keychain. + + @return Returns the accessibility type. + + The return value will be `NULL` or one of the "Keychain Item Accessibility + Constants" used for determining when a keychain item should be readable. + + @see setAccessibilityType + */ ++ (CFTypeRef)accessibilityType; + +/** + Sets the accessibility type for all future passwords saved to the Keychain. + + @param accessibilityType One of the "Keychain Item Accessibility Constants" + used for determining when a keychain item should be readable. + + If the value is `NULL` (the default), the Keychain default will be used which + is highly insecure. You really should use at least `kSecAttrAccessibleAfterFirstUnlock` + for background applications or `kSecAttrAccessibleWhenUnlocked` for all + other applications. + + @see accessibilityType + */ ++ (void)setAccessibilityType:(CFTypeRef)accessibilityType; +#endif + +@end + +NS_ASSUME_NONNULL_END + +#import diff --git a/Pods/SAMKeychain/Sources/SAMKeychain.m b/Pods/SAMKeychain/Sources/SAMKeychain.m new file mode 100755 index 0000000..6d01d3d --- /dev/null +++ b/Pods/SAMKeychain/Sources/SAMKeychain.m @@ -0,0 +1,130 @@ +// +// SAMKeychain.m +// SAMKeychain +// +// Created by Sam Soffes on 5/19/10. +// Copyright (c) 2010-2014 Sam Soffes. All rights reserved. +// + +#import "SAMKeychain.h" +#import "SAMKeychainQuery.h" + +NSString *const kSAMKeychainErrorDomain = @"com.samsoffes.samkeychain"; +NSString *const kSAMKeychainAccountKey = @"acct"; +NSString *const kSAMKeychainCreatedAtKey = @"cdat"; +NSString *const kSAMKeychainClassKey = @"labl"; +NSString *const kSAMKeychainDescriptionKey = @"desc"; +NSString *const kSAMKeychainLabelKey = @"labl"; +NSString *const kSAMKeychainLastModifiedKey = @"mdat"; +NSString *const kSAMKeychainWhereKey = @"svce"; + +#if __IPHONE_4_0 && TARGET_OS_IPHONE + static CFTypeRef SAMKeychainAccessibilityType = NULL; +#endif + +@implementation SAMKeychain + ++ (nullable NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account { + return [self passwordForService:serviceName account:account error:nil]; +} + + ++ (nullable NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError *__autoreleasing *)error { + SAMKeychainQuery *query = [[SAMKeychainQuery alloc] init]; + query.service = serviceName; + query.account = account; + [query fetch:error]; + return query.password; +} + ++ (nullable NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account { + return [self passwordDataForService:serviceName account:account error:nil]; +} + ++ (nullable NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error { + SAMKeychainQuery *query = [[SAMKeychainQuery alloc] init]; + query.service = serviceName; + query.account = account; + [query fetch:error]; + + return query.passwordData; +} + + ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account { + return [self deletePasswordForService:serviceName account:account error:nil]; +} + + ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError *__autoreleasing *)error { + SAMKeychainQuery *query = [[SAMKeychainQuery alloc] init]; + query.service = serviceName; + query.account = account; + return [query deleteItem:error]; +} + + ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account { + return [self setPassword:password forService:serviceName account:account error:nil]; +} + + ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError *__autoreleasing *)error { + SAMKeychainQuery *query = [[SAMKeychainQuery alloc] init]; + query.service = serviceName; + query.account = account; + query.password = password; + return [query save:error]; +} + ++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account { + return [self setPasswordData:password forService:serviceName account:account error:nil]; +} + + ++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error { + SAMKeychainQuery *query = [[SAMKeychainQuery alloc] init]; + query.service = serviceName; + query.account = account; + query.passwordData = password; + return [query save:error]; +} + ++ (nullable NSArray *)allAccounts { + return [self allAccounts:nil]; +} + + ++ (nullable NSArray *)allAccounts:(NSError *__autoreleasing *)error { + return [self accountsForService:nil error:error]; +} + + ++ (nullable NSArray *)accountsForService:(nullable NSString *)serviceName { + return [self accountsForService:serviceName error:nil]; +} + + ++ (nullable NSArray *)accountsForService:(nullable NSString *)serviceName error:(NSError *__autoreleasing *)error { + SAMKeychainQuery *query = [[SAMKeychainQuery alloc] init]; + query.service = serviceName; + return [query fetchAll:error]; +} + + +#if __IPHONE_4_0 && TARGET_OS_IPHONE ++ (CFTypeRef)accessibilityType { + return SAMKeychainAccessibilityType; +} + + ++ (void)setAccessibilityType:(CFTypeRef)accessibilityType { + CFRetain(accessibilityType); + if (SAMKeychainAccessibilityType) { + CFRelease(SAMKeychainAccessibilityType); + } + SAMKeychainAccessibilityType = accessibilityType; +} +#endif + +@end diff --git a/Pods/SAMKeychain/Sources/SAMKeychainQuery.h b/Pods/SAMKeychain/Sources/SAMKeychainQuery.h new file mode 100755 index 0000000..84658e2 --- /dev/null +++ b/Pods/SAMKeychain/Sources/SAMKeychainQuery.h @@ -0,0 +1,147 @@ +// +// SAMKeychainQuery.h +// SAMKeychain +// +// Created by Caleb Davenport on 3/19/13. +// Copyright (c) 2013-2014 Sam Soffes. All rights reserved. +// + +#if __has_feature(modules) + @import Foundation; + @import Security; +#else + #import + #import +#endif + +NS_ASSUME_NONNULL_BEGIN + +#if __IPHONE_7_0 || __MAC_10_9 + // Keychain synchronization available at compile time + #define SAMKEYCHAIN_SYNCHRONIZATION_AVAILABLE 1 +#endif + +#if __IPHONE_3_0 || __MAC_10_9 + // Keychain access group available at compile time + #define SAMKEYCHAIN_ACCESS_GROUP_AVAILABLE 1 +#endif + +#ifdef SAMKEYCHAIN_SYNCHRONIZATION_AVAILABLE +typedef NS_ENUM(NSUInteger, SAMKeychainQuerySynchronizationMode) { + SAMKeychainQuerySynchronizationModeAny, + SAMKeychainQuerySynchronizationModeNo, + SAMKeychainQuerySynchronizationModeYes +}; +#endif + +/** + Simple interface for querying or modifying keychain items. + */ +@interface SAMKeychainQuery : NSObject + +/** kSecAttrAccount */ +@property (nonatomic, copy, nullable) NSString *account; + +/** kSecAttrService */ +@property (nonatomic, copy, nullable) NSString *service; + +/** kSecAttrLabel */ +@property (nonatomic, copy, nullable) NSString *label; + +#ifdef SAMKEYCHAIN_ACCESS_GROUP_AVAILABLE +/** kSecAttrAccessGroup (only used on iOS) */ +@property (nonatomic, copy, nullable) NSString *accessGroup; +#endif + +#ifdef SAMKEYCHAIN_SYNCHRONIZATION_AVAILABLE +/** kSecAttrSynchronizable */ +@property (nonatomic) SAMKeychainQuerySynchronizationMode synchronizationMode; +#endif + +/** Root storage for password information */ +@property (nonatomic, copy, nullable) NSData *passwordData; + +/** + This property automatically transitions between an object and the value of + `passwordData` using NSKeyedArchiver and NSKeyedUnarchiver. + */ +@property (nonatomic, copy, nullable) id passwordObject; + +/** + Convenience accessor for setting and getting a password string. Passes through + to `passwordData` using UTF-8 string encoding. + */ +@property (nonatomic, copy, nullable) NSString *password; + + +///------------------------ +/// @name Saving & Deleting +///------------------------ + +/** + Save the receiver's attributes as a keychain item. Existing items with the + given account, service, and access group will first be deleted. + + @param error Populated should an error occur. + + @return `YES` if saving was successful, `NO` otherwise. + */ +- (BOOL)save:(NSError **)error; + +/** + Delete keychain items that match the given account, service, and access group. + + @param error Populated should an error occur. + + @return `YES` if saving was successful, `NO` otherwise. + */ +- (BOOL)deleteItem:(NSError **)error; + + +///--------------- +/// @name Fetching +///--------------- + +/** + Fetch all keychain items that match the given account, service, and access + group. The values of `password` and `passwordData` are ignored when fetching. + + @param error Populated should an error occur. + + @return An array of dictionaries that represent all matching keychain items or + `nil` should an error occur. + The order of the items is not determined. + */ +- (nullable NSArray *> *)fetchAll:(NSError **)error; + +/** + Fetch the keychain item that matches the given account, service, and access + group. The `password` and `passwordData` properties will be populated unless + an error occurs. The values of `password` and `passwordData` are ignored when + fetching. + + @param error Populated should an error occur. + + @return `YES` if fetching was successful, `NO` otherwise. + */ +- (BOOL)fetch:(NSError **)error; + + +///----------------------------- +/// @name Synchronization Status +///----------------------------- + +#ifdef SAMKEYCHAIN_SYNCHRONIZATION_AVAILABLE +/** + Returns a boolean indicating if keychain synchronization is available on the device at runtime. The #define + SAMKEYCHAIN_SYNCHRONIZATION_AVAILABLE is only for compile time. If you are checking for the presence of synchronization, + you should use this method. + + @return A value indicating if keychain synchronization is available + */ ++ (BOOL)isSynchronizationAvailable; +#endif + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/SAMKeychain/Sources/SAMKeychainQuery.m b/Pods/SAMKeychain/Sources/SAMKeychainQuery.m new file mode 100755 index 0000000..00ecb80 --- /dev/null +++ b/Pods/SAMKeychain/Sources/SAMKeychainQuery.m @@ -0,0 +1,316 @@ +// +// SAMKeychainQuery.m +// SAMKeychain +// +// Created by Caleb Davenport on 3/19/13. +// Copyright (c) 2013-2014 Sam Soffes. All rights reserved. +// + +#import "SAMKeychainQuery.h" +#import "SAMKeychain.h" + +@implementation SAMKeychainQuery + +@synthesize account = _account; +@synthesize service = _service; +@synthesize label = _label; +@synthesize passwordData = _passwordData; + +#ifdef SAMKEYCHAIN_ACCESS_GROUP_AVAILABLE +@synthesize accessGroup = _accessGroup; +#endif + +#ifdef SAMKEYCHAIN_SYNCHRONIZATION_AVAILABLE +@synthesize synchronizationMode = _synchronizationMode; +#endif + +#pragma mark - Public + +- (BOOL)save:(NSError *__autoreleasing *)error { + OSStatus status = SAMKeychainErrorBadArguments; + if (!self.service || !self.account || !self.passwordData) { + if (error) { + *error = [[self class] errorWithCode:status]; + } + return NO; + } + NSMutableDictionary *query = nil; + NSMutableDictionary * searchQuery = [self query]; + status = SecItemCopyMatching((__bridge CFDictionaryRef)searchQuery, nil); + if (status == errSecSuccess) {//item already exists, update it! + query = [[NSMutableDictionary alloc]init]; + [query setObject:self.passwordData forKey:(__bridge id)kSecValueData]; +#if __IPHONE_4_0 && TARGET_OS_IPHONE + CFTypeRef accessibilityType = [SAMKeychain accessibilityType]; + if (accessibilityType) { + [query setObject:(__bridge id)accessibilityType forKey:(__bridge id)kSecAttrAccessible]; + } +#endif + status = SecItemUpdate((__bridge CFDictionaryRef)(searchQuery), (__bridge CFDictionaryRef)(query)); + }else if(status == errSecItemNotFound){//item not found, create it! + query = [self query]; + if (self.label) { + [query setObject:self.label forKey:(__bridge id)kSecAttrLabel]; + } + [query setObject:self.passwordData forKey:(__bridge id)kSecValueData]; +#if __IPHONE_4_0 && TARGET_OS_IPHONE + CFTypeRef accessibilityType = [SAMKeychain accessibilityType]; + if (accessibilityType) { + [query setObject:(__bridge id)accessibilityType forKey:(__bridge id)kSecAttrAccessible]; + } +#endif + status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); + } + if (status != errSecSuccess && error != NULL) { + *error = [[self class] errorWithCode:status]; + } + return (status == errSecSuccess);} + + +- (BOOL)deleteItem:(NSError *__autoreleasing *)error { + OSStatus status = SAMKeychainErrorBadArguments; + if (!self.service || !self.account) { + if (error) { + *error = [[self class] errorWithCode:status]; + } + return NO; + } + + NSMutableDictionary *query = [self query]; +#if TARGET_OS_IPHONE + status = SecItemDelete((__bridge CFDictionaryRef)query); +#else + // On Mac OS, SecItemDelete will not delete a key created in a different + // app, nor in a different version of the same app. + // + // To replicate the issue, save a password, change to the code and + // rebuild the app, and then attempt to delete that password. + // + // This was true in OS X 10.6 and probably later versions as well. + // + // Work around it by using SecItemCopyMatching and SecKeychainItemDelete. + CFTypeRef result = NULL; + [query setObject:@YES forKey:(__bridge id)kSecReturnRef]; + status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); + if (status == errSecSuccess) { + status = SecKeychainItemDelete((SecKeychainItemRef)result); + CFRelease(result); + } +#endif + + if (status != errSecSuccess && error != NULL) { + *error = [[self class] errorWithCode:status]; + } + + return (status == errSecSuccess); +} + + +- (nullable NSArray *)fetchAll:(NSError *__autoreleasing *)error { + NSMutableDictionary *query = [self query]; + [query setObject:@YES forKey:(__bridge id)kSecReturnAttributes]; + [query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit]; +#if __IPHONE_4_0 && TARGET_OS_IPHONE + CFTypeRef accessibilityType = [SAMKeychain accessibilityType]; + if (accessibilityType) { + [query setObject:(__bridge id)accessibilityType forKey:(__bridge id)kSecAttrAccessible]; + } +#endif + + CFTypeRef result = NULL; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); + if (status != errSecSuccess && error != NULL) { + *error = [[self class] errorWithCode:status]; + return nil; + } + + return (__bridge_transfer NSArray *)result; +} + + +- (BOOL)fetch:(NSError *__autoreleasing *)error { + OSStatus status = SAMKeychainErrorBadArguments; + if (!self.service || !self.account) { + if (error) { + *error = [[self class] errorWithCode:status]; + } + return NO; + } + + CFTypeRef result = NULL; + NSMutableDictionary *query = [self query]; + [query setObject:@YES forKey:(__bridge id)kSecReturnData]; + [query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; + status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); + + if (status != errSecSuccess) { + if (error) { + *error = [[self class] errorWithCode:status]; + } + return NO; + } + + self.passwordData = (__bridge_transfer NSData *)result; + return YES; +} + + +#pragma mark - Accessors + +- (void)setPasswordObject:(id)object { + self.passwordData = [NSKeyedArchiver archivedDataWithRootObject:object]; +} + + +- (id)passwordObject { + if ([self.passwordData length]) { + return [NSKeyedUnarchiver unarchiveObjectWithData:self.passwordData]; + } + return nil; +} + + +- (void)setPassword:(NSString *)password { + self.passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; +} + + +- (NSString *)password { + if ([self.passwordData length]) { + return [[NSString alloc] initWithData:self.passwordData encoding:NSUTF8StringEncoding]; + } + return nil; +} + + +#pragma mark - Synchronization Status + +#ifdef SAMKEYCHAIN_SYNCHRONIZATION_AVAILABLE ++ (BOOL)isSynchronizationAvailable { +#if TARGET_OS_IPHONE + // Apple suggested way to check for 7.0 at runtime + // https://developer.apple.com/library/ios/documentation/userexperience/conceptual/transitionguide/SupportingEarlieriOS.html + return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1; +#else + return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_8_4; +#endif +} +#endif + + +#pragma mark - Private + +- (NSMutableDictionary *)query { + NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:3]; + [dictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; + + if (self.service) { + [dictionary setObject:self.service forKey:(__bridge id)kSecAttrService]; + } + + if (self.account) { + [dictionary setObject:self.account forKey:(__bridge id)kSecAttrAccount]; + } + +#ifdef SAMKEYCHAIN_ACCESS_GROUP_AVAILABLE +#if !TARGET_IPHONE_SIMULATOR + if (self.accessGroup) { + [dictionary setObject:self.accessGroup forKey:(__bridge id)kSecAttrAccessGroup]; + } +#endif +#endif + +#ifdef SAMKEYCHAIN_SYNCHRONIZATION_AVAILABLE + if ([[self class] isSynchronizationAvailable]) { + id value; + + switch (self.synchronizationMode) { + case SAMKeychainQuerySynchronizationModeNo: { + value = @NO; + break; + } + case SAMKeychainQuerySynchronizationModeYes: { + value = @YES; + break; + } + case SAMKeychainQuerySynchronizationModeAny: { + value = (__bridge id)(kSecAttrSynchronizableAny); + break; + } + } + + [dictionary setObject:value forKey:(__bridge id)(kSecAttrSynchronizable)]; + } +#endif + + return dictionary; +} + + ++ (NSError *)errorWithCode:(OSStatus) code { + static dispatch_once_t onceToken; + static NSBundle *resourcesBundle = nil; + dispatch_once(&onceToken, ^{ + NSURL *url = [[NSBundle bundleForClass:[SAMKeychainQuery class]] URLForResource:@"SAMKeychain" withExtension:@"bundle"]; + resourcesBundle = [NSBundle bundleWithURL:url]; + }); + + NSString *message = nil; + switch (code) { + case errSecSuccess: return nil; + case SAMKeychainErrorBadArguments: message = NSLocalizedStringFromTableInBundle(@"SAMKeychainErrorBadArguments", @"SAMKeychain", resourcesBundle, nil); break; + +#if TARGET_OS_IPHONE + case errSecUnimplemented: { + message = NSLocalizedStringFromTableInBundle(@"errSecUnimplemented", @"SAMKeychain", resourcesBundle, nil); + break; + } + case errSecParam: { + message = NSLocalizedStringFromTableInBundle(@"errSecParam", @"SAMKeychain", resourcesBundle, nil); + break; + } + case errSecAllocate: { + message = NSLocalizedStringFromTableInBundle(@"errSecAllocate", @"SAMKeychain", resourcesBundle, nil); + break; + } + case errSecNotAvailable: { + message = NSLocalizedStringFromTableInBundle(@"errSecNotAvailable", @"SAMKeychain", resourcesBundle, nil); + break; + } + case errSecDuplicateItem: { + message = NSLocalizedStringFromTableInBundle(@"errSecDuplicateItem", @"SAMKeychain", resourcesBundle, nil); + break; + } + case errSecItemNotFound: { + message = NSLocalizedStringFromTableInBundle(@"errSecItemNotFound", @"SAMKeychain", resourcesBundle, nil); + break; + } + case errSecInteractionNotAllowed: { + message = NSLocalizedStringFromTableInBundle(@"errSecInteractionNotAllowed", @"SAMKeychain", resourcesBundle, nil); + break; + } + case errSecDecode: { + message = NSLocalizedStringFromTableInBundle(@"errSecDecode", @"SAMKeychain", resourcesBundle, nil); + break; + } + case errSecAuthFailed: { + message = NSLocalizedStringFromTableInBundle(@"errSecAuthFailed", @"SAMKeychain", resourcesBundle, nil); + break; + } + default: { + message = NSLocalizedStringFromTableInBundle(@"errSecDefault", @"SAMKeychain", resourcesBundle, nil); + } +#else + default: + message = (__bridge_transfer NSString *)SecCopyErrorMessageString(code, NULL); +#endif + } + + NSDictionary *userInfo = nil; + if (message) { + userInfo = @{ NSLocalizedDescriptionKey : message }; + } + return [NSError errorWithDomain:kSAMKeychainErrorDomain code:code userInfo:userInfo]; +} + +@end diff --git a/Pods/SAMKeychain/Support/SAMKeychain.bundle/en.lproj/SAMKeychain.strings b/Pods/SAMKeychain/Support/SAMKeychain.bundle/en.lproj/SAMKeychain.strings new file mode 100755 index 0000000..5c0f174 Binary files /dev/null and b/Pods/SAMKeychain/Support/SAMKeychain.bundle/en.lproj/SAMKeychain.strings differ diff --git a/Pods/Target Support Files/DVR/DVR-Info.plist b/Pods/Target Support Files/DVR/DVR-Info.plist new file mode 100755 index 0000000..0a12077 --- /dev/null +++ b/Pods/Target Support Files/DVR/DVR-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 2.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/DVR/DVR-dummy.m b/Pods/Target Support Files/DVR/DVR-dummy.m new file mode 100755 index 0000000..2793711 --- /dev/null +++ b/Pods/Target Support Files/DVR/DVR-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_DVR : NSObject +@end +@implementation PodsDummy_DVR +@end diff --git a/Pods/Target Support Files/DVR/DVR-prefix.pch b/Pods/Target Support Files/DVR/DVR-prefix.pch new file mode 100755 index 0000000..beb2a24 --- /dev/null +++ b/Pods/Target Support Files/DVR/DVR-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/Pods/Target Support Files/DVR/DVR-umbrella.h b/Pods/Target Support Files/DVR/DVR-umbrella.h new file mode 100755 index 0000000..6132b8e --- /dev/null +++ b/Pods/Target Support Files/DVR/DVR-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 DVRVersionNumber; +FOUNDATION_EXPORT const unsigned char DVRVersionString[]; + diff --git a/Pods/Target Support Files/DVR/DVR.modulemap b/Pods/Target Support Files/DVR/DVR.modulemap new file mode 100755 index 0000000..2f6c814 --- /dev/null +++ b/Pods/Target Support Files/DVR/DVR.modulemap @@ -0,0 +1,6 @@ +framework module DVR { + umbrella header "DVR-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/DVR/DVR.xcconfig b/Pods/Target Support Files/DVR/DVR.xcconfig new file mode 100755 index 0000000..6b2e24d --- /dev/null +++ b/Pods/Target Support Files/DVR/DVR.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/DVR +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}/DVR +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-Info.plist b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-Info.plist new file mode 100755 index 0000000..2243fe6 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-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/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-acknowledgements.markdown b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-acknowledgements.markdown new file mode 100755 index 0000000..11044cb --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-acknowledgements.markdown @@ -0,0 +1,27 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## SAMKeychain + +Copyright (c) 2010-2016 Sam Soffes, http://soff.es + +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/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-acknowledgements.plist b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-acknowledgements.plist new file mode 100755 index 0000000..3783cd2 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-acknowledgements.plist @@ -0,0 +1,59 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2010-2016 Sam Soffes, http://soff.es + +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 + SAMKeychain + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-dummy.m b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-dummy.m new file mode 100755 index 0000000..f266da4 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_fakestagram : NSObject +@end +@implementation PodsDummy_Pods_fakestagram +@end diff --git a/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-Debug-input-files.xcfilelist b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-Debug-input-files.xcfilelist new file mode 100755 index 0000000..8f68cb4 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-Debug-input-files.xcfilelist @@ -0,0 +1,2 @@ +${PODS_ROOT}/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks.sh +${BUILT_PRODUCTS_DIR}/SAMKeychain/SAMKeychain.framework \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-Debug-output-files.xcfilelist b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-Debug-output-files.xcfilelist new file mode 100755 index 0000000..2211fcb --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-Debug-output-files.xcfilelist @@ -0,0 +1 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SAMKeychain.framework \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-Release-input-files.xcfilelist b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-Release-input-files.xcfilelist new file mode 100755 index 0000000..8f68cb4 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-Release-input-files.xcfilelist @@ -0,0 +1,2 @@ +${PODS_ROOT}/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks.sh +${BUILT_PRODUCTS_DIR}/SAMKeychain/SAMKeychain.framework \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-Release-output-files.xcfilelist b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-Release-output-files.xcfilelist new file mode 100755 index 0000000..2211fcb --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-Release-output-files.xcfilelist @@ -0,0 +1 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SAMKeychain.framework \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks.sh b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks.sh new file mode 100755 index 0000000..ac7abfe --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks.sh @@ -0,0 +1,171 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + +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}" + elif [ -L "${binary}" ]; then + echo "Destination binary is symlinked..." + dirname="$(dirname "${binary}")" + binary="${dirname}/$(readlink "${binary}")" + 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) + 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 +} + +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + +# 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_identity + 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" + 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}/SAMKeychain/SAMKeychain.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/SAMKeychain/SAMKeychain.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-umbrella.h b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-umbrella.h new file mode 100755 index 0000000..b3b51df --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram-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_fakestagramVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_fakestagramVersionString[]; + diff --git a/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram.debug.xcconfig b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram.debug.xcconfig new file mode 100755 index 0000000..40bcc85 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram.debug.xcconfig @@ -0,0 +1,10 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SAMKeychain" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SAMKeychain/SAMKeychain.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "SAMKeychain" -framework "Security" +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 +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram.modulemap b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram.modulemap new file mode 100755 index 0000000..1c79b9b --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram.modulemap @@ -0,0 +1,6 @@ +framework module Pods_fakestagram { + umbrella header "Pods-fakestagram-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram.release.xcconfig b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram.release.xcconfig new file mode 100755 index 0000000..40bcc85 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagram/Pods-fakestagram.release.xcconfig @@ -0,0 +1,10 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SAMKeychain" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SAMKeychain/SAMKeychain.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "SAMKeychain" -framework "Security" +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 +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-Info.plist b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-Info.plist new file mode 100755 index 0000000..2243fe6 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-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/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-acknowledgements.markdown b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-acknowledgements.markdown new file mode 100755 index 0000000..bc283b5 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-acknowledgements.markdown @@ -0,0 +1,27 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## DVR + +Copyright (c) 2015 Venmo + +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/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-acknowledgements.plist b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-acknowledgements.plist new file mode 100755 index 0000000..69b32d2 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-acknowledgements.plist @@ -0,0 +1,59 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2015 Venmo + +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 + DVR + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-dummy.m b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-dummy.m new file mode 100755 index 0000000..3113f34 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_fakestagramTests : NSObject +@end +@implementation PodsDummy_Pods_fakestagramTests +@end diff --git a/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-Debug-input-files.xcfilelist b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-Debug-input-files.xcfilelist new file mode 100755 index 0000000..65ff78c --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-Debug-input-files.xcfilelist @@ -0,0 +1,2 @@ +${PODS_ROOT}/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks.sh +${BUILT_PRODUCTS_DIR}/DVR/DVR.framework \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-Debug-output-files.xcfilelist b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-Debug-output-files.xcfilelist new file mode 100755 index 0000000..31b1df9 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-Debug-output-files.xcfilelist @@ -0,0 +1 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DVR.framework \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-Release-input-files.xcfilelist b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-Release-input-files.xcfilelist new file mode 100755 index 0000000..65ff78c --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-Release-input-files.xcfilelist @@ -0,0 +1,2 @@ +${PODS_ROOT}/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks.sh +${BUILT_PRODUCTS_DIR}/DVR/DVR.framework \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-Release-output-files.xcfilelist b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-Release-output-files.xcfilelist new file mode 100755 index 0000000..31b1df9 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-Release-output-files.xcfilelist @@ -0,0 +1 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DVR.framework \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks.sh b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks.sh new file mode 100755 index 0000000..4c461ee --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks.sh @@ -0,0 +1,171 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + +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}" + elif [ -L "${binary}" ]; then + echo "Destination binary is symlinked..." + dirname="$(dirname "${binary}")" + binary="${dirname}/$(readlink "${binary}")" + 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) + 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 +} + +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + +# 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_identity + 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" + 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}/DVR/DVR.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/DVR/DVR.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-umbrella.h b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-umbrella.h new file mode 100755 index 0000000..8ae0937 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-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_fakestagramTestsVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_fakestagramTestsVersionString[]; + diff --git a/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.debug.xcconfig b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.debug.xcconfig new file mode 100755 index 0000000..fec5fc6 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.debug.xcconfig @@ -0,0 +1,12 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DVR" "${PODS_CONFIGURATION_BUILD_DIR}/SAMKeychain" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DVR/DVR.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SAMKeychain/SAMKeychain.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "DVR" -framework "Foundation" -framework "SAMKeychain" -framework "Security" +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 +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.modulemap b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.modulemap new file mode 100755 index 0000000..5c513c9 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.modulemap @@ -0,0 +1,6 @@ +framework module Pods_fakestagramTests { + umbrella header "Pods-fakestagramTests-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.release.xcconfig b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.release.xcconfig new file mode 100755 index 0000000..fec5fc6 --- /dev/null +++ b/Pods/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.release.xcconfig @@ -0,0 +1,12 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DVR" "${PODS_CONFIGURATION_BUILD_DIR}/SAMKeychain" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DVR/DVR.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SAMKeychain/SAMKeychain.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "DVR" -framework "Foundation" -framework "SAMKeychain" -framework "Security" +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 +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/SAMKeychain/SAMKeychain-Info.plist b/Pods/Target Support Files/SAMKeychain/SAMKeychain-Info.plist new file mode 100755 index 0000000..d24e508 --- /dev/null +++ b/Pods/Target Support Files/SAMKeychain/SAMKeychain-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.5.3 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/SAMKeychain/SAMKeychain-dummy.m b/Pods/Target Support Files/SAMKeychain/SAMKeychain-dummy.m new file mode 100755 index 0000000..7bb8fc3 --- /dev/null +++ b/Pods/Target Support Files/SAMKeychain/SAMKeychain-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_SAMKeychain : NSObject +@end +@implementation PodsDummy_SAMKeychain +@end diff --git a/Pods/Target Support Files/SAMKeychain/SAMKeychain-prefix.pch b/Pods/Target Support Files/SAMKeychain/SAMKeychain-prefix.pch new file mode 100755 index 0000000..beb2a24 --- /dev/null +++ b/Pods/Target Support Files/SAMKeychain/SAMKeychain-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/Pods/Target Support Files/SAMKeychain/SAMKeychain-umbrella.h b/Pods/Target Support Files/SAMKeychain/SAMKeychain-umbrella.h new file mode 100755 index 0000000..6577879 --- /dev/null +++ b/Pods/Target Support Files/SAMKeychain/SAMKeychain-umbrella.h @@ -0,0 +1,18 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "SAMKeychain.h" +#import "SAMKeychainQuery.h" + +FOUNDATION_EXPORT double SAMKeychainVersionNumber; +FOUNDATION_EXPORT const unsigned char SAMKeychainVersionString[]; + diff --git a/Pods/Target Support Files/SAMKeychain/SAMKeychain.modulemap b/Pods/Target Support Files/SAMKeychain/SAMKeychain.modulemap new file mode 100755 index 0000000..47b7948 --- /dev/null +++ b/Pods/Target Support Files/SAMKeychain/SAMKeychain.modulemap @@ -0,0 +1,6 @@ +framework module SAMKeychain { + umbrella header "SAMKeychain-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/SAMKeychain/SAMKeychain.xcconfig b/Pods/Target Support Files/SAMKeychain/SAMKeychain.xcconfig new file mode 100755 index 0000000..a72668c --- /dev/null +++ b/Pods/Target Support Files/SAMKeychain/SAMKeychain.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SAMKeychain +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "Security" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/SAMKeychain +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj old mode 100644 new mode 100755 index dc54317..e5791b4 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -3,17 +3,55 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 51; objects = { /* Begin PBXBuildFile section */ + 004CD0D423BED908003B6AF3 /* LikeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004CD0D323BED908003B6AF3 /* LikeService.swift */; }; + 05D8E963168944918FFCC7FF /* Pods_fakestagram.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FFAA8B9133CEE464C903FDF5 /* Pods_fakestagram.framework */; }; + 0CD5994F23C115A0009F35EB /* CommentService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD5994E23C115A0009F35EB /* CommentService.swift */; }; + D3D164DC7444072103DE027D /* Pods_fakestagramTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E669E31C92D68155914FC99D /* Pods_fakestagramTests.framework */; }; + E023A5542380859200B13B7D /* NotificationKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = E023A5532380859200B13B7D /* NotificationKeys.swift */; }; + E038FCED233FC78600E28571 /* PostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E038FCEC233FC78600E28571 /* PostViewController.swift */; }; + E045844923762E10006574FA /* CreatePostService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045844823762E10006574FA /* CreatePostService.swift */; }; + E045844B237652DD006574FA /* StorageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045844A237652DD006574FA /* StorageType.swift */; }; + E045844D23765677006574FA /* DataContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045844C23765677006574FA /* DataContainer.swift */; }; + E045844F23765B0F006574FA /* ImageStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045844E23765B0F006574FA /* ImageStore.swift */; }; + E045845123766203006574FA /* CacheImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045845023766203006574FA /* CacheImage.swift */; }; + E0458454237721F5006574FA /* CheckSum.m in Sources */ = {isa = PBXBuildFile; fileRef = E0458453237721F5006574FA /* CheckSum.m */; }; + E0458457237725B9006574FA /* IndexService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0458456237725B9006574FA /* IndexService.swift */; }; + E0458459237727D8006574FA /* CheckSumTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0458458237727D8006574FA /* CheckSumTest.swift */; }; E084FADA233A8734009AC50D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAD9233A8734009AC50D /* AppDelegate.swift */; }; E084FADC233A8734009AC50D /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FADB233A8734009AC50D /* SceneDelegate.swift */; }; E084FAE1233A8734009AC50D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E084FADF233A8734009AC50D /* Main.storyboard */; }; E084FAE3233A8735009AC50D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E084FAE2233A8735009AC50D /* Assets.xcassets */; }; E084FAE6233A8735009AC50D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E084FAE4233A8735009AC50D /* LaunchScreen.storyboard */; }; - E084FAF1233A8735009AC50D /* fakestagramTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAF0233A8735009AC50D /* fakestagramTests.swift */; }; - E084FAFC233A8888009AC50D /* PostsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAFB233A8888009AC50D /* PostsTableViewController.swift */; }; + E084FAF1233A8735009AC50D /* RequestBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAF0233A8735009AC50D /* RequestBuilderTests.swift */; }; + E0A9ED51235A782F00A0527E /* PostsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0A9ED50235A782F00A0527E /* PostsViewController.swift */; }; + E0A9ED54235A7FF300A0527E /* PostCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0A9ED52235A7FF300A0527E /* PostCollectionViewCell.swift */; }; + E0A9ED55235A7FF300A0527E /* PostCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E0A9ED53235A7FF300A0527E /* PostCollectionViewCell.xib */; }; + E0C185F0237F92C700AD9983 /* PreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C185EF237F92C700AD9983 /* PreviewView.swift */; }; + E0C93E942351435100FD330C /* RestClientTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93E932351435100FD330C /* RestClientTest.swift */; }; + E0C93E9923514D8800FD330C /* posts.successful.json in Resources */ = {isa = PBXBuildFile; fileRef = E0C93E9823514D8800FD330C /* posts.successful.json */; }; + E0C93E9B23515A0400FD330C /* show_post.successful.json in Resources */ = {isa = PBXBuildFile; fileRef = E0C93E9A23515A0400FD330C /* show_post.successful.json */; }; + E0C93E9D23515CEE00FD330C /* CodableSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93E9C23515CEE00FD330C /* CodableSerializer.swift */; }; + E0C93EA123523B7C00FD330C /* ShowPostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93E9F23523B7C00FD330C /* ShowPostViewController.swift */; }; + E0C93EA223523B7C00FD330C /* ShowPostViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E0C93EA023523B7C00FD330C /* ShowPostViewController.xib */; }; + E0C93EA42352452900FD330C /* AuthorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93EA32352452900FD330C /* AuthorView.swift */; }; + E0C93EA62352454E00FD330C /* Author.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93EA52352454E00FD330C /* Author.swift */; }; + E0C93EA82352455C00FD330C /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93EA72352455C00FD330C /* Comment.swift */; }; + E0C93EAA2352457200FD330C /* Like.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93EA92352457200FD330C /* Like.swift */; }; + E0E2545F235A9F3A00C55767 /* UIDevice+models.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E2545E235A9F3A00C55767 /* UIDevice+models.swift */; }; + E0E25463235B675100C55767 /* CameraViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E25462235B675100C55767 /* CameraViewController.swift */; }; + E0E25465235B6C0500C55767 /* UIImage+Base64.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E25464235B6C0500C55767 /* UIImage+Base64.swift */; }; + E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9642348018200DA9D1A /* Credentials.swift */; }; + E0E8B9682348036D00DA9D1A /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9672348036D00DA9D1A /* Client.swift */; }; + E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96923481D5A00DA9D1A /* StatusCode.swift */; }; + E0E8B96C23481E1700DA9D1A /* HttpResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96B23481E1700DA9D1A /* HttpResponse.swift */; }; + E0E8B96E2348203B00DA9D1A /* RequestBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96D2348203B00DA9D1A /* RequestBuilder.swift */; }; + E0E8B971234916D100DA9D1A /* RestClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B970234916D100DA9D1A /* RestClient.swift */; }; + E0E8B974234918FF00DA9D1A /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B973234918FF00DA9D1A /* Account.swift */; }; + E0E8B9762349197100DA9D1A /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9752349197100DA9D1A /* Post.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -27,6 +65,24 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 004CD0D323BED908003B6AF3 /* LikeService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LikeService.swift; sourceTree = ""; }; + 0CD5994E23C115A0009F35EB /* CommentService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentService.swift; sourceTree = ""; }; + 5E0AE2BFBF9C8D81E583E1BE /* Pods-fakestagramTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagramTests.release.xcconfig"; path = "Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.release.xcconfig"; sourceTree = ""; }; + 66342726A6BCEEEF6289B1AA /* Pods-fakestagramTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagramTests.debug.xcconfig"; path = "Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.debug.xcconfig"; sourceTree = ""; }; + CCC6C6EA9D17CA169951A745 /* Pods-fakestagram.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagram.release.xcconfig"; path = "Target Support Files/Pods-fakestagram/Pods-fakestagram.release.xcconfig"; sourceTree = ""; }; + DB68F7FEC717545506064663 /* Pods-fakestagram.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagram.debug.xcconfig"; path = "Target Support Files/Pods-fakestagram/Pods-fakestagram.debug.xcconfig"; sourceTree = ""; }; + E023A5532380859200B13B7D /* NotificationKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationKeys.swift; sourceTree = ""; }; + E038FCEC233FC78600E28571 /* PostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostViewController.swift; sourceTree = ""; }; + E045844823762E10006574FA /* CreatePostService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreatePostService.swift; sourceTree = ""; }; + E045844A237652DD006574FA /* StorageType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageType.swift; sourceTree = ""; }; + E045844C23765677006574FA /* DataContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataContainer.swift; sourceTree = ""; }; + E045844E23765B0F006574FA /* ImageStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageStore.swift; sourceTree = ""; }; + E045845023766203006574FA /* CacheImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheImage.swift; sourceTree = ""; }; + E0458452237721F5006574FA /* fakestagram-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "fakestagram-Bridging-Header.h"; sourceTree = ""; }; + E0458453237721F5006574FA /* CheckSum.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CheckSum.m; sourceTree = ""; }; + E045845523772360006574FA /* CheckSum.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CheckSum.h; sourceTree = ""; }; + E0458456237725B9006574FA /* IndexService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndexService.swift; sourceTree = ""; }; + E0458458237727D8006574FA /* CheckSumTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckSumTest.swift; sourceTree = ""; }; E084FAD6233A8734009AC50D /* fakestagram.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = fakestagram.app; sourceTree = BUILT_PRODUCTS_DIR; }; E084FAD9233A8734009AC50D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; E084FADB233A8734009AC50D /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -35,9 +91,35 @@ E084FAE5233A8735009AC50D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; E084FAE7233A8735009AC50D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E084FAEC233A8735009AC50D /* fakestagramTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = fakestagramTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - E084FAF0233A8735009AC50D /* fakestagramTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = fakestagramTests.swift; sourceTree = ""; }; + E084FAF0233A8735009AC50D /* RequestBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestBuilderTests.swift; sourceTree = ""; }; E084FAF2233A8735009AC50D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - E084FAFB233A8888009AC50D /* PostsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostsTableViewController.swift; sourceTree = ""; }; + E0A9ED50235A782F00A0527E /* PostsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostsViewController.swift; sourceTree = ""; }; + E0A9ED52235A7FF300A0527E /* PostCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostCollectionViewCell.swift; sourceTree = ""; }; + E0A9ED53235A7FF300A0527E /* PostCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PostCollectionViewCell.xib; sourceTree = ""; }; + E0C185EF237F92C700AD9983 /* PreviewView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreviewView.swift; sourceTree = ""; }; + E0C93E932351435100FD330C /* RestClientTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestClientTest.swift; sourceTree = ""; }; + E0C93E9823514D8800FD330C /* posts.successful.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = posts.successful.json; sourceTree = ""; }; + E0C93E9A23515A0400FD330C /* show_post.successful.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = show_post.successful.json; sourceTree = ""; }; + E0C93E9C23515CEE00FD330C /* CodableSerializer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableSerializer.swift; sourceTree = ""; }; + E0C93E9F23523B7C00FD330C /* ShowPostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShowPostViewController.swift; sourceTree = ""; }; + E0C93EA023523B7C00FD330C /* ShowPostViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ShowPostViewController.xib; sourceTree = ""; }; + E0C93EA32352452900FD330C /* AuthorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorView.swift; sourceTree = ""; }; + E0C93EA52352454E00FD330C /* Author.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Author.swift; sourceTree = ""; }; + E0C93EA72352455C00FD330C /* Comment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comment.swift; sourceTree = ""; }; + E0C93EA92352457200FD330C /* Like.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Like.swift; sourceTree = ""; }; + E0E2545E235A9F3A00C55767 /* UIDevice+models.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIDevice+models.swift"; sourceTree = ""; }; + E0E25462235B675100C55767 /* CameraViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraViewController.swift; sourceTree = ""; }; + E0E25464235B6C0500C55767 /* UIImage+Base64.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Base64.swift"; sourceTree = ""; }; + E0E8B9642348018200DA9D1A /* Credentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Credentials.swift; sourceTree = ""; }; + E0E8B9672348036D00DA9D1A /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; }; + E0E8B96923481D5A00DA9D1A /* StatusCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusCode.swift; sourceTree = ""; }; + E0E8B96B23481E1700DA9D1A /* HttpResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HttpResponse.swift; sourceTree = ""; }; + E0E8B96D2348203B00DA9D1A /* RequestBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestBuilder.swift; sourceTree = ""; }; + E0E8B970234916D100DA9D1A /* RestClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestClient.swift; sourceTree = ""; }; + E0E8B973234918FF00DA9D1A /* Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = ""; }; + E0E8B9752349197100DA9D1A /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = ""; }; + E669E31C92D68155914FC99D /* Pods_fakestagramTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_fakestagramTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FFAA8B9133CEE464C903FDF5 /* Pods_fakestagram.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_fakestagram.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -45,6 +127,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 05D8E963168944918FFCC7FF /* Pods_fakestagram.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -52,18 +135,43 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D3D164DC7444072103DE027D /* Pods_fakestagramTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 01A08896D7765C060714CF7E /* Pods */ = { + isa = PBXGroup; + children = ( + DB68F7FEC717545506064663 /* Pods-fakestagram.debug.xcconfig */, + CCC6C6EA9D17CA169951A745 /* Pods-fakestagram.release.xcconfig */, + 66342726A6BCEEEF6289B1AA /* Pods-fakestagramTests.debug.xcconfig */, + 5E0AE2BFBF9C8D81E583E1BE /* Pods-fakestagramTests.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + E045844723762DF8006574FA /* Services */ = { + isa = PBXGroup; + children = ( + E045844823762E10006574FA /* CreatePostService.swift */, + E0458456237725B9006574FA /* IndexService.swift */, + 004CD0D323BED908003B6AF3 /* LikeService.swift */, + 0CD5994E23C115A0009F35EB /* CommentService.swift */, + ); + path = Services; + sourceTree = ""; + }; E084FACD233A8734009AC50D = { isa = PBXGroup; children = ( E084FAD8233A8734009AC50D /* fakestagram */, E084FAEF233A8735009AC50D /* fakestagramTests */, E084FAD7233A8734009AC50D /* Products */, + 01A08896D7765C060714CF7E /* Pods */, + E59E91806B162F48B9F21B96 /* Frameworks */, ); sourceTree = ""; }; @@ -79,13 +187,22 @@ E084FAD8233A8734009AC50D /* fakestagram */ = { isa = PBXGroup; children = ( + E045844723762DF8006574FA /* Services */, + E0E25466235B7BCE00C55767 /* ViewControllers */, + E0C93E9E23523B4700FD330C /* Views */, + E0E8B972234918ED00DA9D1A /* Models */, + E0E8B96F234916AA00DA9D1A /* Network */, + E0E8B9662348035800DA9D1A /* DataSource */, + E0E25467235B7BE500C55767 /* Utils */, E084FAD9233A8734009AC50D /* AppDelegate.swift */, E084FADB233A8734009AC50D /* SceneDelegate.swift */, - E084FAFB233A8888009AC50D /* PostsTableViewController.swift */, E084FADF233A8734009AC50D /* Main.storyboard */, E084FAE2233A8735009AC50D /* Assets.xcassets */, E084FAE4233A8735009AC50D /* LaunchScreen.storyboard */, E084FAE7233A8735009AC50D /* Info.plist */, + E0458453237721F5006574FA /* CheckSum.m */, + E045845523772360006574FA /* CheckSum.h */, + E0458452237721F5006574FA /* fakestagram-Bridging-Header.h */, ); path = fakestagram; sourceTree = ""; @@ -93,12 +210,103 @@ E084FAEF233A8735009AC50D /* fakestagramTests */ = { isa = PBXGroup; children = ( - E084FAF0233A8735009AC50D /* fakestagramTests.swift */, + E0C93E952351472A00FD330C /* casettes */, + E084FAF0233A8735009AC50D /* RequestBuilderTests.swift */, + E0C93E932351435100FD330C /* RestClientTest.swift */, + E0458458237727D8006574FA /* CheckSumTest.swift */, E084FAF2233A8735009AC50D /* Info.plist */, ); path = fakestagramTests; sourceTree = ""; }; + E0C93E952351472A00FD330C /* casettes */ = { + isa = PBXGroup; + children = ( + E0C93E9A23515A0400FD330C /* show_post.successful.json */, + E0C93E9823514D8800FD330C /* posts.successful.json */, + ); + path = casettes; + sourceTree = ""; + }; + E0C93E9E23523B4700FD330C /* Views */ = { + isa = PBXGroup; + children = ( + E0C185EF237F92C700AD9983 /* PreviewView.swift */, + E0A9ED52235A7FF300A0527E /* PostCollectionViewCell.swift */, + E0A9ED53235A7FF300A0527E /* PostCollectionViewCell.xib */, + E0C93E9F23523B7C00FD330C /* ShowPostViewController.swift */, + E0C93EA023523B7C00FD330C /* ShowPostViewController.xib */, + E0C93EA32352452900FD330C /* AuthorView.swift */, + ); + path = Views; + sourceTree = ""; + }; + E0E25466235B7BCE00C55767 /* ViewControllers */ = { + isa = PBXGroup; + children = ( + E0A9ED50235A782F00A0527E /* PostsViewController.swift */, + E038FCEC233FC78600E28571 /* PostViewController.swift */, + E0E25462235B675100C55767 /* CameraViewController.swift */, + ); + path = ViewControllers; + sourceTree = ""; + }; + E0E25467235B7BE500C55767 /* Utils */ = { + isa = PBXGroup; + children = ( + E0E8B9642348018200DA9D1A /* Credentials.swift */, + E0E2545E235A9F3A00C55767 /* UIDevice+models.swift */, + E0E25464235B6C0500C55767 /* UIImage+Base64.swift */, + E023A5532380859200B13B7D /* NotificationKeys.swift */, + ); + path = Utils; + sourceTree = ""; + }; + E0E8B9662348035800DA9D1A /* DataSource */ = { + isa = PBXGroup; + children = ( + E0E8B970234916D100DA9D1A /* RestClient.swift */, + E0C93E9C23515CEE00FD330C /* CodableSerializer.swift */, + E045845023766203006574FA /* CacheImage.swift */, + E045844E23765B0F006574FA /* ImageStore.swift */, + E045844C23765677006574FA /* DataContainer.swift */, + E045844A237652DD006574FA /* StorageType.swift */, + ); + path = DataSource; + sourceTree = ""; + }; + E0E8B96F234916AA00DA9D1A /* Network */ = { + isa = PBXGroup; + children = ( + E0E8B9672348036D00DA9D1A /* Client.swift */, + E0E8B96923481D5A00DA9D1A /* StatusCode.swift */, + E0E8B96B23481E1700DA9D1A /* HttpResponse.swift */, + E0E8B96D2348203B00DA9D1A /* RequestBuilder.swift */, + ); + path = Network; + sourceTree = ""; + }; + E0E8B972234918ED00DA9D1A /* Models */ = { + isa = PBXGroup; + children = ( + E0E8B973234918FF00DA9D1A /* Account.swift */, + E0E8B9752349197100DA9D1A /* Post.swift */, + E0C93EA52352454E00FD330C /* Author.swift */, + E0C93EA72352455C00FD330C /* Comment.swift */, + E0C93EA92352457200FD330C /* Like.swift */, + ); + path = Models; + sourceTree = ""; + }; + E59E91806B162F48B9F21B96 /* Frameworks */ = { + isa = PBXGroup; + children = ( + FFAA8B9133CEE464C903FDF5 /* Pods_fakestagram.framework */, + E669E31C92D68155914FC99D /* Pods_fakestagramTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -106,9 +314,11 @@ isa = PBXNativeTarget; buildConfigurationList = E084FAF5233A8735009AC50D /* Build configuration list for PBXNativeTarget "fakestagram" */; buildPhases = ( + 4AE804DBB1C330BBDB1A4587 /* [CP] Check Pods Manifest.lock */, E084FAD2233A8734009AC50D /* Sources */, E084FAD3233A8734009AC50D /* Frameworks */, E084FAD4233A8734009AC50D /* Resources */, + BA44E9C49B033049A720850E /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -123,9 +333,11 @@ isa = PBXNativeTarget; buildConfigurationList = E084FAF8233A8735009AC50D /* Build configuration list for PBXNativeTarget "fakestagramTests" */; buildPhases = ( + 9C7D5FC48E01207A73A3C357 /* [CP] Check Pods Manifest.lock */, E084FAE8233A8735009AC50D /* Sources */, E084FAE9233A8735009AC50D /* Frameworks */, E084FAEA233A8735009AC50D /* Resources */, + 7AA77609E4963F9B91BB29FB /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -149,6 +361,7 @@ TargetAttributes = { E084FAD5233A8734009AC50D = { CreatedOnToolsVersion = 11.0; + LastSwiftMigration = 1120; }; E084FAEB233A8735009AC50D = { CreatedOnToolsVersion = 11.0; @@ -180,9 +393,11 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + E0C93EA223523B7C00FD330C /* ShowPostViewController.xib in Resources */, E084FAE6233A8735009AC50D /* LaunchScreen.storyboard in Resources */, E084FAE3233A8735009AC50D /* Assets.xcassets in Resources */, E084FAE1233A8734009AC50D /* Main.storyboard in Resources */, + E0A9ED55235A7FF300A0527E /* PostCollectionViewCell.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -190,18 +405,131 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + E0C93E9923514D8800FD330C /* posts.successful.json in Resources */, + E0C93E9B23515A0400FD330C /* show_post.successful.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 4AE804DBB1C330BBDB1A4587 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-fakestagram-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + 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; + }; + 7AA77609E4963F9B91BB29FB /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 9C7D5FC48E01207A73A3C357 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-fakestagramTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + 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; + }; + BA44E9C49B033049A720850E /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ E084FAD2233A8734009AC50D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E0C93EA42352452900FD330C /* AuthorView.swift in Sources */, + E0E2545F235A9F3A00C55767 /* UIDevice+models.swift in Sources */, + 004CD0D423BED908003B6AF3 /* LikeService.swift in Sources */, + E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */, + E045845123766203006574FA /* CacheImage.swift in Sources */, + E045844B237652DD006574FA /* StorageType.swift in Sources */, + E023A5542380859200B13B7D /* NotificationKeys.swift in Sources */, + E0C185F0237F92C700AD9983 /* PreviewView.swift in Sources */, + E0E8B974234918FF00DA9D1A /* Account.swift in Sources */, + E0C93EA123523B7C00FD330C /* ShowPostViewController.swift in Sources */, + E0E25463235B675100C55767 /* CameraViewController.swift in Sources */, + E0458457237725B9006574FA /* IndexService.swift in Sources */, + E038FCED233FC78600E28571 /* PostViewController.swift in Sources */, + E0C93EA82352455C00FD330C /* Comment.swift in Sources */, + E0C93EAA2352457200FD330C /* Like.swift in Sources */, + E0C93E9D23515CEE00FD330C /* CodableSerializer.swift in Sources */, + E0458454237721F5006574FA /* CheckSum.m in Sources */, + E0E25465235B6C0500C55767 /* UIImage+Base64.swift in Sources */, + E0E8B9762349197100DA9D1A /* Post.swift in Sources */, + 0CD5994F23C115A0009F35EB /* CommentService.swift in Sources */, E084FADA233A8734009AC50D /* AppDelegate.swift in Sources */, - E084FAFC233A8888009AC50D /* PostsTableViewController.swift in Sources */, + E0E8B96E2348203B00DA9D1A /* RequestBuilder.swift in Sources */, + E0E8B9682348036D00DA9D1A /* Client.swift in Sources */, + E0A9ED51235A782F00A0527E /* PostsViewController.swift in Sources */, + E045844923762E10006574FA /* CreatePostService.swift in Sources */, + E0C93EA62352454E00FD330C /* Author.swift in Sources */, + E0A9ED54235A7FF300A0527E /* PostCollectionViewCell.swift in Sources */, + E0E8B96C23481E1700DA9D1A /* HttpResponse.swift in Sources */, + E045844F23765B0F006574FA /* ImageStore.swift in Sources */, + E045844D23765677006574FA /* DataContainer.swift in Sources */, + E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */, + E0E8B971234916D100DA9D1A /* RestClient.swift in Sources */, E084FADC233A8734009AC50D /* SceneDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -210,7 +538,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - E084FAF1233A8735009AC50D /* fakestagramTests.swift in Sources */, + E0C93E942351435100FD330C /* RestClientTest.swift in Sources */, + E084FAF1233A8735009AC50D /* RequestBuilderTests.swift in Sources */, + E0458459237727D8006574FA /* CheckSumTest.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -300,6 +630,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; @@ -353,6 +684,7 @@ MTL_FAST_MATH = YES; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-O"; VALIDATE_PRODUCT = YES; }; @@ -360,8 +692,10 @@ }; E084FAF6233A8735009AC50D /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DB68F7FEC717545506064663 /* Pods-fakestagram.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = D3XL2U7DQC; INFOPLIST_FILE = fakestagram/Info.plist; @@ -371,6 +705,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.3zcurdia.fakestagram; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "fakestagram/fakestagram-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -378,8 +714,10 @@ }; E084FAF7233A8735009AC50D /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = CCC6C6EA9D17CA169951A745 /* Pods-fakestagram.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = D3XL2U7DQC; INFOPLIST_FILE = fakestagram/Info.plist; @@ -389,6 +727,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.3zcurdia.fakestagram; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "fakestagram/fakestagram-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -396,6 +735,7 @@ }; E084FAF9233A8735009AC50D /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 66342726A6BCEEEF6289B1AA /* Pods-fakestagramTests.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; @@ -418,6 +758,7 @@ }; E084FAFA233A8735009AC50D /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 5E0AE2BFBF9C8D81E583E1BE /* Pods-fakestagramTests.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; diff --git a/fakestagram.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/fakestagram.xcodeproj/project.xcworkspace/contents.xcworkspacedata old mode 100644 new mode 100755 diff --git a/fakestagram.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/fakestagram.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist old mode 100644 new mode 100755 diff --git a/fakestagram.xcodeproj/project.xcworkspace/xcuserdata/richard_ohg.xcuserdatad/UserInterfaceState.xcuserstate b/fakestagram.xcodeproj/project.xcworkspace/xcuserdata/richard_ohg.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100755 index 0000000..a5f1d19 Binary files /dev/null and b/fakestagram.xcodeproj/project.xcworkspace/xcuserdata/richard_ohg.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/fakestagram.xcodeproj/xcshareddata/xcbaselines/E084FAEB233A8735009AC50D.xcbaseline/4B2163FF-53B3-4A2D-B0E0-0AF6257FC48D.plist b/fakestagram.xcodeproj/xcshareddata/xcbaselines/E084FAEB233A8735009AC50D.xcbaseline/4B2163FF-53B3-4A2D-B0E0-0AF6257FC48D.plist new file mode 100755 index 0000000..0648835 --- /dev/null +++ b/fakestagram.xcodeproj/xcshareddata/xcbaselines/E084FAEB233A8735009AC50D.xcbaseline/4B2163FF-53B3-4A2D-B0E0-0AF6257FC48D.plist @@ -0,0 +1,22 @@ + + + + + classNames + + CheckSumTest + + testPerformanceExample() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 6.55e-05 + baselineIntegrationDisplayName + Local Baseline + + + + + + diff --git a/fakestagram.xcodeproj/xcshareddata/xcbaselines/E084FAEB233A8735009AC50D.xcbaseline/Info.plist b/fakestagram.xcodeproj/xcshareddata/xcbaselines/E084FAEB233A8735009AC50D.xcbaseline/Info.plist new file mode 100755 index 0000000..fc16441 --- /dev/null +++ b/fakestagram.xcodeproj/xcshareddata/xcbaselines/E084FAEB233A8735009AC50D.xcbaseline/Info.plist @@ -0,0 +1,40 @@ + + + + + runDestinationsByUUID + + 4B2163FF-53B3-4A2D-B0E0-0AF6257FC48D + + localComputer + + busSpeedInMHz + 100 + cpuCount + 1 + cpuKind + Intel Core i7 + cpuSpeedInMHz + 2900 + logicalCPUCoresPerPackage + 8 + modelCode + MacBookPro14,3 + physicalCPUCoresPerPackage + 4 + platformIdentifier + com.apple.platform.macosx + + targetArchitecture + x86_64 + targetDevice + + modelCode + iPhone12,1 + platformIdentifier + com.apple.platform.iphonesimulator + + + + + diff --git a/fakestagram.xcodeproj/xcuserdata/jolvera.xcuserdatad/xcschemes/xcschememanagement.plist b/fakestagram.xcodeproj/xcuserdata/jolvera.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..53f76f5 --- /dev/null +++ b/fakestagram.xcodeproj/xcuserdata/jolvera.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + fakestagram.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/fakestagram.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/xcschememanagement.plist b/fakestagram.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100755 index 0000000..5378346 --- /dev/null +++ b/fakestagram.xcodeproj/xcuserdata/joseolvera.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + fakestagram.xcscheme_^#shared#^_ + + orderHint + 4 + + + + diff --git a/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100755 index 0000000..d88cf55 --- /dev/null +++ b/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,6 @@ + + + diff --git a/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcschemes/xcschememanagement.plist b/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcschemes/xcschememanagement.plist old mode 100644 new mode 100755 index 53f76f5..5378346 --- a/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,7 +7,7 @@ fakestagram.xcscheme_^#shared#^_ orderHint - 0 + 4 diff --git a/fakestagram.xcodeproj/xcuserdata/richard_ohg.xcuserdatad/xcschemes/xcschememanagement.plist b/fakestagram.xcodeproj/xcuserdata/richard_ohg.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100755 index 0000000..53f76f5 --- /dev/null +++ b/fakestagram.xcodeproj/xcuserdata/richard_ohg.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + fakestagram.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/fakestagram.xcworkspace/contents.xcworkspacedata b/fakestagram.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..666ee12 --- /dev/null +++ b/fakestagram.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/fakestagram.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/fakestagram.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 0000000..18d9810 --- /dev/null +++ b/fakestagram.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/fakestagram.xcworkspace/xcuserdata/jolvera.xcuserdatad/UserInterfaceState.xcuserstate b/fakestagram.xcworkspace/xcuserdata/jolvera.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..9578e33 Binary files /dev/null and b/fakestagram.xcworkspace/xcuserdata/jolvera.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/fakestagram.xcworkspace/xcuserdata/joseolvera.xcuserdatad/UserInterfaceState.xcuserstate b/fakestagram.xcworkspace/xcuserdata/joseolvera.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100755 index 0000000..60e39eb Binary files /dev/null and b/fakestagram.xcworkspace/xcuserdata/joseolvera.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/fakestagram/AppDelegate.swift b/fakestagram/AppDelegate.swift old mode 100644 new mode 100755 index 9ef21c3..8408510 --- a/fakestagram/AppDelegate.swift +++ b/fakestagram/AppDelegate.swift @@ -13,6 +13,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. + StorageType.permanent.ensureExists() + StorageType.cache.ensureExists() + loadOrCreateAccount() return true } @@ -30,6 +33,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - + func loadOrCreateAccount() { + if Credentials.apiToken.get() != nil { return } + let account = Account(id: nil, name: "Jose Olvera", deviceNumber: UIDevice.identifier, deviceModel: UIDevice.modelName) + let client = RestClient(client: Client.fakestagram, basePath: "/api/v1/accounts") + client.create(account) { account in + guard let account = account, let idx = account.id else { return } + _ = Credentials.apiToken.set(value: idx) + } + } } - diff --git a/fakestagram/Assets.xcassets/AppIcon.appiconset/Contents.json b/fakestagram/Assets.xcassets/AppIcon.appiconset/Contents.json old mode 100644 new mode 100755 diff --git a/fakestagram/Assets.xcassets/Contents.json b/fakestagram/Assets.xcassets/Contents.json old mode 100644 new mode 100755 diff --git a/fakestagram/Assets.xcassets/approval.imageset/Contents.json b/fakestagram/Assets.xcassets/approval.imageset/Contents.json new file mode 100755 index 0000000..869caf9 --- /dev/null +++ b/fakestagram/Assets.xcassets/approval.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "approval.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "approval@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "approval@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/fakestagram/Assets.xcassets/approval.imageset/approval.png b/fakestagram/Assets.xcassets/approval.imageset/approval.png new file mode 100755 index 0000000..a4c0624 Binary files /dev/null and b/fakestagram/Assets.xcassets/approval.imageset/approval.png differ diff --git a/fakestagram/Assets.xcassets/approval.imageset/approval@2x.png b/fakestagram/Assets.xcassets/approval.imageset/approval@2x.png new file mode 100755 index 0000000..333dc4d Binary files /dev/null and b/fakestagram/Assets.xcassets/approval.imageset/approval@2x.png differ diff --git a/fakestagram/Assets.xcassets/approval.imageset/approval@3x.png b/fakestagram/Assets.xcassets/approval.imageset/approval@3x.png new file mode 100755 index 0000000..c0cc5e2 Binary files /dev/null and b/fakestagram/Assets.xcassets/approval.imageset/approval@3x.png differ diff --git a/fakestagram/Assets.xcassets/cam.imageset/Contents.json b/fakestagram/Assets.xcassets/cam.imageset/Contents.json new file mode 100755 index 0000000..cc6689d --- /dev/null +++ b/fakestagram/Assets.xcassets/cam.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "icons8-camera-32.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/fakestagram/Assets.xcassets/cam.imageset/icons8-camera-32.png b/fakestagram/Assets.xcassets/cam.imageset/icons8-camera-32.png new file mode 100755 index 0000000..536dfd1 Binary files /dev/null and b/fakestagram/Assets.xcassets/cam.imageset/icons8-camera-32.png differ diff --git a/fakestagram/Assets.xcassets/photo.imageset/Contents.json b/fakestagram/Assets.xcassets/photo.imageset/Contents.json new file mode 100755 index 0000000..ed7c26f --- /dev/null +++ b/fakestagram/Assets.xcassets/photo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "icons8-photo-gallery-32.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/fakestagram/Assets.xcassets/photo.imageset/icons8-photo-gallery-32.png b/fakestagram/Assets.xcassets/photo.imageset/icons8-photo-gallery-32.png new file mode 100755 index 0000000..c585abd Binary files /dev/null and b/fakestagram/Assets.xcassets/photo.imageset/icons8-photo-gallery-32.png differ diff --git a/fakestagram/Assets.xcassets/shot.imageset/Contents.json b/fakestagram/Assets.xcassets/shot.imageset/Contents.json new file mode 100755 index 0000000..ed34135 --- /dev/null +++ b/fakestagram/Assets.xcassets/shot.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "icons8-círculo-delgado-60.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git "a/fakestagram/Assets.xcassets/shot.imageset/icons8-c\303\255rculo-delgado-60.png" "b/fakestagram/Assets.xcassets/shot.imageset/icons8-c\303\255rculo-delgado-60.png" new file mode 100755 index 0000000..2baa6ea Binary files /dev/null and "b/fakestagram/Assets.xcassets/shot.imageset/icons8-c\303\255rculo-delgado-60.png" differ diff --git a/fakestagram/Assets.xcassets/spacecat.imageset/Contents.json b/fakestagram/Assets.xcassets/spacecat.imageset/Contents.json new file mode 100755 index 0000000..d1bb6ed --- /dev/null +++ b/fakestagram/Assets.xcassets/spacecat.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "spacecat.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/fakestagram/Assets.xcassets/spacecat.imageset/spacecat.jpg b/fakestagram/Assets.xcassets/spacecat.imageset/spacecat.jpg new file mode 100755 index 0000000..32ea7fd Binary files /dev/null and b/fakestagram/Assets.xcassets/spacecat.imageset/spacecat.jpg differ diff --git a/fakestagram/Assets.xcassets/user.imageset/Contents.json b/fakestagram/Assets.xcassets/user.imageset/Contents.json new file mode 100755 index 0000000..51c1b53 --- /dev/null +++ b/fakestagram/Assets.xcassets/user.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "icons8-user-32.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/fakestagram/Assets.xcassets/user.imageset/icons8-user-32.png b/fakestagram/Assets.xcassets/user.imageset/icons8-user-32.png new file mode 100755 index 0000000..8923fef Binary files /dev/null and b/fakestagram/Assets.xcassets/user.imageset/icons8-user-32.png differ diff --git a/fakestagram/Base.lproj/LaunchScreen.storyboard b/fakestagram/Base.lproj/LaunchScreen.storyboard old mode 100644 new mode 100755 diff --git a/fakestagram/Base.lproj/Main.storyboard b/fakestagram/Base.lproj/Main.storyboard old mode 100644 new mode 100755 index 9e4590a..8ac52be --- a/fakestagram/Base.lproj/Main.storyboard +++ b/fakestagram/Base.lproj/Main.storyboard @@ -1,54 +1,146 @@ - + - + + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + diff --git a/fakestagram/CheckSum.h b/fakestagram/CheckSum.h new file mode 100755 index 0000000..168df88 --- /dev/null +++ b/fakestagram/CheckSum.h @@ -0,0 +1,18 @@ +// +// CheckSum.h +// fakestagram +// +// Created by LuisE on 11/9/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +#ifndef CheckSum_h +#define CheckSum_h +#import +#import + +@interface CheckSum : NSObject ++(NSString *) sha256String: (NSString *)input; +@end + +#endif /* Checksum_h */ diff --git a/fakestagram/CheckSum.m b/fakestagram/CheckSum.m new file mode 100755 index 0000000..181a11f --- /dev/null +++ b/fakestagram/CheckSum.m @@ -0,0 +1,31 @@ +// +// CheckSum.m +// fakestagram +// +// Created by LuisE on 11/9/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// +#import "CheckSum.h" + +@implementation CheckSum +- (instancetype)init { + if (self = [super init]) { + } + return self; +} + ++(NSString *) sha256String: (NSString *)input{ + const char* str = [input UTF8String]; + unsigned char result[CC_SHA256_DIGEST_LENGTH]; + CC_SHA256(str, strlen(str), result); + + NSMutableString *ret = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH*2]; + for(int i = 0; i() + + func read(key: String) -> UIImage? { + return memCache.object(forKey: key as NSString) + } + + func write(key: String, value: UIImage?) { + guard let value = value else { return } + memCache.setObject(value, forKey: key as NSString) + } +} diff --git a/fakestagram/DataSource/CodableSerializer.swift b/fakestagram/DataSource/CodableSerializer.swift new file mode 100755 index 0000000..a6aedf1 --- /dev/null +++ b/fakestagram/DataSource/CodableSerializer.swift @@ -0,0 +1,35 @@ +// +// CodableSerializer.swift +// fakestagram +// +// Created by LuisE on 10/11/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +class CodableSerializer { + let data: Data? + let decoder: JSONDecoder = { + let decoder = JSONDecoder() + decoder.keyDecodingStrategy = .convertFromSnakeCase + return decoder + }() + + init(data: Data?) { + self.data = data + } + + func async(result: @escaping (T?) -> Void) { + guard let data = data else { + DispatchQueue.main.async { result(nil) } + return + } + do { + let json = try decoder.decode(T.self, from: data) + DispatchQueue.main.async { result(json) } + } catch let err { + print("Invalid JSON format: \(err.localizedDescription)") + } + } +} diff --git a/fakestagram/DataSource/DataContainer.swift b/fakestagram/DataSource/DataContainer.swift new file mode 100755 index 0000000..e3a6953 --- /dev/null +++ b/fakestagram/DataSource/DataContainer.swift @@ -0,0 +1,50 @@ +// +// DataContainer.swift +// fakestagram +// +// Created by LuisE on 11/8/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +// Usage +// DataContainer.cache.write("file.json",data: parsedData) +// DataContainer.cache.read("file.png") +// DataContainer.permanent.write("file.json",data: parsedData) +// DataContainer.permanent.read("file.png") + +enum DataContainer { + case cache + case permanent + + var baseUrl: URL { + switch self { + case .cache: + return StorageType.cache.url + case .permanent: + return StorageType.permanent.url + } + } + + func read(_ filename: String) -> Data? { + return try? Data(contentsOf: urlFor(filename: filename)) + } + + func write(_ filename: String, data: Data) -> Bool { + do { + try data.write(to: urlFor(filename: filename)) + return true + } catch let err { + debugPrint("Error: \(err.localizedDescription)") + return false + } + } + + func urlFor(filename: String) -> URL { + var url = baseUrl + url.appendPathComponent(filename) + return url + } + +} diff --git a/fakestagram/DataSource/ImageStore.swift b/fakestagram/DataSource/ImageStore.swift new file mode 100755 index 0000000..b9994f5 --- /dev/null +++ b/fakestagram/DataSource/ImageStore.swift @@ -0,0 +1,52 @@ +// +// ImageStore.swift +// fakestagram +// +// Created by LuisE on 11/8/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation +import UIKit + +// Usage +// ImagaStore.permanent.write("filename.jpg", image: img) +// ImagaStore.cache.read("filename.jpg") + +enum ImageStore { + case cache + case permanent + + var container: DataContainer { + switch self { + case .cache: + return DataContainer.cache + case .permanent: + return DataContainer.permanent + } + } + + func read(_ filename: String) -> UIImage? { + if let img = CacheImage.shared.read(key: filename) { + print(" - Reading from memory") + return img + } + print(" - Reading from disk") + guard let data = container.read(filename) else { return nil } + let image = UIImage(data: data) + + print(" * Writting into memory") + CacheImage.shared.write(key: filename, value: image) + return image + } + + func write(_ filename: String, image: UIImage) -> Bool { + guard let data = image.jpegData(compressionQuality: 0.9) else { return false } + + print(" - Writting into memory") + CacheImage.shared.write(key: filename, value: image) + + print(" - Writting into disk") + return container.write(filename, data: data) + } +} diff --git a/fakestagram/DataSource/RestClient.swift b/fakestagram/DataSource/RestClient.swift new file mode 100755 index 0000000..f22198a --- /dev/null +++ b/fakestagram/DataSource/RestClient.swift @@ -0,0 +1,58 @@ +// +// RestClient.swift +// fakestagram +// +// Created by LuisE on 10/5/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +class RestClient { + private let client: Client + let basePath: String + let encoder: JSONEncoder = { + let encoder = JSONEncoder() + encoder.keyEncodingStrategy = .convertToSnakeCase + return encoder + }() + + init(client: Client, basePath: String) { + self.client = client + self.basePath = basePath + } + + // eg. POST /posts/ + func create(_ data: T, success: @escaping (T?) -> Void) { + let payload = try? encoder.encode(data) + client.post(path: basePath, body: payload) { data in + CodableSerializer(data: data).async(result: success) + } + } + + // eg. GET /posts/ + // eg. GET /posts/:id + func show(id: String? = nil, success: @escaping (T?) -> Void) { + var path = basePath + if let uid = id { + path += "/\(uid)" + } + client.get(path: path) { data in + CodableSerializer(data: data).async(result: success) + } + } + // eg. PUT /posts/:id + func update(id: String, data: T, success: @escaping (T?) -> Void) { + let payload = try? encoder.encode(data) + client.put(path: "\(basePath)/\(id)", body: payload) { data in + CodableSerializer(data: data).async(result: success) + } + } + + // eg. DELETE /posts/:id + func delete(id: String, success: @escaping (T?) -> Void) { + client.delete(path: "\(basePath)/\(id)") { data in + CodableSerializer(data: data).async(result: success) + } + } +} diff --git a/fakestagram/DataSource/StorageType.swift b/fakestagram/DataSource/StorageType.swift new file mode 100755 index 0000000..e337d51 --- /dev/null +++ b/fakestagram/DataSource/StorageType.swift @@ -0,0 +1,47 @@ +// +// StorageType.swift +// fakestagram +// +// Created by LuisE on 11/8/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +enum StorageType { + case cache + case permanent + + var searchPathDirectory: FileManager.SearchPathDirectory { + switch self { + case .cache: + return .cachesDirectory + case .permanent: + return .documentDirectory + } + } + + var url: URL { + var url = FileManager.default.urls(for: searchPathDirectory, in: .userDomainMask).first! + let applicationPath = "mx.unam.ioslab.fakestagram.storage" + url.appendPathComponent(applicationPath) + return url + } + + var path: String { + return url.path + } + + func clear() { + try? FileManager.default.removeItem(at: url) + } + + func ensureExists() { + var isDir: ObjCBool = false + if FileManager.default.fileExists(atPath: path, isDirectory: &isDir) { + if isDir.boolValue { return } + clear() + } + try? FileManager.default.createDirectory(at: url, withIntermediateDirectories: false, attributes: nil) + } +} diff --git a/fakestagram/Info.plist b/fakestagram/Info.plist old mode 100644 new mode 100755 index 2a3483c..d1b73e7 --- a/fakestagram/Info.plist +++ b/fakestagram/Info.plist @@ -20,6 +20,10 @@ 1 LSRequiresIPhoneOS + NSCameraUsageDescription + To capture your favorite moments and share with the world + NSLocationWhenInUseUsageDescription + Geololcalize your moments UIApplicationSceneManifest UIApplicationSupportsMultipleScenes @@ -50,8 +54,6 @@ UISupportedInterfaceOrientations UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad diff --git a/fakestagram/Models/Account.swift b/fakestagram/Models/Account.swift new file mode 100755 index 0000000..9f4c69c --- /dev/null +++ b/fakestagram/Models/Account.swift @@ -0,0 +1,16 @@ +// +// Account.swift +// fakestagram +// +// Created by LuisE on 10/5/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +struct Account: Codable { + let id: String? + let name: String + let deviceNumber: String? + let deviceModel: String? +} diff --git a/fakestagram/Models/Author.swift b/fakestagram/Models/Author.swift new file mode 100755 index 0000000..607dad2 --- /dev/null +++ b/fakestagram/Models/Author.swift @@ -0,0 +1,13 @@ +// +// Author.swift +// fakestagram +// +// Created by LuisE on 10/12/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +struct Author: Codable { + let name: String +} diff --git a/fakestagram/Models/Comment.swift b/fakestagram/Models/Comment.swift new file mode 100755 index 0000000..36032c7 --- /dev/null +++ b/fakestagram/Models/Comment.swift @@ -0,0 +1,16 @@ +// +// Comment.swift +// fakestagram +// +// Created by LuisE on 10/12/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +struct Comment: Codable { + let userComment: String + let idFoto: Int? +} + + diff --git a/fakestagram/Models/Like.swift b/fakestagram/Models/Like.swift new file mode 100755 index 0000000..84f5116 --- /dev/null +++ b/fakestagram/Models/Like.swift @@ -0,0 +1,13 @@ +// +// Like.swift +// fakestagram +// +// Created by LuisE on 10/12/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +struct Like: Codable { + let idFoto: Int? +} diff --git a/fakestagram/Models/Post.swift b/fakestagram/Models/Post.swift new file mode 100755 index 0000000..0b4995e --- /dev/null +++ b/fakestagram/Models/Post.swift @@ -0,0 +1,47 @@ +// +// Post.swift +// fakestagram +// +// Created by LuisE on 10/5/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation +import UIKit + +struct Post: Codable { + let id: Int? + let title: String + let imageUrl: String? + var likesCount: Int + var commentsCount: Int + let createdAt: String + var liked: Bool + let location: String + let author: Author? + + func likesCountText() -> String { + return "\(likesCount) likes" + } + + func commentsCountText() -> String { + return "\(commentsCount) comments" + } + + func load(_ image: @escaping (UIImage) -> Void) { + guard let urlString = imageUrl, let url = URL(string: urlString) else { return } + let filename = CheckSum.sha256String(urlString)! + if let img = ImageStore.cache.read(filename) { + print("Reading cache") + image(img) + return + } + DispatchQueue.global(qos: .background).async { + if let data = try? Data(contentsOf: url), let img = UIImage(data: data) { + print("Loading from the internet") + _ = ImageStore.cache.write(filename, image: img) + DispatchQueue.main.async { image(img) } + } + } + } +} diff --git a/fakestagram/Network/Client.swift b/fakestagram/Network/Client.swift new file mode 100755 index 0000000..187f7ca --- /dev/null +++ b/fakestagram/Network/Client.swift @@ -0,0 +1,76 @@ +// +// Client.swift +// fakestagram +// +// Created by LuisE on 10/4/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +class Client { + static let fakestagram = Client(session: URLSession.shared, baseUrl: "https://fakestagram-api.herokuapp.com") + let session: URLSession + let baseUrl: String + + init(session: URLSession, baseUrl: String) { + self.session = session + self.baseUrl = baseUrl + } + + typealias successfulResponse = (Data?) -> Void + + func get(path: String, success: @escaping successfulResponse) { + request(method: "get", path: path, body: nil, success: success) + } + + func post(path: String, body: Data?, success: @escaping successfulResponse) { + request(method: "post", path: path, body: body, success: success) + } + + func put(path: String, body: Data?, success: @escaping successfulResponse) { + request(method: "put", path: path, body: body, success: success) + } + + func delete(path: String, success: @escaping successfulResponse) { + request(method: "delete", path: path, body: nil, success: success) + } + + private func request(method: String, path: String, body: Data?, success: @escaping successfulResponse) { + guard let req = buildRequest(method: method, path: path, body: body) else { + debugPrint("Invalid request") + return + } + + session.dataTask(with: req) { (data, response, error) in + if let error = error { + debugPrint(error) + return + } + + let response = HttpResponse(response: response) + if response.isSuccessful() { + success(data) + } else { + #if DEBUG + debugPrint(response.status) + if let data = data { + let error = String(data: data, encoding: .utf8) + debugPrint(error) + } + #endif + } + }.resume() + } + + private func buildRequest(method: String, path: String, body: Data?) -> URLRequest? { + var builder = RequestBuilder(baseUrl: self.baseUrl) + builder.method = method + builder.path = path + builder.body = body + if let token = Credentials.apiToken.get() { + builder.headers = ["Authorization": "Bearer \(token)"] + } + return builder.request() + } +} diff --git a/fakestagram/Network/HttpResponse.swift b/fakestagram/Network/HttpResponse.swift new file mode 100755 index 0000000..cd7b4aa --- /dev/null +++ b/fakestagram/Network/HttpResponse.swift @@ -0,0 +1,25 @@ +// +// HttpResponse.swift +// fakestagram +// +// Created by LuisE on 10/4/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +class HttpResponse { + let httpUrlResponse: HTTPURLResponse + + init(response: URLResponse?) { + self.httpUrlResponse = response as! HTTPURLResponse + } + + lazy var status: StatusCode = { + return StatusCode(rawValue: self.httpUrlResponse.statusCode) + }() + + func isSuccessful() -> Bool { + return status == StatusCode.success + } +} diff --git a/fakestagram/Network/RequestBuilder.swift b/fakestagram/Network/RequestBuilder.swift new file mode 100755 index 0000000..0fb17dd --- /dev/null +++ b/fakestagram/Network/RequestBuilder.swift @@ -0,0 +1,62 @@ +// +// RequestBuilder.swift +// fakestagram +// +// Created by LuisE on 10/4/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +struct RequestBuilder { + enum ContentMode { + case jsonApp + + func accept() -> String { + switch self { + case .jsonApp: + return "application/json" + } + } + + func contentType() -> String { + switch self { + case .jsonApp: + return "application/json" + } + } + } + private let urlComponents: URLComponents + public var scheme: String = "https" + public var method: String = "get" + public var path: String = "/" + public var body: Data? + public var headers: [String: String]? + public var contentMode: ContentMode = .jsonApp + + init(baseUrl: String) { + self.urlComponents = URLComponents(string: baseUrl)! + } + + func url() -> URL? { + var comps = self.urlComponents + comps.scheme = scheme + comps.path = path + return comps.url + } + + func request() -> URLRequest? { + guard let url = url() else { return nil } + var req = URLRequest(url: url) + req.httpMethod = method + req.httpBody = body + req.addValue(contentMode.accept(), forHTTPHeaderField: "Accept") + req.addValue(contentMode.contentType(), forHTTPHeaderField: "Content-Type") + if let headers = self.headers { + for (key, value) in headers { + req.addValue(value, forHTTPHeaderField: key) + } + } + return req + } +} diff --git a/fakestagram/Network/StatusCode.swift b/fakestagram/Network/StatusCode.swift new file mode 100755 index 0000000..cdc5e29 --- /dev/null +++ b/fakestagram/Network/StatusCode.swift @@ -0,0 +1,36 @@ +// +// StatusCode.swift +// fakestagram +// +// Created by LuisE on 10/4/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +enum StatusCode: Int { + case unkown = 0 + case info + case success + case redirection + case clientError + case serverError + + public init(rawValue: Int) { + switch rawValue { + case 100, 101, 102: + self = .info + case 200, 201, 202, 203, 204, 205, 206, 207, 208, 226: + self = .success + case 300, 301, 302, 303, 304, 305, 306, 307, 308: + self = .redirection + case 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 421, 422, 423, 424, 426, 428, 429, 431, 451: + self = .clientError + case 500, 501, 502, 503, 504, 505, 506, 507, 510, 511: + self = .serverError + default: + self = .unkown + } + } +} diff --git a/fakestagram/SceneDelegate.swift b/fakestagram/SceneDelegate.swift old mode 100644 new mode 100755 index 5d9879b..25f04f7 --- a/fakestagram/SceneDelegate.swift +++ b/fakestagram/SceneDelegate.swift @@ -12,7 +12,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. @@ -48,6 +47,4 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { // to restore the scene back to its current state. } - } - diff --git a/fakestagram/Services/CommentService.swift b/fakestagram/Services/CommentService.swift new file mode 100644 index 0000000..3c8fa57 --- /dev/null +++ b/fakestagram/Services/CommentService.swift @@ -0,0 +1,30 @@ +// +// CommentService.swift +// fakestagram +// +// Created by Jose Olvera on 04/01/20. +// Copyright © 2020 3zcurdia. All rights reserved. +// + +import Foundation + + +class CommentService { + + func call(userComment: String , idFoto: Int?, success: @escaping (Int?) -> Void){ + + let miComment = Comment( + userComment: userComment, + idFoto: idFoto + ) + + let client = RestClient(client: Client.fakestagram, basePath: "/api/v1/posts/\(miComment.idFoto!)/like") + + client.create(miComment){ post in + NotificationCenter.default.post(name: NotificationKeys.didFinishPostCreation.value, object: nil) + success(post?.idFoto) + } + } + + +} diff --git a/fakestagram/Services/CreatePostService.swift b/fakestagram/Services/CreatePostService.swift new file mode 100755 index 0000000..6a50b85 --- /dev/null +++ b/fakestagram/Services/CreatePostService.swift @@ -0,0 +1,46 @@ +// +// CreatePostService.swift +// fakestagram +// +// Created by LuisE on 11/8/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation +import UIKit +import CoreLocation + +struct CreatePost: Codable { + let id: Int? + let title: String + let imageData: String? + let latitude: Double? + let longitude: Double? +} + +//protocol Geolocable { +// func update(coordinate: CLLocationCoordinate2D?) +//} + +class CreatePostService { + private let client = RestClient(client: Client.fakestagram, basePath: "/api/v1/posts/") + private var currentLocation: CLLocationCoordinate2D? + + func call(image: UIImage, title: String, success: @escaping (Int?) -> Void) { + let newPost = CreatePost( + id: nil, + title: title, + imageData: image.base64(), + latitude: currentLocation?.latitude, + longitude: currentLocation?.longitude + ) + client.create(newPost) { post in + NotificationCenter.default.post(name: NotificationKeys.didFinishPostCreation.value, object: nil) + success(post?.id) + } + } + + func update(coordinate: CLLocationCoordinate2D?) { + currentLocation = coordinate + } +} diff --git a/fakestagram/Services/IndexService.swift b/fakestagram/Services/IndexService.swift new file mode 100755 index 0000000..5c6cb55 --- /dev/null +++ b/fakestagram/Services/IndexService.swift @@ -0,0 +1,17 @@ +// +// IndexService.swift +// fakestagram +// +// Created by LuisE on 11/9/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +class IndexService { + let client = RestClient<[Post]>(client: Client.fakestagram, basePath: "/api/v1/posts") + + func call(success: @escaping ([Post]?) -> Void) { + client.show(success: success) + } +} diff --git a/fakestagram/Services/LikeService.swift b/fakestagram/Services/LikeService.swift new file mode 100755 index 0000000..7b775e3 --- /dev/null +++ b/fakestagram/Services/LikeService.swift @@ -0,0 +1,30 @@ +// +// LikeService.swift +// fakestagram +// +// Created by Jose Olvera on 02/01/20. +// Copyright © 2020 3zcurdia. All rights reserved. +// + +import Foundation + +class LikeService { + + //private let client = RestClient(client: Client.fakestagram, basePath: "/api/v1/posts/\(miLike.idUser)/like") + + func call(idFoto: Int?, success: @escaping (Int?) -> Void) { + + let miLike = Like( + idFoto: idFoto + ) + + + let client = RestClient(client: Client.fakestagram, basePath: "/api/v1/posts/\(miLike.idFoto!)/like") + + client.create(miLike){ post in + NotificationCenter.default.post(name: NotificationKeys.didFinishPostCreation.value, object: nil) + success(post?.idFoto) + } + } + +} diff --git a/fakestagram/Utils/Credentials.swift b/fakestagram/Utils/Credentials.swift new file mode 100755 index 0000000..3ce1105 --- /dev/null +++ b/fakestagram/Utils/Credentials.swift @@ -0,0 +1,37 @@ +// +// Credentials.swift +// fakestagram +// +// Created by LuisE on 10/4/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation +import SAMKeychain + +enum Credentials { + case apiToken + + func get() -> String? { + switch self { + case .apiToken: + return SAMKeychain.password(forService: "mx.unam.fakestagram", account: "apiToken") + } + } + + func set(value: String) -> Bool { + switch self { + case .apiToken: + SAMKeychain.setPassword(value, forService: "mx.unam.fakestagram", account: "apiToken") + } + return true + } + + func destroy() -> Bool { + switch self { + case .apiToken: + SAMKeychain.deletePassword(forService: "mx.unam.fakestagram", account: "apiToken") + } + return true + } +} diff --git a/fakestagram/Utils/NotificationKeys.swift b/fakestagram/Utils/NotificationKeys.swift new file mode 100755 index 0000000..d0bf641 --- /dev/null +++ b/fakestagram/Utils/NotificationKeys.swift @@ -0,0 +1,20 @@ +// +// NotificationNames.swift +// fakestagram +// +// Created by LuisE on 11/16/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +enum NotificationKeys { + case didFinishPostCreation + + var value: Notification.Name { + switch self { + case .didFinishPostCreation: + return Notification.Name(rawValue: "didFinishPostCreationNotification") + } + } +} diff --git a/fakestagram/Utils/UIDevice+models.swift b/fakestagram/Utils/UIDevice+models.swift new file mode 100755 index 0000000..4102a1e --- /dev/null +++ b/fakestagram/Utils/UIDevice+models.swift @@ -0,0 +1,95 @@ +// +// UIDevice+models.swift +// fakestagram +// +// Created by LuisE on 10/18/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit + +public extension UIDevice { + static let identifier: String = { + if let vendorId = UIDevice.current.identifierForVendor { + return "\(vendorId.hashValue):\(vendorId.uuidString)" + } else { + return ":\(UUID().uuidString)" + } + }() + + static let modelName: String = { + var systemInfo = utsname() + uname(&systemInfo) + let machineMirror = Mirror(reflecting: systemInfo.machine) + let identifier = machineMirror.children.reduce("") { identifier, element in + guard let value = element.value as? Int8, value != 0 else { return identifier } + return identifier + String(UnicodeScalar(UInt8(value))) + } + + func mapToDevice(identifier: String) -> String { // swiftlint:disable:this cyclomatic_complexity + #if os(iOS) + switch identifier { + case "iPod5,1": return "iPod touch (5th generation)" + case "iPod7,1": return "iPod touch (6th generation)" + case "iPod9,1": return "iPod touch (7th generation)" + case "iPhone3,1", "iPhone3,2", "iPhone3,3": return "iPhone 4" + case "iPhone4,1": return "iPhone 4s" + case "iPhone5,1", "iPhone5,2": return "iPhone 5" + case "iPhone5,3", "iPhone5,4": return "iPhone 5c" + case "iPhone6,1", "iPhone6,2": return "iPhone 5s" + case "iPhone7,2": return "iPhone 6" + case "iPhone7,1": return "iPhone 6 Plus" + case "iPhone8,1": return "iPhone 6s" + case "iPhone8,2": return "iPhone 6s Plus" + case "iPhone9,1", "iPhone9,3": return "iPhone 7" + case "iPhone9,2", "iPhone9,4": return "iPhone 7 Plus" + case "iPhone8,4": return "iPhone SE" + case "iPhone10,1", "iPhone10,4": return "iPhone 8" + case "iPhone10,2", "iPhone10,5": return "iPhone 8 Plus" + case "iPhone10,3", "iPhone10,6": return "iPhone X" + case "iPhone11,2": return "iPhone XS" + case "iPhone11,4", "iPhone11,6": return "iPhone XS Max" + case "iPhone11,8": return "iPhone XR" + case "iPhone12,1": return "iPhone 11" + case "iPhone12,3": return "iPhone 11 Pro" + case "iPhone12,5": return "iPhone 11 Pro Max" + case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return "iPad 2" + case "iPad3,1", "iPad3,2", "iPad3,3": return "iPad (3rd generation)" + case "iPad3,4", "iPad3,5", "iPad3,6": return "iPad (4th generation)" + case "iPad6,11", "iPad6,12": return "iPad (5th generation)" + case "iPad7,5", "iPad7,6": return "iPad (6th generation)" + case "iPad7,11", "iPad7,12": return "iPad (7th generation)" + case "iPad4,1", "iPad4,2", "iPad4,3": return "iPad Air" + case "iPad5,3", "iPad5,4": return "iPad Air 2" + case "iPad11,4", "iPad11,5": return "iPad Air (3rd generation)" + case "iPad2,5", "iPad2,6", "iPad2,7": return "iPad mini" + case "iPad4,4", "iPad4,5", "iPad4,6": return "iPad mini 2" + case "iPad4,7", "iPad4,8", "iPad4,9": return "iPad mini 3" + case "iPad5,1", "iPad5,2": return "iPad mini 4" + case "iPad11,1", "iPad11,2": return "iPad mini (5th generation)" + case "iPad6,3", "iPad6,4": return "iPad Pro (9.7-inch)" + case "iPad6,7", "iPad6,8": return "iPad Pro (12.9-inch)" + case "iPad7,1", "iPad7,2": return "iPad Pro (12.9-inch) (2nd generation)" + case "iPad7,3", "iPad7,4": return "iPad Pro (10.5-inch)" + case "iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4":return "iPad Pro (11-inch)" + case "iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8":return "iPad Pro (12.9-inch) (3rd generation)" + case "AppleTV5,3": return "Apple TV" + case "AppleTV6,2": return "Apple TV 4K" + case "AudioAccessory1,1": return "HomePod" + case "i386", "x86_64": return "Simulator \(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "iOS"))" + default: return identifier + } + #elseif os(tvOS) + switch identifier { + case "AppleTV5,3": return "Apple TV 4" + case "AppleTV6,2": return "Apple TV 4K" + case "i386", "x86_64": return "Simulator \(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "tvOS"))" + default: return identifier + } + #endif + } + + return mapToDevice(identifier: identifier) + }() + +} diff --git a/fakestagram/Utils/UIImage+Base64.swift b/fakestagram/Utils/UIImage+Base64.swift new file mode 100755 index 0000000..5bb19a0 --- /dev/null +++ b/fakestagram/Utils/UIImage+Base64.swift @@ -0,0 +1,23 @@ +// +// UIImage+Base64.swift +// fakestagram +// +// Created by LuisE on 10/19/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit + +extension Data { + func imageBase64(ext: String = "tiff") -> String { + let encoded = self.base64EncodedString(options: .lineLength64Characters) + return "data:image/\(ext);base64,\(encoded)" + } +} + +extension UIImage { + func base64() -> String { + let data = self.jpegData(compressionQuality: 0.85)! + return data.imageBase64(ext: "jpg") + } +} diff --git a/fakestagram/ViewControllers/CameraViewController.swift b/fakestagram/ViewControllers/CameraViewController.swift new file mode 100755 index 0000000..a7996c7 --- /dev/null +++ b/fakestagram/ViewControllers/CameraViewController.swift @@ -0,0 +1,137 @@ +// +// CameraViewController.swift +// fakestagram +// +// Created by LuisE on 10/19/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit +import CoreLocation +import AVFoundation + +class CameraViewController: UIViewController { + override func viewDidLoad() { + super.viewDidLoad() + enableBasicLocationServices() + enableCameraAccess() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + locationManager.startUpdatingLocation() + } + + override func viewWillDisappear(_ animated: Bool) { + locationManager.stopUpdatingLocation() + super.viewWillDisappear(animated) + } + + let service = CreatePostService() + @IBAction func onTapCreate(_ sender: Any) { + print("📸") + let settings: AVCapturePhotoSettings + print(self.photoOutput.availablePhotoCodecTypes) + if self.photoOutput.availablePhotoCodecTypes.contains(.hevc) { + settings = AVCapturePhotoSettings(format: + [AVVideoCodecKey: AVVideoCodecType.hevc]) + } else { + settings = AVCapturePhotoSettings() + } + settings.flashMode = .auto + photoOutput.capturePhoto(with: settings, delegate: self) + } + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + + // MARK: - CoreLocation methods + let locationManager = CLLocationManager() + func enableBasicLocationServices() { + locationManager.delegate = self + switch CLLocationManager.authorizationStatus() { + case .notDetermined: + locationManager.requestWhenInUseAuthorization() + case .restricted, .denied: + print("Disable location features") + case .authorizedWhenInUse, .authorizedAlways: + print("Enable location features") + @unknown default: + fatalError() + } + } + + // MARK: - AVFoundation methods + + @IBOutlet weak var previewView: PreviewView! + func enableCameraAccess() { + switch AVCaptureDevice.authorizationStatus(for: .video) { + case .authorized: + // The user has previously granted access to the camera. + self.setupCaptureSession() + case .notDetermined: + // The user has not yet been asked for camera access. + AVCaptureDevice.requestAccess(for: .video) { granted in + if granted { + self.setupCaptureSession() + } + } + case .denied: + // The user has previously denied access. + return + case .restricted: + // The user can't grant access due to restrictions. + return + @unknown default: + fatalError() + } + } + + let session = AVCaptureSession() + let photoOutput = AVCapturePhotoOutput() + + func setupCaptureSession() { + session.beginConfiguration() + let device = AVCaptureDevice.default(.builtInDualCamera, + for: .video, position: .back)! + guard let videoDeviceInput = try? AVCaptureDeviceInput(device: device), + session.canAddInput(videoDeviceInput) else { return } + session.addInput(videoDeviceInput) + + guard session.canAddOutput(photoOutput) else { return } + session.sessionPreset = .photo + session.addOutput(photoOutput) + + session.commitConfiguration() + previewView.session = session + + session.startRunning() + } + +} + +extension CameraViewController: AVCapturePhotoCaptureDelegate { + func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { + debugPrint(photo.metadata) + + guard let data = photo.fileDataRepresentation(), let img = UIImage(data: data) else { return } + service.call(image: img, title: UUID().uuidString) { postId in + print("Successful!") + print(postId ?? -1) + } + } +} + +extension CameraViewController: CLLocationManagerDelegate { + func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + guard let location = locations.last else { return } + service.update(coordinate: location.coordinate) + } +} diff --git a/fakestagram/ViewControllers/PostViewController.swift b/fakestagram/ViewControllers/PostViewController.swift new file mode 100755 index 0000000..f18ad1d --- /dev/null +++ b/fakestagram/ViewControllers/PostViewController.swift @@ -0,0 +1,100 @@ +// +// PostViewController.swift +// fakestagram +// +// Created by LuisE on 9/28/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit + +class PostViewController: UIViewController { + var post: Post? { + didSet { + updatePostView() + } + } + @IBOutlet weak var imageView: UIImageView! + + override func viewDidLoad() { + super.viewDidLoad() + updatePostView() + loadComments { comments in + debugPrint(comments) + } + + // Do any additional setup after loading the view. + } + + func updatePostView() { + guard let post = post else { return } + post.load { img in + DispatchQueue.main.async { + self.imageView.image = img + } + } + } + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + func loadComments(successful: @escaping ([Comment]) -> Void) { + guard let uwrappedPost = post, let postId = uwrappedPost.id else { return } + let url = URL(string: "https://fakestagram-api.herokuapp.com/api/v1/posts/\(postId)/comments")! + var request = URLRequest(url: url) + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.httpMethod = "get" + request.addValue("Bearer f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e", forHTTPHeaderField: "Authorization") + + let task = URLSession.shared.dataTask(with: request) { (data, _, error) in + if error != nil || data == nil { + return + } + // get status code + + let decoder = JSONDecoder() + decoder.keyDecodingStrategy = .convertFromSnakeCase + do { + guard let data = data else { print("Empty response"); return } + let json = try decoder.decode([Comment].self, from: data) + successful(json) + } catch let err { + print("Unable to parse successfull response: \(err.localizedDescription)") + } + } + task.resume() + } + + func loadLikes(successful: @escaping ([Like]) -> Void) { + guard let uwrappedPost = post, let postId = uwrappedPost.id else { return } + let url = URL(string: "https://fakestagram-api.herokuapp.com/api/v1/posts/\(postId)/likes")! + var request = URLRequest(url: url) + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.httpMethod = "get" + request.addValue("Bearer f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e", forHTTPHeaderField: "Authorization") + + let task = URLSession.shared.dataTask(with: request) { (data, _, error) in + if error != nil || data == nil { + return + } + let decoder = JSONDecoder() + decoder.keyDecodingStrategy = .convertFromSnakeCase + do { + guard let data = data else { print("Empty response"); return } + let json = try decoder.decode([Like].self, from: data) + successful(json) + } catch let err { + print("Unable to parse successfull response: \(err.localizedDescription)") + } + } + task.resume() + } +} diff --git a/fakestagram/ViewControllers/PostsViewController.swift b/fakestagram/ViewControllers/PostsViewController.swift new file mode 100755 index 0000000..f06d81b --- /dev/null +++ b/fakestagram/ViewControllers/PostsViewController.swift @@ -0,0 +1,75 @@ +// +// PostsViewController.swift +// fakestagram +// +// Created by LuisE on 10/18/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit + +class PostsViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { + var posts: [Post]? { + didSet { + self.postsCollection.reloadData() + } + } + + let service = IndexService() + let refreshControl = UIRefreshControl() + + @IBOutlet weak var postsCollection: UICollectionView! + override func viewDidLoad() { + super.viewDidLoad() + + postsCollection.delegate = self + postsCollection.dataSource = self + let nib = UINib(nibName: String(describing: PostCollectionViewCell.self), bundle: nil) + postsCollection.register(nib, forCellWithReuseIdentifier: PostCollectionViewCell.identifier) + postsCollection.addSubview(refreshControl) + + refreshControl.addTarget(self, action: #selector(self.reloadData), for: UIControl.Event.valueChanged) + + service.call { [unowned self] data in + self.posts = data + } + NotificationCenter.default.addObserver(self, selector: #selector(reloadData), name: NotificationKeys.didFinishPostCreation.value, object: nil) + + // Do any additional setup after loading the view. + } + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + + @objc + func reloadData() { + service.call { [unowned self] data in + self.posts = data + self.refreshControl.endRefreshing() + } + } + + // MARK: - Collection View Delegates + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return self.posts?.count ?? 0 + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PostCollectionViewCell.identifier, for: indexPath) as! PostCollectionViewCell + guard let posts = self.posts else { return cell } + cell.post = posts[indexPath.row] + return cell + } + + // MARK: - Flow Layout Delegates + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + return CGSize(width: self.view.frame.width, height: 650) + } +} diff --git a/fakestagram/Views/AuthorView.swift b/fakestagram/Views/AuthorView.swift new file mode 100755 index 0000000..288967c --- /dev/null +++ b/fakestagram/Views/AuthorView.swift @@ -0,0 +1,66 @@ +// +// AuthorView.swift +// fakestagram +// +// Created by LuisE on 10/12/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit + +@IBDesignable +class AuthorView: UIView { + var author: Author? { + didSet { updateContent() } + } + + private let avatar: UIImageView = { + let iv = UIImageView() + iv.image = UIImage(systemName: "person.circle.fill") + iv.contentMode = .scaleAspectFill + iv.translatesAutoresizingMaskIntoConstraints = false + return iv + }() + private let nameLbl: UILabel = { + let lbl = UILabel() + lbl.text = "Lorem ipsum" + lbl.font = UIFont.systemFont(ofSize: 18, weight: .bold) + lbl.translatesAutoresizingMaskIntoConstraints = false + return lbl + }() + + convenience init() { + self.init(frame: .zero) + } + + override init(frame: CGRect) { + super.init(frame: frame) + setupConstraints() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupConstraints() + } + + private func setupConstraints() { + addSubview(avatar) + NSLayoutConstraint.activate([ + avatar.topAnchor.constraint(equalTo: self.topAnchor, constant: 5), + avatar.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 5), + avatar.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -5), + avatar.widthAnchor.constraint(equalToConstant: 90) + ]) + addSubview(nameLbl) + NSLayoutConstraint.activate([ + nameLbl.leadingAnchor.constraint(equalTo: avatar.trailingAnchor, constant: 5), + nameLbl.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -5), + nameLbl.centerYAnchor.constraint(equalTo: self.centerYAnchor) + ]) + } + + func updateContent() { + guard let uauthor = author else { return } + nameLbl.text = uauthor.name + } +} diff --git a/fakestagram/Views/PostCollectionViewCell.swift b/fakestagram/Views/PostCollectionViewCell.swift new file mode 100755 index 0000000..b48bdb0 --- /dev/null +++ b/fakestagram/Views/PostCollectionViewCell.swift @@ -0,0 +1,72 @@ +// +// PostCollectionViewCell.swift +// fakestagram +// +// Created by LuisE on 10/18/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit + +class PostCollectionViewCell: UICollectionViewCell { + + let miLikeService = LikeService() + let miCommentService = CommentService() + + static let identifier: String = "PostCell" + public var post: Post? { + didSet { + updateView() + } + } + @IBOutlet weak var authorView: AuthorView! + @IBOutlet weak var imageView: UIImageView! + @IBOutlet weak var likeCounter: UILabel! + @IBOutlet weak var titleLabel: UILabel! + @IBOutlet weak var likeBttn: UIButton! + @IBOutlet weak var commentBttn: UIButton! + + func reset() { + self.imageView.image = nil + self.likeCounter.text = "" + self.titleLabel.text = "" + } + + + func updateView() { + reset() + guard let post = self.post else { return } + self.authorView.author = post.author + self.titleLabel.text = post.title + self.likeCounter.text = post.likesCountText() + post.load { [unowned self] img in + self.imageView.image = img + } + } + + + + + @IBAction func Like(_ sender: Any) { + + miLikeService.call(idFoto: post?.id){ idFoto in + print("Se dio un like") + } + } + + + @IBAction func showComents(_ sender: Any) { + + miCommentService.call(userComment: "prueba comentario", idFoto: post?.id){ idFoto in + + print("prueba comentarios") + + } + + } + + + + + +} diff --git a/fakestagram/Views/PostCollectionViewCell.xib b/fakestagram/Views/PostCollectionViewCell.xib new file mode 100755 index 0000000..4308220 --- /dev/null +++ b/fakestagram/Views/PostCollectionViewCell.xib @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fakestagram/Views/PreviewView.swift b/fakestagram/Views/PreviewView.swift new file mode 100755 index 0000000..8c38648 --- /dev/null +++ b/fakestagram/Views/PreviewView.swift @@ -0,0 +1,30 @@ +// +// PreviewView.swift +// HelloCamera +// +// Created by LuisE on 11/15/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit +import AVFoundation + +class PreviewView: UIView { + override class var layerClass: AnyClass { + return AVCaptureVideoPreviewLayer.self + } + + var session: AVCaptureSession? { + get { + return videoPreviewLayer.session + } + set { + videoPreviewLayer.session = newValue + } + } + + /// Convenience wrapper to get layer as its statically known type. + var videoPreviewLayer: AVCaptureVideoPreviewLayer { + return layer as! AVCaptureVideoPreviewLayer + } +} diff --git a/fakestagram/Views/ShowPostViewController.swift b/fakestagram/Views/ShowPostViewController.swift new file mode 100755 index 0000000..c0afe40 --- /dev/null +++ b/fakestagram/Views/ShowPostViewController.swift @@ -0,0 +1,48 @@ +// +// PostViewController.swift +// fakestagram +// +// Created by LuisE on 10/12/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit + +class ShowPostViewController: UIViewController { + @IBOutlet weak var imageView: UIImageView! + @IBOutlet weak var likeCounter: UILabel! + @IBOutlet weak var titleLabel: UILabel! + @IBOutlet weak var likeBttn: UIButton! + @IBOutlet weak var commentBttn: UIButton! + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + @IBAction + func onTapLike(_ sender: Any) { + print("like") + } + + @IBAction + func onTapCreateComment(_ sender: Any) { + print("to comment") + } + + @IBAction + func onTapShowComments(_ sender: Any) { + print("to show comment") + } + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/fakestagram/Views/ShowPostViewController.xib b/fakestagram/Views/ShowPostViewController.xib new file mode 100755 index 0000000..9d91849 --- /dev/null +++ b/fakestagram/Views/ShowPostViewController.xib @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fakestagram/fakestagram-Bridging-Header.h b/fakestagram/fakestagram-Bridging-Header.h new file mode 100755 index 0000000..f31fb29 --- /dev/null +++ b/fakestagram/fakestagram-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "CheckSum.m" diff --git a/fakestagramTests/CheckSumTest.swift b/fakestagramTests/CheckSumTest.swift new file mode 100755 index 0000000..5236806 --- /dev/null +++ b/fakestagramTests/CheckSumTest.swift @@ -0,0 +1,26 @@ +// +// CheckSumTest.swift +// fakestagramTests +// +// Created by LuisE on 11/9/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import XCTest +//import CryptoKit +@testable import fakestagram + +class CheckSumTest: XCTestCase { + + func testPerformanceExample() { + let text = "lorem ipsum dolor quet sit amet consectetur" +// let data = text.data(using: .utf8)! + let expected = "df033ae7d7ff21916308e1e0f52c8f559f76bed69f5b4f8ed6237514bed8e2c4" + self.measure { + let result = CheckSum.sha256String(text) +// let result = String(SHA256.hash(data: data).description.dropFirst(15)) + XCTAssertEqual(expected, result) + } + } + +} diff --git a/fakestagramTests/Info.plist b/fakestagramTests/Info.plist old mode 100644 new mode 100755 diff --git a/fakestagramTests/RequestBuilderTests.swift b/fakestagramTests/RequestBuilderTests.swift new file mode 100755 index 0000000..01606ed --- /dev/null +++ b/fakestagramTests/RequestBuilderTests.swift @@ -0,0 +1,65 @@ +// +// RequestBuilderTests.swift +// RequestBuilderTests +// +// Created by LuisE on 9/24/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import XCTest +@testable import fakestagram + +class RequestBuilderTests: XCTestCase { + func testBuildValidURL() { + var builder = RequestBuilder(baseUrl: "https://example.com/") + builder.path = "/api/v1/accounts" + XCTAssertEqual(builder.scheme, "https") + XCTAssertEqual(builder.method, "get") + XCTAssertEqual(builder.url(), URL(string: "https://example.com/api/v1/accounts")!) + } + + func testBuildInvalidURL() { + var builder = RequestBuilder(baseUrl: "example.com") + builder.path = "//@3`-" + XCTAssertNil(builder.url()) + } + + func testBuildForceSchemeURL() { + let builder = RequestBuilder(baseUrl: "http://example.com/") + XCTAssertEqual(builder.url(), URL(string: "https://example.com/")!) + } + + func testBuildOverrideSchemeURL() { + var builder = RequestBuilder(baseUrl: "http://example.com/") + builder.scheme = "ftp" + XCTAssertEqual(builder.url(), URL(string: "ftp://example.com/")!) + } + + func testBuildInvalidRequest() { + var builder = RequestBuilder(baseUrl: "example.com") + builder.path = "//@3`-" + XCTAssertNil(builder.request()) + } + + func testBuildValidRequest() { + var builder = RequestBuilder(baseUrl: "https://example.com/") + builder.path = "/api/v1/accounts" + builder.method = "post" + builder.body = "{\"a\": 1}".data(using: .utf8) + builder.headers = ["test": "example"] + + let result = builder.request() + XCTAssertNotNil(result) + XCTAssertEqual(result!.httpMethod!, "POST") + XCTAssertEqual(result!.httpBody!, "{\"a\": 1}".data(using: .utf8)) + XCTAssertEqual(result!.allHTTPHeaderFields!, ["Accept": "application/json", "Content-Type": "application/json", "test": "example"]) + } + + func testBuildValidRequestWithDefaults() { + let result = RequestBuilder(baseUrl: "https://example.com/").request() + XCTAssertNotNil(result) + XCTAssertEqual(result!.httpMethod!, "GET") + XCTAssertNil(result!.httpBody) + XCTAssertEqual(result!.allHTTPHeaderFields!, ["Accept": "application/json", "Content-Type": "application/json"]) + } +} diff --git a/fakestagramTests/RestClientTest.swift b/fakestagramTests/RestClientTest.swift new file mode 100755 index 0000000..9ed3fc0 --- /dev/null +++ b/fakestagramTests/RestClientTest.swift @@ -0,0 +1,47 @@ +// +// RestClientTest.swift +// fakestagramTests +// +// Created by LuisE on 10/11/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import XCTest +import DVR +@testable import fakestagram + +class RestClientTest: XCTestCase { + func testShowPosts() { + let session = Session(cassetteName: "posts.successful") + let client = Client(session: session, baseUrl: "https://fakestagram-api.herokuapp.com") + let restClient = RestClient<[Post]>(client: client, basePath: "/api/v1/posts") + let exp = expectation(description: "Successfull index posts") + + restClient.show { posts in + exp.fulfill() + XCTAssertNotNil(posts) + XCTAssertEqual(posts!.count, 25) + XCTAssertEqual(posts!.first!.id, 228) + XCTAssertEqual(posts!.first!.title, "Example") + } + + waitForExpectations(timeout: 2, handler: nil) + } + + func testShowPost() { + let session = Session(cassetteName: "show_post.successful") + let client = Client(session: session, baseUrl: "https://fakestagram-api.herokuapp.com") + + let restClient = RestClient(client: client, basePath: "/api/v1/posts") + let exp = expectation(description: "Successfull index posts") + + restClient.show(id: "228") { post in + exp.fulfill() + XCTAssertNotNil(post) + XCTAssertEqual(post!.id, 228) + XCTAssertEqual(post!.title, "Example") + } + + waitForExpectations(timeout: 2, handler: nil) + } +} diff --git a/fakestagramTests/casettes/posts.successful.json b/fakestagramTests/casettes/posts.successful.json new file mode 100755 index 0000000..24d2ccf --- /dev/null +++ b/fakestagramTests/casettes/posts.successful.json @@ -0,0 +1,444 @@ +{ + "interactions" : [ + { + "request" : { + "method" : "GET", + "headers" : { + "Content-Type" : "application\/json", + "Authorization" : "Bearer f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e", + "Accept" : "application\/json" + }, + "url" : "https:\/\/fakestagram-api.herokuapp.com\/api\/v1\/posts" + }, + "recorded_at" : 1570837975.1744719, + "response" : { + "url" : "https:\/\/fakestagram-api.herokuapp.com\/api\/v1\/posts", + "headers" : { + "Etag" : "W\/\"0d7dc5010941ab1928365db038e254f9\"", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains", + "X-Request-Id" : "f9b64a0a-2902-46c5-9355-feffcda2b924", + "Vary" : "Origin", + "X-Download-Options" : "noopen", + "Via" : "1.1 vegur", + "X-Permitted-Cross-Domain-Policies" : "none", + "X-Content-Type-Options" : "nosniff", + "Content-Length" : "0", + "X-Xss-Protection" : "1; mode=block", + "Connection" : "keep-alive", + "Cache-Control" : "max-age=0, private, must-revalidate", + "Content-Type" : "application\/json; charset=utf-8", + "X-Frame-Options" : "SAMEORIGIN", + "X-Runtime" : "0.087793", + "Referrer-Policy" : "strict-origin-when-cross-origin", + "Date" : "Fri, 11 Oct 2019 23:52:54 GMT", + "Transfer-Encoding" : "Identity", + "Server" : "Cowboy" + }, + "body" : [ + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e", + "name" : "John Carney", + "avatar_url" : null + }, + "id" : 228, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZTA9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--b668068c1f6252a77beacbd9313d8f4e078a400f\/4ed83e29-b955-4dc6-b5ee-eafd994e9de8", + "title" : "Example", + "created_at" : "2019-10-04T21:15:42.650Z", + "liked" : true, + "updated_at" : "2019-10-04T21:15:42.738Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e", + "name" : "John Carney", + "avatar_url" : null + }, + "id" : 227, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZWs9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--af591b63753c7a621bbaece3f99c79c9375551b4\/9b13eeaf-3a33-45d8-9f96-09506672ddf4", + "title" : "Example", + "created_at" : "2019-10-04T05:11:50.647Z", + "liked" : true, + "updated_at" : "2019-10-04T05:11:50.701Z", + "comments_count" : 0 + }, + { + "location" : "South San Francisco BART, Bart, South San Francisco, San Mateo County, California, 94014, USA", + "likes_count" : 0, + "author" : { + "id" : "26c0b0a1-6b04-4625-9d08-f8b348b968d6", + "name" : "Gerard Hane", + "avatar_url" : null + }, + "id" : 226, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZVk9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--a89eead659aa964493322d79f9f5cca4db18ff9d\/3340cca1-dd82-4c63-ba8f-3986bddbc500", + "title" : "1566158823894", + "created_at" : "2019-08-18T20:07:04.661Z", + "liked" : false, + "updated_at" : "2019-08-18T20:07:04.686Z", + "comments_count" : 0 + }, + { + "location" : "South San Francisco BART, Bart, South San Francisco, San Mateo County, California, 94014, USA", + "likes_count" : 0, + "author" : { + "id" : "26c0b0a1-6b04-4625-9d08-f8b348b968d6", + "name" : "Gerard Hane", + "avatar_url" : null + }, + "id" : 225, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZVU9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--0e22a6bc1f9e9477762e32356036134efd54eb55\/70bb725c-e86e-4430-b925-11c25718392a", + "title" : "1566158820509", + "created_at" : "2019-08-18T20:07:01.750Z", + "liked" : false, + "updated_at" : "2019-08-18T20:07:01.854Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 2, + "author" : { + "id" : "ababf2cd-0eb9-45b6-99e5-90de794f7860", + "name" : "Katelyn Sanford", + "avatar_url" : null + }, + "id" : 224, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZVE9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--b927d8cd407bfb7f4e32dff66842cbce798e10a3\/78a88dea-8b8e-4d33-a633-5e492bc14842", + "title" : ":p", + "created_at" : "2019-08-11T20:17:49.826Z", + "liked" : false, + "updated_at" : "2019-08-11T20:17:49.895Z", + "comments_count" : 2 + }, + { + "location" : "", + "likes_count" : 1, + "author" : { + "id" : "9b590ebf-4875-4a83-8249-c6223e0d1a2a", + "name" : "Sammy Beier", + "avatar_url" : null + }, + "id" : 223, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZU09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--5726e694e2d04ec83ee589ff11293f8d4a49daf5\/3c7f898e-ae8d-410c-800d-20c590b8118e", + "title" : "1565393475188", + "created_at" : "2019-08-09T23:31:20.358Z", + "liked" : false, + "updated_at" : "2019-08-09T23:31:20.380Z", + "comments_count" : 1 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f9d53895-93f9-43c2-973e-ce47aadf6239", + "name" : "Arlinda Balistreri", + "avatar_url" : null + }, + "id" : 222, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZUk9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--3d89565f024de56af1b3d510d954b64e11593812\/0314b818-2096-4387-bcee-ed62594b013e", + "title" : "1565392767381", + "created_at" : "2019-08-09T23:19:30.715Z", + "liked" : false, + "updated_at" : "2019-08-09T23:19:30.737Z", + "comments_count" : 1 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f9d53895-93f9-43c2-973e-ce47aadf6239", + "name" : "Arlinda Balistreri", + "avatar_url" : null + }, + "id" : 221, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZUU9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--26a6cfcb28d63275d7d2e38cc19cc318106bc7a1\/74ee9a0c-3fd3-413f-9a05-ed56514f9b4c", + "title" : "1565392624022", + "created_at" : "2019-08-09T23:17:06.162Z", + "liked" : false, + "updated_at" : "2019-08-09T23:17:06.191Z", + "comments_count" : 4 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f9d53895-93f9-43c2-973e-ce47aadf6239", + "name" : "Arlinda Balistreri", + "avatar_url" : null + }, + "id" : 220, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZUE9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--84f7d1d7e2c9624478e486b85ef289101adff64b\/89fe9faf-dafb-4c44-9810-55f9dc1643f7", + "title" : "1565389845416", + "created_at" : "2019-08-09T22:30:45.562Z", + "liked" : false, + "updated_at" : "2019-08-09T22:30:45.589Z", + "comments_count" : 11 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f9d53895-93f9-43c2-973e-ce47aadf6239", + "name" : "Arlinda Balistreri", + "avatar_url" : null + }, + "id" : 219, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZDg9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--aa3dbf1922f86c5ab9f874710541abd83a10aa21\/8d34e2e6-d33d-4ac1-954b-b0c3e1403301", + "title" : "1565389827272", + "created_at" : "2019-08-09T22:30:27.612Z", + "liked" : false, + "updated_at" : "2019-08-09T22:30:27.633Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f9d53895-93f9-43c2-973e-ce47aadf6239", + "name" : "Arlinda Balistreri", + "avatar_url" : null + }, + "id" : 218, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZDQ9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--9534d1e17eab3138685b2ae633f1fce2b3072fa3\/24f26bae-f215-499a-a985-ad1cca2168e3", + "title" : "1565387654424", + "created_at" : "2019-08-09T21:54:14.782Z", + "liked" : false, + "updated_at" : "2019-08-09T21:54:14.823Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 1, + "author" : { + "id" : "cb9a00b1-c23d-4dcd-84a3-0066cc930adc", + "name" : "Melvina DuBuque", + "avatar_url" : null + }, + "id" : 217, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZDA9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--ce6d7e4e61a3bad722d0b1ecc9d9c85a5d443782\/b077e3b9-7abd-4f01-a3d4-baaeaa03d035", + "title" : "1565284409539", + "created_at" : "2019-08-08T17:13:30.621Z", + "liked" : false, + "updated_at" : "2019-08-08T17:13:30.647Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "cb9a00b1-c23d-4dcd-84a3-0066cc930adc", + "name" : "Melvina DuBuque", + "avatar_url" : null + }, + "id" : 216, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZHc9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--5fd762895b481581889f8370850660961ac27ae2\/79075b3f-a2f6-4a28-8478-2b2024361b8f", + "title" : "1565284311613", + "created_at" : "2019-08-08T17:11:51.968Z", + "liked" : false, + "updated_at" : "2019-08-08T17:11:52.041Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "1a11b5ea-b450-478c-b968-6e4bf1724a27", + "name" : "Garth Hartmann", + "avatar_url" : null + }, + "id" : 215, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZHM9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--3aaf6ee04bf6e2e276af0a7542057df4bc859a9d\/b2f6db08-2257-4bd4-9371-e784c7dd3ef5", + "title" : "1565240319353", + "created_at" : "2019-08-08T04:58:39.800Z", + "liked" : false, + "updated_at" : "2019-08-08T04:58:39.871Z", + "comments_count" : 0 + }, + { + "location" : "Powell Street Station, Market Street, Union Square, San Francisco, San Francisco City and County, California, 94103-3124, USA", + "likes_count" : 0, + "author" : { + "id" : "44a51289-6d9e-4e27-8638-6d3102511ad8", + "name" : "Melanie Gaylord", + "avatar_url" : null + }, + "id" : 214, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZG89IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--475805cb649993f55820a95307fc1f7a80db3f4e\/71f1b9e0-f262-4261-ad1d-ece8046151ef", + "title" : "1565064895736", + "created_at" : "2019-08-06T04:14:56.879Z", + "liked" : false, + "updated_at" : "2019-08-06T04:14:56.920Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "90834f94-fd51-420a-b350-30851abf61d5", + "name" : "Belle Douglas", + "avatar_url" : null + }, + "id" : 213, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZGs9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--f5b051063503aadef9f0cd9a0723c12d2d627dde\/bc279b9d-2dce-49c6-9120-4e4b575f7a78", + "title" : "1565028839754", + "created_at" : "2019-08-05T18:14:00.016Z", + "liked" : false, + "updated_at" : "2019-08-05T18:14:00.078Z", + "comments_count" : 0 + }, + { + "location" : "Powell Street Station, Market Street, Union Square, San Francisco, San Francisco City and County, California, 94103-3124, USA", + "likes_count" : 0, + "author" : { + "id" : "44a51289-6d9e-4e27-8638-6d3102511ad8", + "name" : "Melanie Gaylord", + "avatar_url" : null + }, + "id" : 212, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZGc9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--ead89bde0e160956f51b9d5d7637c4ca1b8d5643\/3c16b6e2-838b-453e-87a8-c8e623efee6f", + "title" : "1564953882318", + "created_at" : "2019-08-04T21:24:43.366Z", + "liked" : false, + "updated_at" : "2019-08-04T21:24:43.424Z", + "comments_count" : 0 + }, + { + "location" : "Powell Street Station, Market Street, Union Square, San Francisco, San Francisco City and County, California, 94103-3124, USA", + "likes_count" : 1, + "author" : { + "id" : "44a51289-6d9e-4e27-8638-6d3102511ad8", + "name" : "Melanie Gaylord", + "avatar_url" : null + }, + "id" : 211, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZGM9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--aa53a5c71d2af02eb63f222e8f62666ac020626d\/70601715-1ce5-4886-8647-614a88acdc3e", + "title" : "1564938932927", + "created_at" : "2019-08-04T17:15:34.008Z", + "liked" : false, + "updated_at" : "2019-08-04T17:15:34.072Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 1, + "author" : { + "id" : "15e6a545-c5c7-4775-b3b3-f4c08622b7f8", + "name" : "Venessa Prosacco", + "avatar_url" : null + }, + "id" : 209, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZFE9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--677615c8da9ee16d4a2f2d04d71620345dad3dcb\/a37c2b48-53b0-4200-8ca4-0ab3c601c2be", + "title" : "No lo haga compa", + "created_at" : "2019-07-26T22:14:55.445Z", + "liked" : false, + "updated_at" : "2019-07-26T22:14:55.465Z", + "comments_count" : 2 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "15e6a545-c5c7-4775-b3b3-f4c08622b7f8", + "name" : "Venessa Prosacco", + "avatar_url" : null + }, + "id" : 208, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZE09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--701845e2a532406662abd63bd9903cfb3d6fa427\/f56ff4ea-21aa-416f-9644-bbcc36c0a489", + "title" : "No lo haga compa", + "created_at" : "2019-07-26T22:14:48.407Z", + "liked" : false, + "updated_at" : "2019-07-26T22:14:48.472Z", + "comments_count" : 2 + }, + { + "location" : "Calle Durango, Condesa, Mexico City, Cuauhtémoc, Mexico City, 06140, Mexico", + "likes_count" : 0, + "author" : { + "id" : "3c06d9f5-9cc0-483e-a089-8bcc4c11c14e", + "name" : "Shenita Champlin", + "avatar_url" : null + }, + "id" : 207, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZEU9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--b375a88531fce2fba8301e8f4d9cda92016317f6\/2a6c1b7a-16d8-4155-9825-e92a834f083a", + "title" : "1563810644322", + "created_at" : "2019-07-22T15:50:48.103Z", + "liked" : false, + "updated_at" : "2019-07-22T15:50:48.219Z", + "comments_count" : 1 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "10b7accf-1817-4fe5-9674-8f7703220e96", + "name" : "Shonda Hammes", + "avatar_url" : null + }, + "id" : 206, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZEE9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--6b9c9e7a5919fc296349d7e0ba3eb327fab7e28d\/8be5a13a-b703-4e9d-bfa8-640969a1d03b", + "title" : "Las svm son chidas", + "created_at" : "2019-07-11T17:43:09.553Z", + "liked" : false, + "updated_at" : "2019-07-11T17:43:09.600Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "10b7accf-1817-4fe5-9674-8f7703220e96", + "name" : "Shonda Hammes", + "avatar_url" : null + }, + "id" : 205, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBYzg9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--9bd1e3affaa38a100b254bcc0ebfbd34697367ee\/5abbd134-50c2-4529-8474-64ad58de7383", + "title" : "Mr. Bean es mi pastor!", + "created_at" : "2019-07-11T17:40:58.360Z", + "liked" : false, + "updated_at" : "2019-07-11T17:40:58.429Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "10b7accf-1817-4fe5-9674-8f7703220e96", + "name" : "Shonda Hammes", + "avatar_url" : null + }, + "id" : 204, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZEk9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--f0193550348281afd2b2998b93997529e8ca4d16\/9b188868-6f6a-424d-b577-5bd8e99fff4c", + "title" : "Todos los del diplomado en las fiestas jajaja!", + "created_at" : "2019-07-10T23:46:37.725Z", + "liked" : false, + "updated_at" : "2019-07-23T01:22:34.916Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 1, + "author" : { + "id" : "519661d9-5f38-45dc-ba4e-ec3522aa128a", + "name" : "Lesley Funk", + "avatar_url" : null + }, + "id" : 203, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBY3M9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--954b1ccc1f0dcb9d061ac38009b43f0bd727b118\/83e80764-2bd6-40e7-b6a8-01c54af1dd84", + "title" : "1562190435299", + "created_at" : "2019-07-03T21:47:15.564Z", + "liked" : false, + "updated_at" : "2019-07-03T21:47:15.623Z", + "comments_count" : 1 + } + ], + "status" : 200 + } + } + ], + "name" : "posts.successful" +} diff --git a/fakestagramTests/casettes/show_post.successful.json b/fakestagramTests/casettes/show_post.successful.json new file mode 100755 index 0000000..03e91e1 --- /dev/null +++ b/fakestagramTests/casettes/show_post.successful.json @@ -0,0 +1,57 @@ +{ + "interactions" : [ + { + "response" : { + "status" : 200, + "body" : { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e", + "name" : "John Carney", + "avatar_url" : null + }, + "id" : 228, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZTA9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--b668068c1f6252a77beacbd9313d8f4e078a400f\/4ed83e29-b955-4dc6-b5ee-eafd994e9de8", + "title" : "Example", + "created_at" : "2019-10-04T21:15:42.650Z", + "liked" : false, + "updated_at" : "2019-10-04T21:15:42.738Z", + "comments_count" : 0 + }, + "headers" : { + "X-Permitted-Cross-Domain-Policies" : "none", + "Content-Type" : "application\/json; charset=utf-8", + "X-Request-Id" : "c6266b7f-6e74-4fc8-808c-6046b689f67f", + "Via" : "1.1 vegur", + "Cache-Control" : "max-age=0, private, must-revalidate", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains", + "Date" : "Sat, 12 Oct 2019 00:46:20 GMT", + "Transfer-Encoding" : "Identity", + "X-Xss-Protection" : "1; mode=block", + "Referrer-Policy" : "strict-origin-when-cross-origin", + "X-Download-Options" : "noopen", + "Server" : "Cowboy", + "X-Runtime" : "0.063186", + "Connection" : "keep-alive", + "Etag" : "W\/\"819b2d0fa0647c5c452d27fb77a8d11e\"", + "X-Frame-Options" : "SAMEORIGIN", + "Vary" : "Origin", + "X-Content-Type-Options" : "nosniff" + }, + "url" : "https:\/\/fakestagram-api.herokuapp.com\/api\/v1\/posts\/228" + }, + "request" : { + "headers" : { + "Accept" : "application\/json", + "Content-Type" : "application\/json", + "Authorization" : "Bearer f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e" + }, + "method" : "GET", + "url" : "https:\/\/fakestagram-api.herokuapp.com\/api\/v1\/posts\/228" + }, + "recorded_at" : 1570841180.898001 + } + ], + "name" : "show_post.successful" +}