Initial commit for reupload

This commit is contained in:
Andrew Walz 2016-12-25 16:59:29 -10:00
commit 903414eedc
28 changed files with 1845 additions and 0 deletions

View file

@ -0,0 +1,336 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1675A9761E00A68300B80903 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1675A9751E00A68300B80903 /* AppDelegate.swift */; };
1675A9781E00A68300B80903 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1675A9771E00A68300B80903 /* ViewController.swift */; };
1675A97B1E00A68300B80903 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1675A9791E00A68300B80903 /* Main.storyboard */; };
1675A97D1E00A68300B80903 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1675A97C1E00A68300B80903 /* Assets.xcassets */; };
1675A9801E00A68300B80903 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1675A97E1E00A68300B80903 /* LaunchScreen.storyboard */; };
1675A98D1E00A74A00B80903 /* PreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1675A9891E00A74A00B80903 /* PreviewView.swift */; };
1675A98E1E00A74A00B80903 /* SwiftyCamButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1675A98A1E00A74A00B80903 /* SwiftyCamButton.swift */; };
1675A98F1E00A74A00B80903 /* SwiftyCamViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1675A98B1E00A74A00B80903 /* SwiftyCamViewController.swift */; };
1675A9901E00A74A00B80903 /* SwiftyCamViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1675A98C1E00A74A00B80903 /* SwiftyCamViewControllerDelegate.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
1675A9721E00A68300B80903 /* DemoSwiftyCam.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DemoSwiftyCam.app; sourceTree = BUILT_PRODUCTS_DIR; };
1675A9751E00A68300B80903 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
1675A9771E00A68300B80903 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
1675A97A1E00A68300B80903 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
1675A97C1E00A68300B80903 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
1675A97F1E00A68300B80903 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
1675A9811E00A68300B80903 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
1675A9891E00A74A00B80903 /* PreviewView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PreviewView.swift; path = ../../Source/PreviewView.swift; sourceTree = "<group>"; };
1675A98A1E00A74A00B80903 /* SwiftyCamButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftyCamButton.swift; path = ../../Source/SwiftyCamButton.swift; sourceTree = "<group>"; };
1675A98B1E00A74A00B80903 /* SwiftyCamViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftyCamViewController.swift; path = ../../Source/SwiftyCamViewController.swift; sourceTree = "<group>"; };
1675A98C1E00A74A00B80903 /* SwiftyCamViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftyCamViewControllerDelegate.swift; path = ../../Source/SwiftyCamViewControllerDelegate.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
1675A96F1E00A68300B80903 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
1675A9691E00A68300B80903 = {
isa = PBXGroup;
children = (
1675A9741E00A68300B80903 /* DemoSwiftyCam */,
1675A9731E00A68300B80903 /* Products */,
);
sourceTree = "<group>";
};
1675A9731E00A68300B80903 /* Products */ = {
isa = PBXGroup;
children = (
1675A9721E00A68300B80903 /* DemoSwiftyCam.app */,
);
name = Products;
sourceTree = "<group>";
};
1675A9741E00A68300B80903 /* DemoSwiftyCam */ = {
isa = PBXGroup;
children = (
1675A9911E00A74F00B80903 /* Source */,
1675A9751E00A68300B80903 /* AppDelegate.swift */,
1675A9771E00A68300B80903 /* ViewController.swift */,
1675A9791E00A68300B80903 /* Main.storyboard */,
1675A97C1E00A68300B80903 /* Assets.xcassets */,
1675A97E1E00A68300B80903 /* LaunchScreen.storyboard */,
1675A9811E00A68300B80903 /* Info.plist */,
);
path = DemoSwiftyCam;
sourceTree = "<group>";
};
1675A9911E00A74F00B80903 /* Source */ = {
isa = PBXGroup;
children = (
1675A9891E00A74A00B80903 /* PreviewView.swift */,
1675A98A1E00A74A00B80903 /* SwiftyCamButton.swift */,
1675A98B1E00A74A00B80903 /* SwiftyCamViewController.swift */,
1675A98C1E00A74A00B80903 /* SwiftyCamViewControllerDelegate.swift */,
);
name = Source;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
1675A9711E00A68300B80903 /* DemoSwiftyCam */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1675A9841E00A68300B80903 /* Build configuration list for PBXNativeTarget "DemoSwiftyCam" */;
buildPhases = (
1675A96E1E00A68300B80903 /* Sources */,
1675A96F1E00A68300B80903 /* Frameworks */,
1675A9701E00A68300B80903 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = DemoSwiftyCam;
productName = DemoSwiftyCam;
productReference = 1675A9721E00A68300B80903 /* DemoSwiftyCam.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
1675A96A1E00A68300B80903 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0810;
LastUpgradeCheck = 0820;
ORGANIZATIONNAME = Cappsule;
TargetAttributes = {
1675A9711E00A68300B80903 = {
CreatedOnToolsVersion = 8.1;
DevelopmentTeam = LW28KCU8N5;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 1675A96D1E00A68300B80903 /* Build configuration list for PBXProject "DemoSwiftyCam" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 1675A9691E00A68300B80903;
productRefGroup = 1675A9731E00A68300B80903 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
1675A9711E00A68300B80903 /* DemoSwiftyCam */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
1675A9701E00A68300B80903 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1675A9801E00A68300B80903 /* LaunchScreen.storyboard in Resources */,
1675A97D1E00A68300B80903 /* Assets.xcassets in Resources */,
1675A97B1E00A68300B80903 /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
1675A96E1E00A68300B80903 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1675A9781E00A68300B80903 /* ViewController.swift in Sources */,
1675A9901E00A74A00B80903 /* SwiftyCamViewControllerDelegate.swift in Sources */,
1675A9761E00A68300B80903 /* AppDelegate.swift in Sources */,
1675A98F1E00A74A00B80903 /* SwiftyCamViewController.swift in Sources */,
1675A98D1E00A74A00B80903 /* PreviewView.swift in Sources */,
1675A98E1E00A74A00B80903 /* SwiftyCamButton.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
1675A9791E00A68300B80903 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
1675A97A1E00A68300B80903 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
1675A97E1E00A68300B80903 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
1675A97F1E00A68300B80903 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
1675A9821E00A68300B80903 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = 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_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
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_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 = 10.1;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
1675A9831E00A68300B80903 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = 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_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "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 = gnu99;
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 = 10.1;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
1675A9851E00A68300B80903 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = LW28KCU8N5;
INFOPLIST_FILE = DemoSwiftyCam/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.Cappsule.DemoSwiftyCam;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
1675A9861E00A68300B80903 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = LW28KCU8N5;
INFOPLIST_FILE = DemoSwiftyCam/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.Cappsule.DemoSwiftyCam;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
1675A96D1E00A68300B80903 /* Build configuration list for PBXProject "DemoSwiftyCam" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1675A9821E00A68300B80903 /* Debug */,
1675A9831E00A68300B80903 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1675A9841E00A68300B80903 /* Build configuration list for PBXNativeTarget "DemoSwiftyCam" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1675A9851E00A68300B80903 /* Debug */,
1675A9861E00A68300B80903 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 1675A96A1E00A68300B80903 /* Project object */;
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:DemoSwiftyCam.xcodeproj">
</FileRef>
</Workspace>

View file

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0820"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1675A9711E00A68300B80903"
BuildableName = "DemoSwiftyCam.app"
BlueprintName = "DemoSwiftyCam"
ReferencedContainer = "container:DemoSwiftyCam.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1675A9711E00A68300B80903"
BuildableName = "DemoSwiftyCam.app"
BlueprintName = "DemoSwiftyCam"
ReferencedContainer = "container:DemoSwiftyCam.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1675A9711E00A68300B80903"
BuildableName = "DemoSwiftyCam.app"
BlueprintName = "DemoSwiftyCam"
ReferencedContainer = "container:DemoSwiftyCam.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1675A9711E00A68300B80903"
BuildableName = "DemoSwiftyCam.app"
BlueprintName = "DemoSwiftyCam"
ReferencedContainer = "container:DemoSwiftyCam.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>DemoSwiftyCam.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>1675A9711E00A68300B80903</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>

View file

@ -0,0 +1,54 @@
/*Copyright (c) 2016, Andrew Walz.
Redistribution and use in source and binary forms, with or without modification,are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: 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:.
}
}

View file

@ -0,0 +1,48 @@
{
"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"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "Camera@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "Camera@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View file

@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View file

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "flash@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "Flash@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "flipcamera@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "flipCamera@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11542" systemVersion="16C48b" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="DemoSwiftyCam" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SH4-0K-8ra">
<rect key="frame" x="325" y="30" width="30" height="22"/>
<state key="normal" image="Flash"/>
<connections>
<action selector="toggleFlashAction:" destination="BYZ-38-t0r" eventType="touchUpInside" id="j1T-ak-teR"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Bb3-ix-Jd1">
<rect key="frame" x="20" y="28" width="30" height="26"/>
<state key="normal" image="flipCamera"/>
<connections>
<action selector="cameraSwitchAction:" destination="BYZ-38-t0r" eventType="touchUpInside" id="a9E-90-SZM"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="Bb3-ix-Jd1" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="8" symbolic="YES" id="2Fx-Ut-jDO"/>
<constraint firstAttribute="trailingMargin" secondItem="SH4-0K-8ra" secondAttribute="trailing" constant="4" id="AiE-Y6-Sxj"/>
<constraint firstItem="Bb3-ix-Jd1" firstAttribute="centerY" secondItem="SH4-0K-8ra" secondAttribute="centerY" id="Cnv-VO-rR3"/>
<constraint firstItem="Bb3-ix-Jd1" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leadingMargin" constant="4" id="yuS-xl-hcP"/>
</constraints>
</view>
<connections>
<outlet property="flipCameraButton" destination="Bb3-ix-Jd1" id="Q9m-ib-9iQ"/>
<outlet property="toggleFlashButton" destination="SH4-0K-8ra" id="BSt-X8-4Do"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
<resources>
<image name="Flash" width="30" height="19"/>
<image name="flipCamera" width="30" height="26"/>
</resources>
</document>

View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSMicrophoneUsageDescription</key>
<string>To record audio with videos</string>
<key>NSCameraUsageDescription</key>
<string>To take photos and videos</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View file

@ -0,0 +1,83 @@
/*Copyright (c) 2016, Andrew Walz.
Redistribution and use in source and binary forms, with or without modification,are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
import UIKit
class ViewController: SwiftyCamViewController, SwiftyCamViewControllerDelegate {
@IBOutlet weak var flipCameraButton: UIButton!
@IBOutlet weak var toggleFlashButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
cameraDelegate = self
kMaximumVideoDuration = 10.0
tapToFocus = true
pinchToZoom = true
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let button : SwiftyCamButton = SwiftyCamButton(frame: CGRect(x: (self.view.frame.width / 2) - 35, y: self.view.frame.height - 85, width: 70, height: 70))
button.delegate = self
button.setImage(UIImage(named: "Camera"), for: UIControlState())
self.view.addSubview(button)
self.view.bringSubview(toFront: flipCameraButton)
self.view.bringSubview(toFront: toggleFlashButton)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func SwiftyCamDidTakePhoto(_ photo: UIImage) {
print(photo)
}
func SwiftyCamDidBeginRecordingVideo() {
print("Did Begin Recording")
}
func SwiftyCamDidFinishRecordingVideo() {
print("Did finish Recording")
}
func SwiftyCamDidFinishProcessingVideoAt(_ url: String) {
print(url)
}
func SwiftyCamDidFocusAtPoint(focusPoint: CGPoint) {
print(focusPoint)
}
func SwiftyCamDidChangeZoomLevel(zoomLevel: CGFloat) {
print(zoomLevel)
}
func SwiftyCamDidSwitchCameras(camera: SwiftyCamViewController.CameraSelection) {
print(camera)
}
@IBAction func cameraSwitchAction(_ sender: Any) {
switchCamera()
}
@IBAction func toggleFlashAction(_ sender: Any) {
toggleFlash()
}
}

22
LICENSE Normal file
View file

@ -0,0 +1,22 @@
Copyright (c) 2016, Andrew Walz.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

205
README.md Normal file
View file

@ -0,0 +1,205 @@
# SwiftyCam
[![Version](https://img.shields.io/cocoapods/v/SwiftyCam.svg?style=flat)](http://cocoapods.org/pods/SwiftyCam)
[![License](https://img.shields.io/cocoapods/l/SwiftyCam.svg?style=flat)](http://cocoapods.org/pods/SwiftyCam)
[![Platform](https://img.shields.io/cocoapods/p/SwiftyCam.svg?style=flat)](http://cocoapods.org/pods/SwiftyCam)
## Overview
SwiftyCam is a a simple, clean iOS Camera framework for easy photo and video capture. SwiftyCam allows users to capture both photos and videos from the same session with very little configuration.
Configuring a Camera View Controller in AVFoundation can be tedious and time consuming. SwiftyCam is a drop in View Controller which gives complete control of the AVSession.
## Requirements
* iOS 8.0+
* Swift 3.0+
## License
SwiftyCam is available under the BSD license. See the LICENSE file for more info.
## Installation
### Cocoapods:
SwiftyCam is available through [CocoaPods](http://cocoapods.org). To install
it, simply add the following line to your Podfile:
```ruby
pod "SwiftyCam"
```
### Manual Installation:
Simply copy the contents of the Source folder into your project.
## Usage
Using SwiftyCam is very simple.
### Prerequisites:
As of iOS 10, Apple requires the additon of the NSCameraUsageDescription and NSMicrophoneUsageDescription strings to the info.plist of your application. Example:
<key>NSCameraUsageDescription</key>
<string>To Take Photos and Video</string>
<key>NSMicrophoneUsageDescription</key>
<string>To Record Audio With Video</string>
### Getting Started:
Add the import statement to the View Controller you ware working in:
import SwiftyCam
SwiftyCam is a drop-in convenience framework. To create a Camera instance, create a new UIViewController subclass. Replace the UIViewController subclass declaration with SwiftyCamViewController:
class MyCameraViewController : SwiftyCamViewController
That is all that is required to setup the AVSession for photo and video capture. SwiftyCam will prompt the user for permission to use the camera/microphone, and configure both the device inputs and outputs.
## Capture
### SwiftyCamButton:
SwiftyCam comes with a very convenient method of capturing media. SwiftyCamButton uses gesture recognizers to take either photos of videos.
A single tap of the SwiftyCam button triggers a photo capture.
A long press/tap and hold gesture initiates a video capture. Releasing the button ends the video recoring.
To use a SwiftyCamButton, simply create one and assign the delegate to your SwiftyCamViewController:
let captureButton = SwiftyCamButton(frame: buttonFrame)
captureButton.delegate = self
### Manual:
Capturing media with SwiftyCam is very simple. To capture a photo, simply call the takePhoto function:
takePhoto()
Capturing Video is just as easy. To begin recording video, call the startVideoRecording function:
startVideoRecording()
To end the capture of a video, call the endVideoRecordingFunction:
endVideoRecording()
###Delegate
In order to acquire the photos and videos taken by either the SwiftyCamButton or manually, you must implement the SwiftyCamViewControllerDelegate and set the delegate to your view controller instance:
class MyCameraViewController : SwiftyCamViewController, SwiftyCamViewControllerDelegate
and in your viewDidLoad, assign the cameraDelegate to self:
self.cameraDelegate = self
####Delegate methods:
**SwiftyCamDidTakePhoto(_ photo:UIImage)** - Return a UIImage captured from the AVSession
**SwiftyCamDidBeginRecordingVideo()** - Called when the capture session begins recording a video
**SwiftyCamDidFinishRecordingVideo()** - Called when the capture session has finished recording a video and has begun processing
**SwiftyCamDidFinishProcessingVideoAt(_ url: String)** - Called when the capture session finished processing the video returns the location on disk the video is stored. This will always be in the temorary folder of the device.
**SwiftyCamDidSwitchCameras(camera: SwiftyCamViewController.CameraSelection)** - Called when the user has initiated a switch in camera orientations.
**SwiftyCamDidFocusAtPoint(focusPoint: CGPoint)** - Returns the point on the preview where a tap to focus was initiated (Will only be called if *tapToFocus* is set to *true*)
**SwiftyCamDidChangeZoomLevel(zoomLevel: CGFloat)** - Returns the current zoom level of the preview layer after a pinch to zoom has been initiated. Will be called several times (Will only be called if *pinchToZoom* is set to *true*)
**SwiftyCamDidFailCameraPermissionSettings()** - Called during SwiftyCamViewController launch if the user has denied permission to access either the camera of microphone (Will only be called if *promptToAppPrivacySettings* is set to *false*)
## Flash
The flash(torch) can be enabled on the device by calling:
toggleFlash()
The flash will only be enabled if the current camera is the rear camera and will automatically if the camera switches or the View Controller is dismissed.
## Switching Camera
SwiftyCam supports capture from both the front and back cameras. To switch cameras, call the function:
switchCamera()
Tap-to-focus, pinch-to-zoom and camera flash are not supported when the front facing camera is selected. *Switching video while video is being recorded is not currently supported*
##Configuration
SwiftyCam has several options for configurating the functionality of the capture:
### Video Quality
Video quality can be set by the **videoQuality** property of SwiftyCamViewController. The choices available correspond to the matching **AVCaptureSessionPreset**:
* **.high** (AVCapturePresetHigh)
* **.medium** (AVCapturePresetMedium)
* **.low** (AVCapturePresetLow)
* **.resolution352x288** (AVCaptureSessionPreset352x288)
* **.resolution640x480** (AVCaptureSessionPreset640x480)
* **.resolution1280x720** (AVCaptureSessionPreset1280x720)
* **.resolution1920x1080** (AVCaptureSessionPreset1920x1080)
* **.resolution3840x2160** (AVCaptureSessionPreset3840x2160)
* **.iframe960x540** (AVCaptureSessionPresetiFrame960x540)
* **.iframe1280x720** (AVCaptureSessionPresetiFrame1280x720)
The default value is **.resolution1920x1080**
### Maximum Video Duration
If using a SwiftyCamButton, you can set a maximum video duration for the length of video. The video recording will me automatically stopped once the time limit has been reached and the delegate method **SwiftyCamDidFinishRecordingVideo** will be called. To set this value, simply change the **kMaximumVideoDuration** value:
kMaximumVideoDuration = 10.0
A value of **0.0** will allow for unlimited video recording via the SwiftyCamButton. The default value is **0.0**.
## Camera Zoom
SwiftyCam supports digital zoom of the camera session via pinch gestures. The gestures work similar to the default iOS app and will zoom to the maximum supported zoom level. Camera zoom is only supported on the rear facing camera. AVFoundation does not currently support front facing camera zoom. To disable this feature, change the **pinchToZoom** property:
pinchToZoom = false
By default, **pinchToZoom** is enabled.
## Camera Focus
SwiftyCam, by default, support tap to focus on the video preview. SwiftyCam will set the focus and exposure levels of the session to the tapped point. Autofocus and autoexposure will be resumed once SwiftyCam detects significant movement from the tapped point. To disable this feature, change the **tapToFocus** property:
tapToFocus = false
By default, **tapToFocus** is enabled. If you wish to show a on screen animation when a tap to focus is initiated, you can use the **SwiftyCamDidFocusAtPoint(focusPoint:)** to get the coordinates of tap and provide your own tap animation
## Privacy
When a user firsts launch SwiftyCamViewController, they will be prompted for permission for access to the cameras and microphones. By default, if a user declines access to the hardware, SwiftyCam will provide a prompt to the App privacy settings inside the iOS settings application. If you wish to change this behaviour, the **promptToAppPrivacySettings** property can be modified:
promptToAppPrivacySettings = false
Instead of prompting the user to the settings application, the delegate method **SwiftyCamDidFailCameraPermissionSettings** will be called and will have to be manually handled.
## Miscellaneous
Other properties:
* **isCameraFlashOn** - Bool
* **isVideoRecording** - Bool
* **isSessionRunning** - Bool
* **currentCamera** - CameraSelection
### Contact
If you have any questions, requests, or enhancements, feel free to submit a pull request, create an issue, or contact me in person:
**Andrew Walz**
**andrewjwalz@gmail.com**

49
Source/PreviewView.swift Normal file
View file

@ -0,0 +1,49 @@
/*Copyright (c) 2016, Andrew Walz.
Redistribution and use in source and binary forms, with or without modification,are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
import UIKit
import AVFoundation
class PreviewView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.black
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
var videoPreviewLayer: AVCaptureVideoPreviewLayer {
return layer as! AVCaptureVideoPreviewLayer
}
var session: AVCaptureSession? {
get {
return videoPreviewLayer.session
}
set {
videoPreviewLayer.session = newValue
}
}
// MARK: UIView
override class var layerClass : AnyClass {
return AVCaptureVideoPreviewLayer.self
}
}

View file

@ -0,0 +1,82 @@
/*Copyright (c) 2016, Andrew Walz.
Redistribution and use in source and binary forms, with or without modification,are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
import UIKit
public protocol SwiftyCamButtonDelegate {
func buttonWasTapped()
func buttonDidBeginLongPress()
func buttonDidEndLongPress()
func longPressDidReachMaximumDuration()
func setMaxiumVideoDuration() -> Double
}
open class SwiftyCamButton: UIButton {
public var delegate: SwiftyCamButtonDelegate?
fileprivate var timer : Timer?
override public init(frame: CGRect) {
super.init(frame: frame)
createGestureRecognizers()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
createGestureRecognizers()
}
@objc fileprivate func Tap() {
self.delegate?.buttonWasTapped()
}
@objc fileprivate func LongPress(_ sender:UILongPressGestureRecognizer!) {
if (sender.state == UIGestureRecognizerState.ended) {
invalidateTimer()
self.delegate?.buttonDidEndLongPress()
} else if (sender.state == UIGestureRecognizerState.began) {
self.delegate?.buttonDidBeginLongPress()
startTimer()
}
}
@objc fileprivate func timerFinished() {
invalidateTimer()
self.delegate?.longPressDidReachMaximumDuration()
}
fileprivate func startTimer() {
if let duration = delegate?.setMaxiumVideoDuration() {
if duration != 0.0 && duration > 0.0 {
timer = Timer.scheduledTimer(timeInterval: duration, target: self, selector: #selector(SwiftyCamButton.timerFinished), userInfo: nil, repeats: false)
}
}
}
fileprivate func invalidateTimer() {
timer?.invalidate()
timer = nil
}
fileprivate func createGestureRecognizers() {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(SwiftyCamButton.Tap))
let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(SwiftyCamButton.LongPress))
self.addGestureRecognizer(tapGesture)
self.addGestureRecognizer(longGesture)
}
}

View file

@ -0,0 +1,536 @@
/*Copyright (c) 2016, Andrew Walz.
Redistribution and use in source and binary forms, with or without modification,are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
import UIKit
import AVFoundation
open class SwiftyCamViewController: UIViewController {
public enum CameraSelection {
case rear
case front
}
public enum VideoQuality {
case high
case medium
case low
case resolution352x288
case resolution640x480
case resolution1280x720
case resolution1920x1080
case resolution3840x2160
case iframe960x540
case iframe1280x720
}
fileprivate enum SessionSetupResult {
case success
case notAuthorized
case configurationFailed
}
public var cameraDelegate: SwiftyCamViewControllerDelegate?
public var kMaximumVideoDuration : Double = 0.0
public var videoQuality : VideoQuality = .resolution1920x1080
public var pinchToZoom = true
public var tapToFocus = true
public var promptToAppPrivacySettings = true
private(set) public var isCameraFlashOn = false
private(set) public var isVideRecording = false
private(set) public var isSessionRunning = false
private(set) public var currentCamera = CameraSelection.rear
fileprivate let session = AVCaptureSession()
fileprivate let sessionQueue = DispatchQueue(label: "session queue", attributes: [])
fileprivate var zoomScale = CGFloat(1.0)
fileprivate var beginZoomScale = CGFloat(1.0)
fileprivate var setupResult = SessionSetupResult.success
fileprivate var backgroundRecordingID : UIBackgroundTaskIdentifier? = nil
fileprivate var videoDeviceInput : AVCaptureDeviceInput!
fileprivate var movieFileOutput : AVCaptureMovieFileOutput?
fileprivate var photoFileOutput : AVCaptureStillImageOutput?
fileprivate var videoDevice : AVCaptureDevice?
fileprivate var previewLayer : PreviewView!
override open func viewDidLoad() {
super.viewDidLoad()
previewLayer = PreviewView(frame: self.view.frame)
addGestureRecognizers(toView: previewLayer)
self.view.addSubview(previewLayer)
previewLayer.session = session
switch AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo){
case .authorized:
break
case .notDetermined:
sessionQueue.suspend()
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { [unowned self] granted in
if !granted {
self.setupResult = .notAuthorized
}
self.sessionQueue.resume()
})
default:
setupResult = .notAuthorized
}
sessionQueue.async { [unowned self] in
self.configureSession()
}
}
override open func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
sessionQueue.async {
switch self.setupResult {
case .success:
self.session.startRunning()
self.isSessionRunning = self.session.isRunning
case .notAuthorized:
self.promptToAppSettings()
case .configurationFailed:
DispatchQueue.main.async(execute: { [unowned self] in
let message = NSLocalizedString("Unable to capture media", comment: "Alert message when something goes wrong during capture session configuration")
let alertController = UIAlertController(title: "AVCam", message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Alert OK button"), style: .cancel, handler: nil))
self.present(alertController, animated: true, completion: nil)
})
}
}
}
override open func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if self.isSessionRunning == true {
self.session.stopRunning()
self.isSessionRunning = false
}
disableFlash()
}
func takePhoto() {
if let videoConnection = photoFileOutput?.connection(withMediaType: AVMediaTypeVideo) {
videoConnection.videoOrientation = AVCaptureVideoOrientation.portrait
photoFileOutput?.captureStillImageAsynchronously(from: videoConnection, completionHandler: {(sampleBuffer, error) in
if (sampleBuffer != nil) {
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
let image = self.processPhoto(imageData!)
self.cameraDelegate?.SwiftyCamDidTakePhoto(image)
}
})
}
}
func startVideoRecording() {
guard let movieFileOutput = self.movieFileOutput else {
return
}
let videoPreviewLayerOrientation = previewLayer!.videoPreviewLayer.connection.videoOrientation
sessionQueue.async { [unowned self] in
if !movieFileOutput.isRecording {
if UIDevice.current.isMultitaskingSupported {
self.backgroundRecordingID = UIApplication.shared.beginBackgroundTask(expirationHandler: nil)
}
// Update the orientation on the movie file output video connection before starting recording.
let movieFileOutputConnection = self.movieFileOutput?.connection(withMediaType: AVMediaTypeVideo)
//flip video output if front facing camera is selected
if self.currentCamera == .front {
movieFileOutputConnection?.isVideoMirrored = true
}
movieFileOutputConnection?.videoOrientation = videoPreviewLayerOrientation
// Start recording to a temporary file.
let outputFileName = UUID().uuidString
let outputFilePath = (NSTemporaryDirectory() as NSString).appendingPathComponent((outputFileName as NSString).appendingPathExtension("mov")!)
movieFileOutput.startRecording(toOutputFileURL: URL(fileURLWithPath: outputFilePath), recordingDelegate: self)
self.isVideRecording = true
self.cameraDelegate?.SwiftyCamDidBeginRecordingVideo()
}
else {
movieFileOutput.stopRecording()
}
}
}
func endVideoRecording() {
if self.movieFileOutput?.isRecording == true {
self.isVideRecording = false
movieFileOutput!.stopRecording()
self.cameraDelegate?.SwiftyCamDidFinishRecordingVideo()
}
}
func switchCamera() {
if isVideRecording == true {
print("[SwiftyCam]: Switching between cameras while recoring video is not supported")
return
}
switch currentCamera {
case .front:
self.currentCamera = .rear
case .rear:
self.currentCamera = .front
}
sessionQueue.async { [unowned self] in
let currentInputs : [AVCaptureInput] = self.session.inputs as! [AVCaptureInput]
let currentOutputs : [AVCaptureOutput] = self.session.outputs as! [AVCaptureOutput]
for input in currentInputs {
self.session.removeInput(input)
}
for output in currentOutputs {
self.session.removeOutput(output)
}
self.configureSession()
self.cameraDelegate?.SwiftyCamDidSwitchCameras(camera: self.currentCamera)
}
disableFlash()
}
func toggleFlash() {
guard self.currentCamera == .rear else {
return
}
let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
if (device?.hasTorch)! {
do {
try device?.lockForConfiguration()
if (device?.torchMode == AVCaptureTorchMode.on) {
device?.torchMode = AVCaptureTorchMode.off
self.isCameraFlashOn = false
} else {
do {
try device?.setTorchModeOnWithLevel(1.0)
self.isCameraFlashOn = true
} catch {
print("[SwiftyCam]: \(error)")
}
}
device?.unlockForConfiguration()
} catch {
print("[SwiftyCam]: \(error)")
}
}
}
override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard tapToFocus == true, currentCamera == .rear else {
return
}
let screenSize = previewLayer!.bounds.size
if let touchPoint = touches.first {
let x = touchPoint.location(in: previewLayer!).y / screenSize.height
let y = 1.0 - touchPoint.location(in: previewLayer!).x / screenSize.width
let focusPoint = CGPoint(x: x, y: y)
if let device = videoDevice {
do {
try device.lockForConfiguration()
device.focusPointOfInterest = focusPoint
//device.focusMode = .continuousAutoFocus
device.focusMode = .autoFocus
//device.focusMode = .locked
device.exposurePointOfInterest = focusPoint
device.exposureMode = AVCaptureExposureMode.continuousAutoExposure
device.unlockForConfiguration()
self.cameraDelegate?.SwiftyCamDidFocusAtPoint(focusPoint: touchPoint.location(in: previewLayer))
}
catch {
// just ignore
}
}
}
}
/**************************************** Private Functions ****************************************/
fileprivate func configureSession() {
guard setupResult == .success else {
return
}
session.beginConfiguration()
addVideoInput()
addAudioInput()
configureVideoOutput()
configurePhotoOutput()
session.commitConfiguration()
}
fileprivate func addVideoInput() {
switch currentCamera {
case .front:
videoDevice = SwiftyCamViewController.deviceWithMediaType(AVMediaTypeVideo, preferringPosition: .front)
case .rear:
videoDevice = SwiftyCamViewController.deviceWithMediaType(AVMediaTypeVideo, preferringPosition: .back)
}
if let device = videoDevice {
do {
try device.lockForConfiguration()
if device.isFocusModeSupported(.continuousAutoFocus) {
device.focusMode = .continuousAutoFocus
if device.isSmoothAutoFocusSupported {
device.isSmoothAutoFocusEnabled = true
}
}
if device.isExposureModeSupported(.continuousAutoExposure) {
device.exposureMode = .continuousAutoExposure
}
if device.isWhiteBalanceModeSupported(.continuousAutoWhiteBalance) {
device.whiteBalanceMode = .continuousAutoWhiteBalance
}
device.unlockForConfiguration()
} catch {
print("[SwiftyCam]: Error locking configuration")
}
}
do {
let videoDeviceInput = try AVCaptureDeviceInput(device: videoDevice)
if session.canAddInput(videoDeviceInput) {
session.addInput(videoDeviceInput)
self.videoDeviceInput = videoDeviceInput
} else {
print("[SwiftyCam]: Could not add video device input to the session")
setupResult = .configurationFailed
session.commitConfiguration()
return
}
} catch {
print("[SwiftyCam]: Could not create video device input: \(error)")
setupResult = .configurationFailed
return
}
}
fileprivate func addAudioInput() {
do {
let audioDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio)
let audioDeviceInput = try AVCaptureDeviceInput(device: audioDevice)
if session.canAddInput(audioDeviceInput) {
session.addInput(audioDeviceInput)
}
else {
print("[SwiftyCam]: Could not add audio device input to the session")
}
}
catch {
print("[SwiftyCam]: Could not create audio device input: \(error)")
}
}
fileprivate func configureVideoOutput() {
let movieFileOutput = AVCaptureMovieFileOutput()
if self.session.canAddOutput(movieFileOutput) {
self.session.addOutput(movieFileOutput)
self.session.sessionPreset = videoInputPresetFromVideoQuality(quality: videoQuality)
print(videoInputPresetFromVideoQuality(quality: videoQuality))
if let connection = movieFileOutput.connection(withMediaType: AVMediaTypeVideo) {
if connection.isVideoStabilizationSupported {
connection.preferredVideoStabilizationMode = .auto
}
}
self.movieFileOutput = movieFileOutput
}
}
fileprivate func configurePhotoOutput() {
let photoFileOutput = AVCaptureStillImageOutput()
if self.session.canAddOutput(photoFileOutput) {
photoFileOutput.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
self.session.addOutput(photoFileOutput)
self.photoFileOutput = photoFileOutput
}
}
fileprivate func processPhoto(_ imageData: Data) -> UIImage {
let dataProvider = CGDataProvider(data: imageData as CFData)
let cgImageRef = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: CGColorRenderingIntent.defaultIntent)
var image: UIImage!
switch self.currentCamera {
case .front:
image = UIImage(cgImage: cgImageRef!, scale: 1.0, orientation: .rightMirrored)
case .rear:
image = UIImage(cgImage: cgImageRef!, scale: 1.0, orientation: .right)
}
return image
}
@objc fileprivate func zoomGesture(pinch: UIPinchGestureRecognizer) {
guard pinchToZoom == true else {
return
}
do {
let captureDevice = AVCaptureDevice.devices().first as? AVCaptureDevice
try captureDevice?.lockForConfiguration()
zoomScale = max(1.0, min(beginZoomScale * pinch.scale, captureDevice!.activeFormat.videoMaxZoomFactor))
captureDevice?.videoZoomFactor = zoomScale
self.cameraDelegate?.SwiftyCamDidChangeZoomLevel(zoomLevel: zoomScale)
captureDevice?.unlockForConfiguration()
} catch {
print("[SwiftyCam]: Error locking configuration")
}
}
fileprivate func addGestureRecognizers(toView: UIView) {
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(zoomGesture(pinch:)))
pinchGesture.delegate = self
toView.addGestureRecognizer(pinchGesture)
}
fileprivate func promptToAppSettings() {
guard promptToAppPrivacySettings == true else {
self.cameraDelegate?.SwiftyCamDidFailCameraPermissionSettings()
return
}
DispatchQueue.main.async(execute: { [unowned self] in
let message = NSLocalizedString("AVCam doesn't have permission to use the camera, please change privacy settings", comment: "Alert message when the user has denied access to the camera")
let alertController = UIAlertController(title: "AVCam", message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Alert OK button"), style: .cancel, handler: nil))
alertController.addAction(UIAlertAction(title: NSLocalizedString("Settings", comment: "Alert button to open Settings"), style: .default, handler: { action in
if #available(iOS 10.0, *) {
UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
} else {
if let appSettings = URL(string: UIApplicationOpenSettingsURLString) {
UIApplication.shared.openURL(appSettings)
}
}
}))
self.present(alertController, animated: true, completion: nil)
})
}
fileprivate func videoInputPresetFromVideoQuality(quality: VideoQuality) -> String {
switch quality {
case .high: return AVCaptureSessionPresetHigh
case .medium: return AVCaptureSessionPresetMedium
case .low: return AVCaptureSessionPresetLow
case .resolution352x288: return AVCaptureSessionPreset352x288
case .resolution640x480: return AVCaptureSessionPreset640x480
case .resolution1280x720: return AVCaptureSessionPreset1280x720
case .resolution1920x1080: return AVCaptureSessionPreset1920x1080
case .iframe960x540: return AVCaptureSessionPresetiFrame960x540
case .iframe1280x720: return AVCaptureSessionPresetiFrame1280x720
case .resolution3840x2160:
if #available(iOS 9.0, *) {
return AVCaptureSessionPreset3840x2160
}
else {
print("[SwiftyCam]: Resolution 3840x2160 not supported")
return AVCaptureSessionPresetPhoto
}
}
}
fileprivate class func deviceWithMediaType(_ mediaType: String, preferringPosition position: AVCaptureDevicePosition) -> AVCaptureDevice? {
if let devices = AVCaptureDevice.devices(withMediaType: mediaType) as? [AVCaptureDevice] {
return devices.filter({ $0.position == position }).first
}
return nil
}
fileprivate func enableFlash() {
if self.isCameraFlashOn == false {
toggleFlash()
}
}
fileprivate func disableFlash() {
if self.isCameraFlashOn == true {
toggleFlash()
}
}
}
extension SwiftyCamViewController : SwiftyCamButtonDelegate {
public func setMaxiumVideoDuration() -> Double {
return kMaximumVideoDuration
}
public func buttonWasTapped() {
takePhoto()
}
public func buttonDidBeginLongPress() {
startVideoRecording()
}
public func buttonDidEndLongPress() {
endVideoRecording()
}
public func longPressDidReachMaximumDuration() {
endVideoRecording()
}
}
extension SwiftyCamViewController : AVCaptureFileOutputRecordingDelegate {
public func capture(_ captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [Any]!, error: Error!) {
if let currentBackgroundRecordingID = backgroundRecordingID {
backgroundRecordingID = UIBackgroundTaskInvalid
if currentBackgroundRecordingID != UIBackgroundTaskInvalid {
UIApplication.shared.endBackgroundTask(currentBackgroundRecordingID)
}
}
if error != nil {
print("[SwiftyCam]: Movie file finishing error: \(error)")
} else {
self.cameraDelegate?.SwiftyCamDidFinishProcessingVideoAt(outputFileURL.path)
}
}
}
extension SwiftyCamViewController : UIGestureRecognizerDelegate {
public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer.isKind(of: UIPinchGestureRecognizer.self) {
beginZoomScale = zoomScale;
}
return true
}
}

