diff --git a/README.md b/README.md index 3b79135..230d1d9 100644 --- a/README.md +++ b/README.md @@ -1 +1,32 @@ -# SwiftExceptionCatcher \ No newline at end of file +# SwiftExceptionCatcher + +[](https://RedRoma.tech) + +`SwiftExceptionCatcher` allows Swift Code to catch exceptions thrown from Objective-C code. + +This is useful when using Thrift libraries, where it is perfectly normal for code to throw `NSException` types. + + +# Cocoapods +```xml +pod 'SwiftExceptionCatcher', :git => 'https://github.com/RedRoma/SwiftExceptionCatcher.git' +``` + +# API +Simply wrap the code-in-play in the `tryOp` function call. + +```js +var object: SomeObjectThatThrows +... +do { + try tryOp() { object.act() } +} +catch let ex is AromaException { + print("Aroma Failed: \(ex") +} +catch let ex { + print("Exception: \(ex") +} + +``` diff --git a/SwiftExceptionCatcher.podspec b/SwiftExceptionCatcher.podspec new file mode 100644 index 0000000..d63053d --- /dev/null +++ b/SwiftExceptionCatcher.podspec @@ -0,0 +1,18 @@ +Pod::Spec.new do |spec| + spec.name = "SwiftExceptionCatcher" + spec.module_name = 'SwiftExceptionCatcher' + spec.version = "1.0" + spec.summary = "Catch NSException with Swift" + spec.homepage = "https://github.com/RedRoma/SwiftExceptionCatcher" + spec.license = "Code is Licensed under Apache 2.0" + spec.author = { "SirWellington" => "wellington@redroma.tech" } + spec.source = + { + :path => "SwiftExceptionCatcher/SwiftExceptionCatcher/" + } + spec.source_files = "SwiftExceptionCatcher/SwiftExceptionCatcher/*.{h,m,swift}" + # spec.resources = 'Pod/Assets/*' + + spec.platform = :ios, '8.0', :osx, '10.8' + spec.requires_arc = false +end diff --git a/SwiftExceptionCatcher/SwiftExceptionCatcher.xcodeproj/project.pbxproj b/SwiftExceptionCatcher/SwiftExceptionCatcher.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e085efc --- /dev/null +++ b/SwiftExceptionCatcher/SwiftExceptionCatcher.xcodeproj/project.pbxproj @@ -0,0 +1,433 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + DE683D8E1CB380180072F98A /* SwiftExceptionCatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = DE683D8D1CB380180072F98A /* SwiftExceptionCatcher.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DE683D951CB380180072F98A /* SwiftExceptionCatcher.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DE683D8A1CB380180072F98A /* SwiftExceptionCatcher.framework */; }; + DE683D9A1CB380180072F98A /* SwiftExceptionCatcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE683D991CB380180072F98A /* SwiftExceptionCatcherTests.swift */; }; + DE683DA81CB380320072F98A /* SwiftExceptionCatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = DE683DA51CB380320072F98A /* SwiftExceptionCatcher.m */; }; + DE683DA91CB380320072F98A /* SwiftExceptionCatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE683DA61CB380320072F98A /* SwiftExceptionCatcher.swift */; }; + DE683DAD1CB38EFB0072F98A /* Throwing.m in Sources */ = {isa = PBXBuildFile; fileRef = DE683DAC1CB38EFB0072F98A /* Throwing.m */; }; + DE683DAF1CB3902D0072F98A /* Throwing.h in Headers */ = {isa = PBXBuildFile; fileRef = DE683DAB1CB38EB80072F98A /* Throwing.h */; settings = {ATTRIBUTES = (Public, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + DE683D961CB380180072F98A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DE683D811CB380180072F98A /* Project object */; + proxyType = 1; + remoteGlobalIDString = DE683D891CB380180072F98A; + remoteInfo = SwiftExceptionCatcher; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + DE683D8A1CB380180072F98A /* SwiftExceptionCatcher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftExceptionCatcher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DE683D8D1CB380180072F98A /* SwiftExceptionCatcher.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftExceptionCatcher.h; sourceTree = ""; }; + DE683D8F1CB380180072F98A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DE683D941CB380180072F98A /* SwiftExceptionCatcherTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftExceptionCatcherTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + DE683D991CB380180072F98A /* SwiftExceptionCatcherTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftExceptionCatcherTests.swift; sourceTree = ""; }; + DE683D9B1CB380180072F98A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DE683DA51CB380320072F98A /* SwiftExceptionCatcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SwiftExceptionCatcher.m; sourceTree = ""; }; + DE683DA61CB380320072F98A /* SwiftExceptionCatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftExceptionCatcher.swift; sourceTree = ""; }; + DE683DAB1CB38EB80072F98A /* Throwing.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Throwing.h; sourceTree = ""; }; + DE683DAC1CB38EFB0072F98A /* Throwing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Throwing.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + DE683D861CB380180072F98A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE683D911CB380180072F98A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DE683D951CB380180072F98A /* SwiftExceptionCatcher.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + DE683D801CB380180072F98A = { + isa = PBXGroup; + children = ( + DE683D8C1CB380180072F98A /* SwiftExceptionCatcher */, + DE683D981CB380180072F98A /* SwiftExceptionCatcherTests */, + DE683D8B1CB380180072F98A /* Products */, + ); + sourceTree = ""; + }; + DE683D8B1CB380180072F98A /* Products */ = { + isa = PBXGroup; + children = ( + DE683D8A1CB380180072F98A /* SwiftExceptionCatcher.framework */, + DE683D941CB380180072F98A /* SwiftExceptionCatcherTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + DE683D8C1CB380180072F98A /* SwiftExceptionCatcher */ = { + isa = PBXGroup; + children = ( + DE683D8D1CB380180072F98A /* SwiftExceptionCatcher.h */, + DE683DA51CB380320072F98A /* SwiftExceptionCatcher.m */, + DE683DA61CB380320072F98A /* SwiftExceptionCatcher.swift */, + DE683D8F1CB380180072F98A /* Info.plist */, + ); + path = SwiftExceptionCatcher; + sourceTree = ""; + }; + DE683D981CB380180072F98A /* SwiftExceptionCatcherTests */ = { + isa = PBXGroup; + children = ( + DE683D991CB380180072F98A /* SwiftExceptionCatcherTests.swift */, + DE683D9B1CB380180072F98A /* Info.plist */, + DE683DAB1CB38EB80072F98A /* Throwing.h */, + DE683DAC1CB38EFB0072F98A /* Throwing.m */, + ); + path = SwiftExceptionCatcherTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + DE683D871CB380180072F98A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DE683D8E1CB380180072F98A /* SwiftExceptionCatcher.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE683DAE1CB390240072F98A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DE683DAF1CB3902D0072F98A /* Throwing.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + DE683D891CB380180072F98A /* SwiftExceptionCatcher */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE683D9E1CB380180072F98A /* Build configuration list for PBXNativeTarget "SwiftExceptionCatcher" */; + buildPhases = ( + DE683D851CB380180072F98A /* Sources */, + DE683D861CB380180072F98A /* Frameworks */, + DE683D871CB380180072F98A /* Headers */, + DE683D881CB380180072F98A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SwiftExceptionCatcher; + productName = SwiftExceptionCatcher; + productReference = DE683D8A1CB380180072F98A /* SwiftExceptionCatcher.framework */; + productType = "com.apple.product-type.framework"; + }; + DE683D931CB380180072F98A /* SwiftExceptionCatcherTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DE683DA11CB380180072F98A /* Build configuration list for PBXNativeTarget "SwiftExceptionCatcherTests" */; + buildPhases = ( + DE683D901CB380180072F98A /* Sources */, + DE683DAE1CB390240072F98A /* Headers */, + DE683D911CB380180072F98A /* Frameworks */, + DE683D921CB380180072F98A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DE683D971CB380180072F98A /* PBXTargetDependency */, + ); + name = SwiftExceptionCatcherTests; + productName = SwiftExceptionCatcherTests; + productReference = DE683D941CB380180072F98A /* SwiftExceptionCatcherTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + DE683D811CB380180072F98A /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0730; + LastUpgradeCheck = 0730; + ORGANIZATIONNAME = "RedRoma, Inc."; + TargetAttributes = { + DE683D891CB380180072F98A = { + CreatedOnToolsVersion = 7.3; + }; + DE683D931CB380180072F98A = { + CreatedOnToolsVersion = 7.3; + }; + }; + }; + buildConfigurationList = DE683D841CB380180072F98A /* Build configuration list for PBXProject "SwiftExceptionCatcher" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = DE683D801CB380180072F98A; + productRefGroup = DE683D8B1CB380180072F98A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + DE683D891CB380180072F98A /* SwiftExceptionCatcher */, + DE683D931CB380180072F98A /* SwiftExceptionCatcherTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + DE683D881CB380180072F98A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE683D921CB380180072F98A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + DE683D851CB380180072F98A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE683DA81CB380320072F98A /* SwiftExceptionCatcher.m in Sources */, + DE683DA91CB380320072F98A /* SwiftExceptionCatcher.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DE683D901CB380180072F98A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DE683D9A1CB380180072F98A /* SwiftExceptionCatcherTests.swift in Sources */, + DE683DAD1CB38EFB0072F98A /* Throwing.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + DE683D971CB380180072F98A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DE683D891CB380180072F98A /* SwiftExceptionCatcher */; + targetProxy = DE683D961CB380180072F98A /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + DE683D9C1CB380180072F98A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; + 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_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + 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 = 9.3; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + DE683D9D1CB380180072F98A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; + 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_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + 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 = 9.3; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DE683D9F1CB380180072F98A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; + CLANG_ENABLE_MODULES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; + INFOPLIST_FILE = SwiftExceptionCatcher/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = tech.redroma.SwiftExceptionCatcher; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + DE683DA01CB380180072F98A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; + CLANG_ENABLE_MODULES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; + INFOPLIST_FILE = SwiftExceptionCatcher/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = tech.redroma.SwiftExceptionCatcher; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + DE683DA21CB380180072F98A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; + CLANG_ENABLE_MODULES = YES; + INFOPLIST_FILE = SwiftExceptionCatcherTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = tech.redroma.SwiftExceptionCatcherTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = SwiftExceptionCatcherTests/Throwing.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + DE683DA31CB380180072F98A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; + CLANG_ENABLE_MODULES = YES; + INFOPLIST_FILE = SwiftExceptionCatcherTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = tech.redroma.SwiftExceptionCatcherTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = SwiftExceptionCatcherTests/Throwing.h; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + DE683D841CB380180072F98A /* Build configuration list for PBXProject "SwiftExceptionCatcher" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE683D9C1CB380180072F98A /* Debug */, + DE683D9D1CB380180072F98A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DE683D9E1CB380180072F98A /* Build configuration list for PBXNativeTarget "SwiftExceptionCatcher" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE683D9F1CB380180072F98A /* Debug */, + DE683DA01CB380180072F98A /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + DE683DA11CB380180072F98A /* Build configuration list for PBXNativeTarget "SwiftExceptionCatcherTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE683DA21CB380180072F98A /* Debug */, + DE683DA31CB380180072F98A /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = DE683D811CB380180072F98A /* Project object */; +} diff --git a/SwiftExceptionCatcher/SwiftExceptionCatcher.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/SwiftExceptionCatcher/SwiftExceptionCatcher.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..2660e47 --- /dev/null +++ b/SwiftExceptionCatcher/SwiftExceptionCatcher.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/SwiftExceptionCatcher/SwiftExceptionCatcher/Info.plist b/SwiftExceptionCatcher/SwiftExceptionCatcher/Info.plist new file mode 100644 index 0000000..d3de8ee --- /dev/null +++ b/SwiftExceptionCatcher/SwiftExceptionCatcher/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/SwiftExceptionCatcher/SwiftExceptionCatcher/SwiftExceptionCatcher.h b/SwiftExceptionCatcher/SwiftExceptionCatcher/SwiftExceptionCatcher.h new file mode 100644 index 0000000..59ee724 --- /dev/null +++ b/SwiftExceptionCatcher/SwiftExceptionCatcher/SwiftExceptionCatcher.h @@ -0,0 +1,26 @@ +// +// SwiftExceptionCatcher.h +// SwiftExceptionCatcher +// +// Created by Juan Wellington Moreno on 4/4/16. +// Copyright © 2016 RedRoma, Inc. All rights reserved. +// + +#ifndef SwiftExceptionCatcher +#define SwiftExceptionCatcher + +#import +#import + +//! Project version number for SwiftExceptionCatcher. +FOUNDATION_EXPORT double SwiftExceptionCatcherVersionNumber; + +//! Project version string for SwiftExceptionCatcher. +FOUNDATION_EXPORT const unsigned char SwiftExceptionCatcherVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + +void tryOperation(void(^tryBlock)(), void(^catchBlock)(NSException *e)); + +#endif \ No newline at end of file diff --git a/SwiftExceptionCatcher/SwiftExceptionCatcher/SwiftExceptionCatcher.m b/SwiftExceptionCatcher/SwiftExceptionCatcher/SwiftExceptionCatcher.m new file mode 100644 index 0000000..4e3ec24 --- /dev/null +++ b/SwiftExceptionCatcher/SwiftExceptionCatcher/SwiftExceptionCatcher.m @@ -0,0 +1,20 @@ +// +// TryOperation.m +// SwiftExceptionCatcher +// +// Created by Juan Wellington Moreno on 4/4/16. +// Copyright © 2016 RedRoma, Inc. All rights reserved. +// + +#import +#import "SwiftExceptionCatcher.h" + +void tryOperation(void (^tryBlock)(), void(^catchBlock)(NSException *e)) { + + @try { + tryBlock(); + } + @catch (NSException *exception) { + catchBlock(exception); + } +} diff --git a/SwiftExceptionCatcher/SwiftExceptionCatcher/SwiftExceptionCatcher.swift b/SwiftExceptionCatcher/SwiftExceptionCatcher/SwiftExceptionCatcher.swift new file mode 100644 index 0000000..c4c84a3 --- /dev/null +++ b/SwiftExceptionCatcher/SwiftExceptionCatcher/SwiftExceptionCatcher.swift @@ -0,0 +1,53 @@ +// +// TryOperation.swift +// SwiftExceptionCatcher +// +// Created by Juan Wellington Moreno on 4/4/16. +// Copyright © 2016 RedRoma, Inc. All rights reserved. +// + +import Foundation + + +/** + * This Extension adds the ability to catch NSException Types in Swift. + */ +extension NSException : ErrorType { + public var _domain: String { return "tech.redroma.SwiftExceptionCatcher" } + public var _code: Int { return 0 } +} + +/** + This class wraps Operations that may throw NSException types and catches them in a safe way + Primarily designed to overcome Swift's exception-handling limitations. + + - parameter operation: This operation may throw an Objective-C NSException type and must be safely wrapped. +*/ +public func tryOp(operation: (() throws -> T)) throws -> T { + + var result: T? + var error: NSException? + + let theTry: () -> () = { + do { + result = try operation() + } catch let ex { + error = ex as? NSException + } + return + } + + let theCatch: (NSException!) -> () = { ex in + error = ex + } + + tryOperation(theTry, theCatch) + + if let result = result { + return result + } else if let ex = error { + throw ex + } else { + throw NSException(name: "Unknown", reason: "Error Occured performing Operation", userInfo: nil) + } +} diff --git a/SwiftExceptionCatcher/SwiftExceptionCatcherTests/Info.plist b/SwiftExceptionCatcher/SwiftExceptionCatcherTests/Info.plist new file mode 100644 index 0000000..ba72822 --- /dev/null +++ b/SwiftExceptionCatcher/SwiftExceptionCatcherTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/SwiftExceptionCatcher/SwiftExceptionCatcherTests/SwiftExceptionCatcherTests.swift b/SwiftExceptionCatcher/SwiftExceptionCatcherTests/SwiftExceptionCatcherTests.swift new file mode 100644 index 0000000..a3c982c --- /dev/null +++ b/SwiftExceptionCatcher/SwiftExceptionCatcherTests/SwiftExceptionCatcherTests.swift @@ -0,0 +1,76 @@ +// +// SwiftExceptionCatcherTests.swift +// SwiftExceptionCatcherTests +// +// Created by Juan Wellington Moreno on 4/4/16. +// Copyright © 2016 RedRoma, Inc. All rights reserved. +// + +import XCTest +@testable import SwiftExceptionCatcher + +class SwiftExceptionCatcherTests: XCTestCase { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testWhenThrows() { + + do { + try tryOp() { + Throwing.functionThatThrows() + } + XCTFail("Expected Exception") + } + catch { + //Test Passed + } + } + + func testWhenNotThrows() { + do { + try tryOp() { Throwing.functionNotThrowing() } + } + catch let ex { + XCTFail("Unexpected Exception: \(ex)") + } + } + + func testWhenSwiftThrows() { + do { + try tryOp() { try self.somethingThatMightThrow(true) } + XCTFail("Expected Exception") + } + catch { + + } + } + + func testWhenSwiftNotThrows() { + do { + try tryOp() { try self.somethingThatMightThrow(false) } + } + catch let ex { + XCTFail("Unexpected Exception: \(ex)") + } + } + + + private func somethingThatMightThrow(shouldThrow: Bool = true) throws { + + if shouldThrow { + throw NSException(name: "Test", reason: "Because", userInfo: nil) + } + else { + print("Not Throwing") + } + } + +} diff --git a/SwiftExceptionCatcher/SwiftExceptionCatcherTests/Throwing.h b/SwiftExceptionCatcher/SwiftExceptionCatcherTests/Throwing.h new file mode 100644 index 0000000..aba57b4 --- /dev/null +++ b/SwiftExceptionCatcher/SwiftExceptionCatcherTests/Throwing.h @@ -0,0 +1,23 @@ +// +// Throwing.h +// SwiftExceptionCatcher +// +// Created by Juan Wellington Moreno on 4/4/16. +// Copyright © 2016 RedRoma, Inc. All rights reserved. +// + +#ifndef Throwing_h +#define Throwing_h + +#import + +@interface Throwing : NSObject + ++ (void) functionThatThrows; + ++ (void) functionNotThrowing; + + +@end + +#endif /* Throwing_h */ diff --git a/SwiftExceptionCatcher/SwiftExceptionCatcherTests/Throwing.m b/SwiftExceptionCatcher/SwiftExceptionCatcherTests/Throwing.m new file mode 100644 index 0000000..417486c --- /dev/null +++ b/SwiftExceptionCatcher/SwiftExceptionCatcherTests/Throwing.m @@ -0,0 +1,24 @@ +// +// Throwing.m +// SwiftExceptionCatcher +// +// Created by Juan Wellington Moreno on 4/4/16. +// Copyright © 2016 RedRoma, Inc. All rights reserved. +// + +#import +#import "Throwing.h" + +@implementation Throwing + ++ (void) functionThatThrows +{ + @throw [NSException exceptionWithName:@"Test" reason:@"" userInfo:nil]; +} + ++ (void) functionNotThrowing +{ + +} + +@end \ No newline at end of file