diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a33eb7a --- /dev/null +++ b/.gitignore @@ -0,0 +1,67 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xccheckout +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output \ No newline at end of file diff --git a/.swift-version b/.swift-version new file mode 100644 index 0000000..f398a20 --- /dev/null +++ b/.swift-version @@ -0,0 +1 @@ +3.0 \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..de496ff --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: swift + +osx_image: xcode8.3 + +script: +- xcodebuild -workspace LaunchScreenSnapshot.xcworkspace -scheme Example -destination "platform=iOS Simulator,name=iPhone 7,OS=10.3" -configuration Debug -enableCodeCoverage YES clean build test + +after_success: +- bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9b273a2 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +# Release 0.1.0 + +- [x] First release. \ No newline at end of file diff --git a/Example/AppDelegate.swift b/Example/AppDelegate.swift new file mode 100644 index 0000000..52183b1 --- /dev/null +++ b/Example/AppDelegate.swift @@ -0,0 +1,22 @@ +// +// AppDelegate.swift +// Example +// +// Created by Alex Rupérez on 19/5/17. +// Copyright © 2017 alexruperez. All rights reserved. +// + +import UIKit +import LaunchScreenSnapshot + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + LaunchScreenSnapshot.protect() + return true + } + +} diff --git a/Example/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..1d060ed --- /dev/null +++ b/Example/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,93 @@ +{ + "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" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/Base.lproj/LaunchScreen.storyboard b/Example/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..b1d9411 --- /dev/null +++ b/Example/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/Base.lproj/Main.storyboard b/Example/Base.lproj/Main.storyboard new file mode 100644 index 0000000..76d5f41 --- /dev/null +++ b/Example/Base.lproj/Main.storyboard @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/Info.plist b/Example/Info.plist new file mode 100644 index 0000000..86d859b --- /dev/null +++ b/Example/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(CURRENT_PROJECT_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Example/ViewController.swift b/Example/ViewController.swift new file mode 100644 index 0000000..3e95cc7 --- /dev/null +++ b/Example/ViewController.swift @@ -0,0 +1,11 @@ +// +// ViewController.swift +// Example +// +// Created by Alex Rupérez on 19/5/17. +// Copyright © 2017 alexruperez. All rights reserved. +// + +import UIKit + +class ViewController: UIViewController {} diff --git a/ExampleUITests/ExampleUITests.swift b/ExampleUITests/ExampleUITests.swift new file mode 100644 index 0000000..6a3e145 --- /dev/null +++ b/ExampleUITests/ExampleUITests.swift @@ -0,0 +1,30 @@ +// +// ExampleUITests.swift +// ExampleUITests +// +// Created by Alex Rupérez on 19/5/17. +// Copyright © 2017 alexruperez. All rights reserved. +// + +import XCTest +import LaunchScreenSnapshot + +class ExampleUITests: XCTestCase { + + override func setUp() { + super.setUp() + continueAfterFailure = false + if #available(iOS 9.0, *) { + XCUIApplication().launch() + } + } + + override func tearDown() { + super.tearDown() + } + + func testStaticUnprotect() { + LaunchScreenSnapshot.unprotect() + } + +} diff --git a/ExampleUITests/Info.plist b/ExampleUITests/Info.plist new file mode 100644 index 0000000..6c6c23c --- /dev/null +++ b/ExampleUITests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + 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 new file mode 100644 index 0000000..28881ee --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 alexruperez + +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. \ No newline at end of file diff --git a/LaunchScreenSnapshot.gif b/LaunchScreenSnapshot.gif new file mode 100644 index 0000000..bd62555 Binary files /dev/null and b/LaunchScreenSnapshot.gif differ diff --git a/LaunchScreenSnapshot.png b/LaunchScreenSnapshot.png new file mode 100644 index 0000000..aa602da Binary files /dev/null and b/LaunchScreenSnapshot.png differ diff --git a/LaunchScreenSnapshot.podspec b/LaunchScreenSnapshot.podspec new file mode 100644 index 0000000..2ff850a --- /dev/null +++ b/LaunchScreenSnapshot.podspec @@ -0,0 +1,16 @@ +Pod::Spec.new do |s| + s.name = 'LaunchScreenSnapshot' + s.version = '0.1.0' + s.summary = 'Protects sensitive data in your app snapshot.' + + s.homepage = 'https://github.com/alexruperez/LaunchScreenSnapshot' + s.license = { :type => 'MIT', :file => 'LICENSE' } + s.authors = { 'Alex Rupérez' => 'contact@alexruperez.com' } + s.source = { :git => 'https://github.com/alexruperez/LaunchScreenSnapshot.git', :tag => s.version.to_s } + s.social_media_url = "https://twitter.com/alexruperez" + s.screenshot = 'https://raw.githubusercontent.com/alexruperez/LaunchScreenSnapshot/master/LaunchScreenSnapshot.png' + + s.ios.deployment_target = '8.0' + + s.source_files ="LaunchScreenSnapshot/*.{h,swift}" +end \ No newline at end of file diff --git a/LaunchScreenSnapshot.xcodeproj/project.pbxproj b/LaunchScreenSnapshot.xcodeproj/project.pbxproj new file mode 100644 index 0000000..95ad2e4 --- /dev/null +++ b/LaunchScreenSnapshot.xcodeproj/project.pbxproj @@ -0,0 +1,727 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + D51AD4C01ECF21E100B17CFC /* ExampleUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D51AD4BF1ECF21E100B17CFC /* ExampleUITests.swift */; }; + D5B5848C1ECEECDC00A4928F /* LaunchScreenSnapshot.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5B584821ECEECDC00A4928F /* LaunchScreenSnapshot.framework */; }; + D5B584911ECEECDC00A4928F /* LaunchScreenSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B584901ECEECDC00A4928F /* LaunchScreenSnapshotTests.swift */; }; + D5B584931ECEECDC00A4928F /* LaunchScreenSnapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = D5B584851ECEECDC00A4928F /* LaunchScreenSnapshot.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D5B584A31ECEECFF00A4928F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B584A21ECEECFF00A4928F /* AppDelegate.swift */; }; + D5B584A51ECEECFF00A4928F /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B584A41ECEECFF00A4928F /* ViewController.swift */; }; + D5B584A81ECEECFF00A4928F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D5B584A61ECEECFF00A4928F /* Main.storyboard */; }; + D5B584AA1ECEECFF00A4928F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D5B584A91ECEECFF00A4928F /* Assets.xcassets */; }; + D5B584AD1ECEECFF00A4928F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D5B584AB1ECEECFF00A4928F /* LaunchScreen.storyboard */; }; + D5B584B21ECEED3400A4928F /* LaunchScreenSnapshot.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5B584821ECEECDC00A4928F /* LaunchScreenSnapshot.framework */; }; + D5B584B31ECEED3400A4928F /* LaunchScreenSnapshot.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D5B584821ECEECDC00A4928F /* LaunchScreenSnapshot.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + D5B584B81ECEED5800A4928F /* LaunchScreenSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B584B71ECEED5800A4928F /* LaunchScreenSnapshot.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + D51AD4B71ECF209200B17CFC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D5B584791ECEECDC00A4928F /* Project object */; + proxyType = 1; + remoteGlobalIDString = D5B5849F1ECEECFF00A4928F; + remoteInfo = Example; + }; + D51AD4C21ECF21E100B17CFC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D5B584791ECEECDC00A4928F /* Project object */; + proxyType = 1; + remoteGlobalIDString = D5B5849F1ECEECFF00A4928F; + remoteInfo = Example; + }; + D5B5848D1ECEECDC00A4928F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D5B584791ECEECDC00A4928F /* Project object */; + proxyType = 1; + remoteGlobalIDString = D5B584811ECEECDC00A4928F; + remoteInfo = LaunchScreenSnapshot; + }; + D5B584B41ECEED3400A4928F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D5B584791ECEECDC00A4928F /* Project object */; + proxyType = 1; + remoteGlobalIDString = D5B584811ECEECDC00A4928F; + remoteInfo = LaunchScreenSnapshot; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + D5B584B61ECEED3500A4928F /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + D5B584B31ECEED3400A4928F /* LaunchScreenSnapshot.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + D51AD4BD1ECF21E100B17CFC /* ExampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + D51AD4BF1ECF21E100B17CFC /* ExampleUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleUITests.swift; sourceTree = ""; }; + D51AD4C11ECF21E100B17CFC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D5B584821ECEECDC00A4928F /* LaunchScreenSnapshot.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LaunchScreenSnapshot.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D5B584851ECEECDC00A4928F /* LaunchScreenSnapshot.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LaunchScreenSnapshot.h; sourceTree = ""; }; + D5B584861ECEECDC00A4928F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D5B5848B1ECEECDC00A4928F /* LaunchScreenSnapshotTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LaunchScreenSnapshotTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + D5B584901ECEECDC00A4928F /* LaunchScreenSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchScreenSnapshotTests.swift; sourceTree = ""; }; + D5B584921ECEECDC00A4928F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D5B584A01ECEECFF00A4928F /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D5B584A21ECEECFF00A4928F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + D5B584A41ECEECFF00A4928F /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + D5B584A71ECEECFF00A4928F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + D5B584A91ECEECFF00A4928F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + D5B584AC1ECEECFF00A4928F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + D5B584AE1ECEECFF00A4928F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D5B584B71ECEED5800A4928F /* LaunchScreenSnapshot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LaunchScreenSnapshot.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + D51AD4BA1ECF21E100B17CFC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D5B5847E1ECEECDC00A4928F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D5B584881ECEECDC00A4928F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D5B5848C1ECEECDC00A4928F /* LaunchScreenSnapshot.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D5B5849D1ECEECFF00A4928F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D5B584B21ECEED3400A4928F /* LaunchScreenSnapshot.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + D51AD4BE1ECF21E100B17CFC /* ExampleUITests */ = { + isa = PBXGroup; + children = ( + D51AD4BF1ECF21E100B17CFC /* ExampleUITests.swift */, + D51AD4C11ECF21E100B17CFC /* Info.plist */, + ); + path = ExampleUITests; + sourceTree = ""; + }; + D5B584781ECEECDC00A4928F = { + isa = PBXGroup; + children = ( + D5B584841ECEECDC00A4928F /* LaunchScreenSnapshot */, + D5B5848F1ECEECDC00A4928F /* LaunchScreenSnapshotTests */, + D5B584A11ECEECFF00A4928F /* Example */, + D51AD4BE1ECF21E100B17CFC /* ExampleUITests */, + D5B584831ECEECDC00A4928F /* Products */, + ); + sourceTree = ""; + }; + D5B584831ECEECDC00A4928F /* Products */ = { + isa = PBXGroup; + children = ( + D5B584821ECEECDC00A4928F /* LaunchScreenSnapshot.framework */, + D5B5848B1ECEECDC00A4928F /* LaunchScreenSnapshotTests.xctest */, + D5B584A01ECEECFF00A4928F /* Example.app */, + D51AD4BD1ECF21E100B17CFC /* ExampleUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + D5B584841ECEECDC00A4928F /* LaunchScreenSnapshot */ = { + isa = PBXGroup; + children = ( + D5B584B71ECEED5800A4928F /* LaunchScreenSnapshot.swift */, + D5B584851ECEECDC00A4928F /* LaunchScreenSnapshot.h */, + D5B584861ECEECDC00A4928F /* Info.plist */, + ); + path = LaunchScreenSnapshot; + sourceTree = ""; + }; + D5B5848F1ECEECDC00A4928F /* LaunchScreenSnapshotTests */ = { + isa = PBXGroup; + children = ( + D5B584901ECEECDC00A4928F /* LaunchScreenSnapshotTests.swift */, + D5B584921ECEECDC00A4928F /* Info.plist */, + ); + path = LaunchScreenSnapshotTests; + sourceTree = ""; + }; + D5B584A11ECEECFF00A4928F /* Example */ = { + isa = PBXGroup; + children = ( + D5B584A21ECEECFF00A4928F /* AppDelegate.swift */, + D5B584A41ECEECFF00A4928F /* ViewController.swift */, + D5B584A61ECEECFF00A4928F /* Main.storyboard */, + D5B584A91ECEECFF00A4928F /* Assets.xcassets */, + D5B584AB1ECEECFF00A4928F /* LaunchScreen.storyboard */, + D5B584AE1ECEECFF00A4928F /* Info.plist */, + ); + path = Example; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + D5B5847F1ECEECDC00A4928F /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D5B584931ECEECDC00A4928F /* LaunchScreenSnapshot.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + D51AD4BC1ECF21E100B17CFC /* ExampleUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D51AD4C41ECF21E100B17CFC /* Build configuration list for PBXNativeTarget "ExampleUITests" */; + buildPhases = ( + D51AD4B91ECF21E100B17CFC /* Sources */, + D51AD4BA1ECF21E100B17CFC /* Frameworks */, + D51AD4BB1ECF21E100B17CFC /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D51AD4C31ECF21E100B17CFC /* PBXTargetDependency */, + ); + name = ExampleUITests; + productName = ExampleUITests; + productReference = D51AD4BD1ECF21E100B17CFC /* ExampleUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; + D5B584811ECEECDC00A4928F /* LaunchScreenSnapshot */ = { + isa = PBXNativeTarget; + buildConfigurationList = D5B584961ECEECDC00A4928F /* Build configuration list for PBXNativeTarget "LaunchScreenSnapshot" */; + buildPhases = ( + D5B5847D1ECEECDC00A4928F /* Sources */, + D5B5847E1ECEECDC00A4928F /* Frameworks */, + D5B5847F1ECEECDC00A4928F /* Headers */, + D5B584801ECEECDC00A4928F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = LaunchScreenSnapshot; + productName = LaunchScreenSnapshot; + productReference = D5B584821ECEECDC00A4928F /* LaunchScreenSnapshot.framework */; + productType = "com.apple.product-type.framework"; + }; + D5B5848A1ECEECDC00A4928F /* LaunchScreenSnapshotTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D5B584991ECEECDC00A4928F /* Build configuration list for PBXNativeTarget "LaunchScreenSnapshotTests" */; + buildPhases = ( + D5B584871ECEECDC00A4928F /* Sources */, + D5B584881ECEECDC00A4928F /* Frameworks */, + D5B584891ECEECDC00A4928F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D5B5848E1ECEECDC00A4928F /* PBXTargetDependency */, + D51AD4B81ECF209200B17CFC /* PBXTargetDependency */, + ); + name = LaunchScreenSnapshotTests; + productName = LaunchScreenSnapshotTests; + productReference = D5B5848B1ECEECDC00A4928F /* LaunchScreenSnapshotTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + D5B5849F1ECEECFF00A4928F /* Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = D5B584AF1ECEECFF00A4928F /* Build configuration list for PBXNativeTarget "Example" */; + buildPhases = ( + D5B5849C1ECEECFF00A4928F /* Sources */, + D5B5849D1ECEECFF00A4928F /* Frameworks */, + D5B5849E1ECEECFF00A4928F /* Resources */, + D5B584B61ECEED3500A4928F /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D5B584B51ECEED3400A4928F /* PBXTargetDependency */, + ); + name = Example; + productName = Example; + productReference = D5B584A01ECEECFF00A4928F /* Example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D5B584791ECEECDC00A4928F /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0830; + LastUpgradeCheck = 0830; + ORGANIZATIONNAME = alexruperez; + TargetAttributes = { + D51AD4BC1ECF21E100B17CFC = { + CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = Q6BEQCNWYM; + ProvisioningStyle = Automatic; + TestTargetID = D5B5849F1ECEECFF00A4928F; + }; + D5B584811ECEECDC00A4928F = { + CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = Q6BEQCNWYM; + LastSwiftMigration = 0830; + ProvisioningStyle = Automatic; + }; + D5B5848A1ECEECDC00A4928F = { + CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = Q6BEQCNWYM; + ProvisioningStyle = Automatic; + TestTargetID = D5B5849F1ECEECFF00A4928F; + }; + D5B5849F1ECEECFF00A4928F = { + CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = Q6BEQCNWYM; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = D5B5847C1ECEECDC00A4928F /* Build configuration list for PBXProject "LaunchScreenSnapshot" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = D5B584781ECEECDC00A4928F; + productRefGroup = D5B584831ECEECDC00A4928F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D5B584811ECEECDC00A4928F /* LaunchScreenSnapshot */, + D5B5848A1ECEECDC00A4928F /* LaunchScreenSnapshotTests */, + D5B5849F1ECEECFF00A4928F /* Example */, + D51AD4BC1ECF21E100B17CFC /* ExampleUITests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + D51AD4BB1ECF21E100B17CFC /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D5B584801ECEECDC00A4928F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D5B584891ECEECDC00A4928F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D5B5849E1ECEECFF00A4928F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D5B584AD1ECEECFF00A4928F /* LaunchScreen.storyboard in Resources */, + D5B584AA1ECEECFF00A4928F /* Assets.xcassets in Resources */, + D5B584A81ECEECFF00A4928F /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + D51AD4B91ECF21E100B17CFC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D51AD4C01ECF21E100B17CFC /* ExampleUITests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D5B5847D1ECEECDC00A4928F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D5B584B81ECEED5800A4928F /* LaunchScreenSnapshot.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D5B584871ECEECDC00A4928F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D5B584911ECEECDC00A4928F /* LaunchScreenSnapshotTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D5B5849C1ECEECFF00A4928F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D5B584A51ECEECFF00A4928F /* ViewController.swift in Sources */, + D5B584A31ECEECFF00A4928F /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + D51AD4B81ECF209200B17CFC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D5B5849F1ECEECFF00A4928F /* Example */; + targetProxy = D51AD4B71ECF209200B17CFC /* PBXContainerItemProxy */; + }; + D51AD4C31ECF21E100B17CFC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D5B5849F1ECEECFF00A4928F /* Example */; + targetProxy = D51AD4C21ECF21E100B17CFC /* PBXContainerItemProxy */; + }; + D5B5848E1ECEECDC00A4928F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D5B584811ECEECDC00A4928F /* LaunchScreenSnapshot */; + targetProxy = D5B5848D1ECEECDC00A4928F /* PBXContainerItemProxy */; + }; + D5B584B51ECEED3400A4928F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D5B584811ECEECDC00A4928F /* LaunchScreenSnapshot */; + targetProxy = D5B584B41ECEED3400A4928F /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + D5B584A61ECEECFF00A4928F /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + D5B584A71ECEECFF00A4928F /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + D5B584AB1ECEECFF00A4928F /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + D5B584AC1ECEECFF00A4928F /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + D51AD4C51ECF21E100B17CFC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = ExampleUITests/Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = com.alexruperez.LaunchScreenSnapshot.Example.UITests; + TEST_TARGET_NAME = Example; + }; + name = Debug; + }; + D51AD4C61ECF21E100B17CFC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = ExampleUITests/Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = com.alexruperez.LaunchScreenSnapshot.Example.UITests; + TEST_TARGET_NAME = Example; + }; + name = Release; + }; + D5B584941ECEECDC00A4928F /* 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++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_ASSIGN_ENUM = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = "${DYLIB_CURRENT_VERSION}"; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = Q6BEQCNWYM; + DYLIB_COMPATIBILITY_VERSION = 0.1.0; + DYLIB_CURRENT_VERSION = 0.1.0; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SHORT_ENUMS = YES; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_PEDANTIC = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULE_VERSION = "${DYLIB_CURRENT_VERSION}"; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_BUILDER = alexruperez; + }; + name = Debug; + }; + D5B584951ECEECDC00A4928F /* 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++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_ASSIGN_ENUM = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = "${DYLIB_CURRENT_VERSION}"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = Q6BEQCNWYM; + DYLIB_COMPATIBILITY_VERSION = 0.1.0; + DYLIB_CURRENT_VERSION = 0.1.0; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_SHORT_ENUMS = YES; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_PEDANTIC = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULE_VERSION = "${DYLIB_CURRENT_VERSION}"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_BUILDER = alexruperez; + }; + name = Release; + }; + D5B584971ECEECDC00A4928F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + DEFINES_MODULE = YES; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = LaunchScreenSnapshot/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.alexruperez.LaunchScreenSnapshot; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + D5B584981ECEECDC00A4928F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + DEFINES_MODULE = YES; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = LaunchScreenSnapshot/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.alexruperez.LaunchScreenSnapshot; + SKIP_INSTALL = YES; + }; + name = Release; + }; + D5B5849A1ECEECDC00A4928F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + INFOPLIST_FILE = LaunchScreenSnapshotTests/Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = com.alexruperez.LaunchScreenSnapshot.Tests; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example"; + }; + name = Debug; + }; + D5B5849B1ECEECDC00A4928F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + INFOPLIST_FILE = LaunchScreenSnapshotTests/Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = com.alexruperez.LaunchScreenSnapshot.Tests; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example"; + }; + name = Release; + }; + D5B584B01ECEECFF00A4928F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = Example/Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = com.alexruperez.LaunchScreenSnapshot.Example; + }; + name = Debug; + }; + D5B584B11ECEECFF00A4928F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = Example/Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = com.alexruperez.LaunchScreenSnapshot.Example; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + D51AD4C41ECF21E100B17CFC /* Build configuration list for PBXNativeTarget "ExampleUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D51AD4C51ECF21E100B17CFC /* Debug */, + D51AD4C61ECF21E100B17CFC /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + D5B5847C1ECEECDC00A4928F /* Build configuration list for PBXProject "LaunchScreenSnapshot" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D5B584941ECEECDC00A4928F /* Debug */, + D5B584951ECEECDC00A4928F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D5B584961ECEECDC00A4928F /* Build configuration list for PBXNativeTarget "LaunchScreenSnapshot" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D5B584971ECEECDC00A4928F /* Debug */, + D5B584981ECEECDC00A4928F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D5B584991ECEECDC00A4928F /* Build configuration list for PBXNativeTarget "LaunchScreenSnapshotTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D5B5849A1ECEECDC00A4928F /* Debug */, + D5B5849B1ECEECDC00A4928F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D5B584AF1ECEECFF00A4928F /* Build configuration list for PBXNativeTarget "Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D5B584B01ECEECFF00A4928F /* Debug */, + D5B584B11ECEECFF00A4928F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D5B584791ECEECDC00A4928F /* Project object */; +} diff --git a/LaunchScreenSnapshot.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/LaunchScreenSnapshot.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..6cc47fe --- /dev/null +++ b/LaunchScreenSnapshot.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/LaunchScreenSnapshot.xcodeproj/xcshareddata/xcschemes/Example.xcscheme b/LaunchScreenSnapshot.xcodeproj/xcshareddata/xcschemes/Example.xcscheme new file mode 100644 index 0000000..cc3c0cd --- /dev/null +++ b/LaunchScreenSnapshot.xcodeproj/xcshareddata/xcschemes/Example.xcscheme @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LaunchScreenSnapshot.xcodeproj/xcshareddata/xcschemes/LaunchScreenSnapshot.xcscheme b/LaunchScreenSnapshot.xcodeproj/xcshareddata/xcschemes/LaunchScreenSnapshot.xcscheme new file mode 100644 index 0000000..58c1089 --- /dev/null +++ b/LaunchScreenSnapshot.xcodeproj/xcshareddata/xcschemes/LaunchScreenSnapshot.xcscheme @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LaunchScreenSnapshot.xcworkspace/contents.xcworkspacedata b/LaunchScreenSnapshot.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..e248013 --- /dev/null +++ b/LaunchScreenSnapshot.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/LaunchScreenSnapshot.xcworkspace/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist b/LaunchScreenSnapshot.xcworkspace/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..04df8b7 --- /dev/null +++ b/LaunchScreenSnapshot.xcworkspace/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/LaunchScreenSnapshot/Info.plist b/LaunchScreenSnapshot/Info.plist new file mode 100644 index 0000000..09738df --- /dev/null +++ b/LaunchScreenSnapshot/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + $(CURRENT_PROJECT_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/LaunchScreenSnapshot/LaunchScreenSnapshot.h b/LaunchScreenSnapshot/LaunchScreenSnapshot.h new file mode 100644 index 0000000..c5767d9 --- /dev/null +++ b/LaunchScreenSnapshot/LaunchScreenSnapshot.h @@ -0,0 +1,19 @@ +// +// LaunchScreenSnapshot.h +// LaunchScreenSnapshot +// +// Created by Alex Rupérez on 19/5/17. +// Copyright © 2017 alexruperez. All rights reserved. +// + +#import + +//! Project version number for LaunchScreenSnapshot. +FOUNDATION_EXPORT double LaunchScreenSnapshotVersionNumber; + +//! Project version string for LaunchScreenSnapshot. +FOUNDATION_EXPORT const unsigned char LaunchScreenSnapshotVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/LaunchScreenSnapshot/LaunchScreenSnapshot.swift b/LaunchScreenSnapshot/LaunchScreenSnapshot.swift new file mode 100644 index 0000000..c6b0292 --- /dev/null +++ b/LaunchScreenSnapshot/LaunchScreenSnapshot.swift @@ -0,0 +1,189 @@ +// +// LaunchScreenSnapshot.swift +// LaunchScreenSnapshot +// +// Created by Alex Rupérez on 19/5/17. +// Copyright © 2017 alexruperez. All rights reserved. +// + +import UIKit + +public class LaunchScreenSnapshot { + + /// Shared LaunchScreenSnapshot instance with default configuration. + public static let shared = LaunchScreenSnapshot() + /// UIWindow where your custom snapshot will be added. + public var window: UIWindow? + fileprivate let application: UIApplication + fileprivate var view: UIView? + fileprivate var duration: TimeInterval = 0 + fileprivate var delay: TimeInterval = 0 + fileprivate var dampingRatio: CGFloat = 0 + fileprivate var velocity: CGFloat = 0 + fileprivate var options: UIViewAnimationOptions = [] + fileprivate var force = false + private let notificationCenter: NotificationCenter + private let bundle: Bundle + + /** + Protects your app snapshot with the provided parameters. + + - Parameter view: Your custom view for your app snapshot, by default is your Info.plist UILaunchStoryboardName or your UILaunchStoryboards -> UIDefaultLaunchStoryboard initial ViewController view. + - Parameter duration: The total duration of the animations, measured in seconds. If you specify a negative value or 0, the changes are made without animating them. Default is 0. + - Parameter delay: The amount of time (measured in seconds) to wait before beginning the animations. Specify a value of 0 to begin the animations immediately. Default is 0. + - Parameter dampingRatio: The damping ratio for the spring animation as it approaches its quiescent state. + To smoothly decelerate the animation without oscillation, use a value of 1. Employ a damping ratio closer to zero to increase oscillation. Default is 1. + - Parameter velocity: The initial spring velocity. For smooth start to the animation, match this value to the view’s velocity as it was prior to attachment. + A value of 1 corresponds to the total animation distance traversed in one second. For example, if the total animation distance is 200 points and you want the start of the animation to match a view velocity of 100 pt/s, use a value of 0.5. Default is 0. + - Parameter options: A mask of options indicating how you want to perform the animations. For a list of valid constants, see UIViewAnimationOptions. Default is []. + - Parameter force: Forces the presentation of your app snapshot. Default is false. + + - Returns: Shared LaunchScreenSnapshot instance with default configuration. + */ + @discardableResult public static func protect(with view: UIView? = nil, duration: TimeInterval = 0, delay: TimeInterval = 0, dampingRatio: CGFloat = 1, velocity: CGFloat = 0, options: UIViewAnimationOptions = [], force: Bool = false) -> LaunchScreenSnapshot { + let launchScreenSnapshot = LaunchScreenSnapshot.shared + launchScreenSnapshot.protect(with: view, duration: duration, delay: delay, dampingRatio: dampingRatio, velocity: velocity, options: options, force: force) + return launchScreenSnapshot + } + + /** + Unprotects your app snapshot. + + - Returns: Shared LaunchScreenSnapshot instance with default configuration. + */ + @discardableResult public static func unprotect() -> LaunchScreenSnapshot { + let launchScreenSnapshot = LaunchScreenSnapshot.shared + launchScreenSnapshot.unprotect() + return launchScreenSnapshot + } + + /** + Initializes a new LaunchScreenSnapshot with the provided configuration. + + - Parameter application: Your UIApplication. By default is .shared + - Parameter notificationCenter: Your NotificationCenter. By default is .default + - Parameter bundle: Your Bundle. By default is .main + + - Returns: A LaunchScreenSnapshot instance, custom built. + */ + public init(application: UIApplication = .shared, notificationCenter: NotificationCenter = .default, bundle: Bundle = .main) { + self.application = application + self.window = application.delegate?.window ?? application.keyWindow ?? application.windows.first + self.notificationCenter = notificationCenter + self.bundle = bundle + notificationCenter.addObserver(self, selector: #selector(applicationWillResignActive), name: .UIApplicationWillResignActive, object: nil) + notificationCenter.addObserver(self, selector: #selector(applicationWillEnterForeground), name: .UIApplicationWillEnterForeground, object: nil) + notificationCenter.addObserver(self, selector: #selector(applicationDidBecomeActive), name: .UIApplicationDidBecomeActive, object: nil) + } + + deinit { + unprotect() + notificationCenter.removeObserver(self) + } + + /** + Protects your app snapshot with the provided parameters. + + - Parameter view: Your custom view for your app snapshot, by default is your Info.plist UILaunchStoryboardName or your UILaunchStoryboards -> UIDefaultLaunchStoryboard initial ViewController view. + - Parameter duration: The total duration of the animations, measured in seconds. If you specify a negative value or 0, the changes are made without animating them. Default is 0. + - Parameter delay: The amount of time (measured in seconds) to wait before beginning the animations. Specify a value of 0 to begin the animations immediately. Default is 0. + - Parameter dampingRatio: The damping ratio for the spring animation as it approaches its quiescent state. + To smoothly decelerate the animation without oscillation, use a value of 1. Employ a damping ratio closer to zero to increase oscillation. Default is 1. + - Parameter velocity: The initial spring velocity. For smooth start to the animation, match this value to the view’s velocity as it was prior to attachment. + A value of 1 corresponds to the total animation distance traversed in one second. For example, if the total animation distance is 200 points and you want the start of the animation to match a view velocity of 100 pt/s, use a value of 0.5. Default is 0. + - Parameter options: A mask of options indicating how you want to perform the animations. For a list of valid constants, see UIViewAnimationOptions. Default is []. + - Parameter force: Forces the presentation of your app snapshot. Default is false. + + - Returns: true if your app snapshot has been protected. + */ + @discardableResult public func protect(with view: UIView? = nil, duration: TimeInterval = 0, delay: TimeInterval = 0, dampingRatio: CGFloat = 1, velocity: CGFloat = 0, options: UIViewAnimationOptions = [], force: Bool = false) -> Bool { + self.view = view + if self.view == nil { + if let launchStoryboardName = bundle.object(forInfoDictionaryKey: "UILaunchStoryboardName") as? String { + self.view = viewFromStoryboard(name: launchStoryboardName, bundle: bundle) + } else if let launchStoryboards = bundle.object(forInfoDictionaryKey: "UILaunchStoryboards") as? [AnyHashable: Any], let defaultLaunchStoryboard = launchStoryboards["UIDefaultLaunchStoryboard"] as? String, let definitions = launchStoryboards["UILaunchStoryboardDefinitions"] as? [AnyHashable: Any], let launchStoryboardName = definitions[defaultLaunchStoryboard] as? String { + self.view = viewFromStoryboard(name: launchStoryboardName, bundle: bundle) + } + } + self.duration = duration + self.delay = delay + assert(dampingRatio > 0, "LaunchScreenSnapshot: dampingRatio must be greater than 0.") + self.dampingRatio = dampingRatio + self.velocity = velocity + self.options = options + self.force = force + if force { + addView() + } + return self.view == nil + } + + /// Unprotects your app snapshot. + public func unprotect() { + force = false + removeView { [weak self] in + self?.view = nil + } + } + +} + +private extension LaunchScreenSnapshot { + + @objc func applicationWillResignActive(_ notification: Notification) { + application.ignoreSnapshotOnNextApplicationLaunch() + addView() + } + + @objc func applicationWillEnterForeground(_ notification: Notification) { + removeView() + } + + @objc func applicationDidBecomeActive(_ notification: Notification) { + if force { + addView() + } else { + removeView() + } + } + + func addView() { + if let view = view { + view.alpha = 0 + window?.addSubview(view) + window?.bringSubview(toFront: view) + UIView.animate(withDuration: duration, delay: delay, usingSpringWithDamping: dampingRatio, initialSpringVelocity: velocity, options: options, animations: { + view.alpha = 1 + }) + } + } + + func removeView(completion: (() -> Swift.Void)? = nil) { + guard !force else { + return + } + if let view = view { + guard duration > 0 else { + view.alpha = 0 + view.removeFromSuperview() + completion?() + return + } + UIView.animate(withDuration: duration, delay: delay, usingSpringWithDamping: dampingRatio, initialSpringVelocity: velocity, options: options, animations: { + view.alpha = 0 + }, completion: { _ in + view.removeFromSuperview() + completion?() + }) + } else { + completion?() + } + } + + func viewFromStoryboard(name: String, bundle: Bundle? = nil) -> UIView? { + let storyboard = UIStoryboard(name: name, bundle: bundle) + let viewController = storyboard.instantiateInitialViewController() + return viewController?.view + } + +} diff --git a/LaunchScreenSnapshotTests/Info.plist b/LaunchScreenSnapshotTests/Info.plist new file mode 100644 index 0000000..6c6c23c --- /dev/null +++ b/LaunchScreenSnapshotTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/LaunchScreenSnapshotTests/LaunchScreenSnapshotTests.swift b/LaunchScreenSnapshotTests/LaunchScreenSnapshotTests.swift new file mode 100644 index 0000000..067298b --- /dev/null +++ b/LaunchScreenSnapshotTests/LaunchScreenSnapshotTests.swift @@ -0,0 +1,81 @@ +// +// LaunchScreenSnapshotTests.swift +// LaunchScreenSnapshotTests +// +// Created by Alex Rupérez on 19/5/17. +// Copyright © 2017 alexruperez. All rights reserved. +// + +import XCTest +@testable import LaunchScreenSnapshot + +class LaunchScreenSnapshotTests: XCTestCase { + + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func testApplicationWillResignActive() { + let window = UIWindow() + let view = UIView() + let notificationCenter = NotificationCenter.default + let launchScreenSnapshot = LaunchScreenSnapshot(notificationCenter: notificationCenter) + launchScreenSnapshot.window = window + launchScreenSnapshot.protect(with: view) + XCTAssertFalse(window.subviews.contains(view)) + notificationCenter.post(name: .UIApplicationWillResignActive, object: nil) + XCTAssertTrue(window.subviews.contains(view)) + } + + func testApplicationDidBecomeActive() { + let window = UIWindow() + let view = UIView() + let notificationCenter = NotificationCenter.default + let launchScreenSnapshot = LaunchScreenSnapshot(notificationCenter: notificationCenter) + launchScreenSnapshot.window = window + XCTAssertFalse(window.subviews.contains(view)) + launchScreenSnapshot.protect(with: view, force: true) + notificationCenter.post(name: .UIApplicationDidBecomeActive, object: nil) + XCTAssertTrue(window.subviews.contains(view)) + } + + func testApplicationWillEnterForeground() { + let window = UIWindow() + let view = UIView() + let notificationCenter = NotificationCenter.default + let launchScreenSnapshot = LaunchScreenSnapshot(notificationCenter: notificationCenter) + launchScreenSnapshot.window = window + launchScreenSnapshot.protect(with: view) + XCTAssertFalse(window.subviews.contains(view)) + notificationCenter.post(name: .UIApplicationWillResignActive, object: nil) + XCTAssertTrue(window.subviews.contains(view)) + notificationCenter.post(name: .UIApplicationWillEnterForeground, object: nil) + XCTAssertFalse(window.subviews.contains(view)) + } + + func testStaticProtectUnprotect() { + let window = UIWindow() + let view = UIView() + let launchScreenSnapshot = LaunchScreenSnapshot.protect(with: view) + launchScreenSnapshot.window = window + XCTAssertFalse(window.subviews.contains(view)) + NotificationCenter.default.post(name: .UIApplicationWillResignActive, object: nil) + XCTAssertTrue(window.subviews.contains(view)) + LaunchScreenSnapshot.unprotect() + XCTAssertFalse(window.subviews.contains(view)) + } + + func testViewFromStoryboard() { + let window = UIWindow() + let launchScreenSnapshot = LaunchScreenSnapshot(bundle: Bundle(identifier: "com.alexruperez.LaunchScreenSnapshot.Example")!) + launchScreenSnapshot.window = window + launchScreenSnapshot.protect() + NotificationCenter.default.post(name: .UIApplicationWillResignActive, object: nil) + XCTAssertGreaterThan(window.subviews.count, 0) + } + +} diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..6ef38f3 --- /dev/null +++ b/Package.swift @@ -0,0 +1,7 @@ +import PackageDescription + +let package = Package( + name: "LaunchScreenSnapshot", + dependencies : [], + exclude: ["LaunchScreenSnapshotTests", "Example", "ExampleUITests"] +) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..9d5ca88 --- /dev/null +++ b/README.md @@ -0,0 +1,84 @@ +# LaunchScreenSnapshot + +[![Twitter](https://img.shields.io/badge/contact-@alexruperez-0FABFF.svg?style=flat)](http://twitter.com/alexruperez) +[![Version](https://img.shields.io/cocoapods/v/LaunchScreenSnapshot.svg?style=flat)](http://cocoapods.org/pods/LaunchScreenSnapshot) +[![License](https://img.shields.io/cocoapods/l/LaunchScreenSnapshot.svg?style=flat)](http://cocoapods.org/pods/LaunchScreenSnapshot) +[![Platform](https://img.shields.io/cocoapods/p/LaunchScreenSnapshot.svg?style=flat)](http://cocoapods.org/pods/LaunchScreenSnapshot) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![Swift Package Manager Compatible](https://img.shields.io/badge/Swift%20Package%20Manager-compatible-4BC51D.svg?style=flat)](https://github.com/apple/swift-package-manager) +[![Build Status](https://travis-ci.org/alexruperez/LaunchScreenSnapshot.svg?branch=master)](https://travis-ci.org/alexruperez/LaunchScreenSnapshot) +[![Code Coverage](https://codecov.io/gh/alexruperez/LaunchScreenSnapshot/branch/master/graph/badge.svg)](https://codecov.io/gh/alexruperez/LaunchScreenSnapshot) + +*LaunchScreenSnapshot* protects sensitive data in your app snapshot. + +![*LaunchScreenSnapshot*](https://raw.githubusercontent.com/alexruperez/LaunchScreenSnapshot/master/LaunchScreenSnapshot.gif) + +## Installation + +LaunchScreenSnapshot is available through [*CocoaPods*](http://cocoapods.org). To install +it, simply add the following line to your Podfile: + +```ruby +pod 'LaunchScreenSnapshot' +``` + +#### Or you can install it with [*Carthage*](https://github.com/Carthage/Carthage): + +```ogdl +github "alexruperez/LaunchScreenSnapshot" +``` + +#### Or install it with [*Swift Package Manager*](https://swift.org/package-manager/): + +```swift +dependencies: [ + .Package(url: "https://github.com/alexruperez/LaunchScreenSnapshot.git") +] +``` + +## Usage + +#### Protect your app snapshot: + +```swift +LaunchScreenSnapshot.protect() +``` + +#### Unprotect your app snapshot: + +```swift +LaunchScreenSnapshot.unprotect() +``` + +### Advanced usage + +#### Shared instance: + +```swift +let launchScreenSnapshot = LaunchScreenSnapshot.shared +``` + +#### Custom built: + +```swift +let launchScreenSnapshot = LaunchScreenSnapshot(application: <#T##Custom UIApplication#>, notificationCenter: <#T##Custom NotificationCenter#>, bundle: <#T##Custom Bundle#>) +``` + +#### Provided parameters: + +```swift +launchScreenSnapshot.protect(with: <#T##Custom UIView?#>, duration: <#T##Duration TimeInterval#>, delay: <#T##Delay TimeInterval#>, dampingRatio: <#T##Damping Ratio CGFloat#>, velocity: <#T##Velocity CGFloat#>, options: <#T##UIViewAnimationOptions#>, force: <#T##Force Bool#>) +``` + +## Etc. + +* Contributions are very welcome. +* Attribution is appreciated (let's spread the word!), but not mandatory. + +## Authors + +[alexruperez](https://github.com/alexruperez), contact@alexruperez.com + +## License + +*LaunchScreenSnapshot* is available under the MIT license. See the LICENSE file for more info. diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..3397c9a --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-architect \ No newline at end of file