View file

@ -0,0 +1,65 @@
/*Copyright (c) 2016, Andrew Walz.
Redistribution and use in source and binary forms, with or without modification,are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
import UIKit
public protocol SwiftyCamViewControllerDelegate {
func SwiftyCamDidTakePhoto(_ photo:UIImage)
func SwiftyCamDidBeginRecordingVideo()
func SwiftyCamDidFinishRecordingVideo()
func SwiftyCamDidFinishProcessingVideoAt(_ url: String)
func SwiftyCamDidSwitchCameras(camera: SwiftyCamViewController.CameraSelection)
func SwiftyCamDidFocusAtPoint(focusPoint: CGPoint)
func SwiftyCamDidChangeZoomLevel(zoomLevel: CGFloat)
func SwiftyCamDidFailCameraPermissionSettings()
}
public extension SwiftyCamViewControllerDelegate {
func SwiftyCamDidTakePhoto(_ photo:UIImage) {
// Optional
}
func SwiftyCamDidBeginRecordingVideo() {
// Optional
}
func SwiftyCamDidFinishRecordingVideo() {
// Optional
}
func SwiftyCamDidFinishProcessingVideoAt(_ url: String) {
// Optional
}
func SwiftyCamDidSwitchCameras(camera: SwiftyCamViewController.CameraSelection) {
// Optional
}
func SwiftyCamDidFocusAtPoint(focusPoint: CGPoint) {
// Optional
}
func SwiftyCamDidChangeZoomLevel(zoomLevel: CGFloat) {
// Optional
}
func SwiftyCamDidFailCameraPermissionSettings() {
// Optional
}
}

44
SwiftyCam.podspec Normal file
View file

@ -0,0 +1,44 @@
#
# Be sure to run `pod lib lint SwiftyCam.podspec' to ensure this is a
# valid spec before submitting.
#
# Any lines starting with a # are optional, but their use is encouraged
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#
Pod::Spec.new do |s|
s.name = 'SwiftyCam'
s.version = '1.0.0'
s.summary = 'A Simple, Snapchat-style camera Framework written in Swift'
s.ios.deployment_target = '8.0'
# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!
s.description = <<-DESC
A drop in Camera View Controller for capturing photos and videos from one AVSession. Written in Swift.
DESC
s.homepage = 'https://github.com/Awalz/SwiftyCam'
# s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
s.license = { :type => 'BSD', :file => 'LICENSE' }
s.author = { 'Andrew Walz' => 'andrewjwalz@gmail.com' }
s.source = { :git => 'https://github.com/Awalz/SwiftyCam.git', :tag => s.version.to_s }
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
s.ios.deployment_target = '8.0'
s.source_files = 'Source/**/*'
# s.resource_bundles = {
# 'SwiftyCam' => ['SwiftyCam/Assets/*.png']
# }
# s.public_header_files = 'Pod/Classes/**/*.h'
# s.frameworks = 'UIKit', 'MapKit'
# s.dependency 'AFNetworking', '~> 2.3'
end